diff options
347 files changed, 8439 insertions, 4832 deletions
diff --git a/Android.mk b/Android.mk index 6ec434cfbf54..b49d0793802c 100644 --- a/Android.mk +++ b/Android.mk @@ -215,6 +215,7 @@ LOCAL_SRC_FILES += \ core/java/android/os/IBatteryPropertiesRegistrar.aidl \ core/java/android/os/ICancellationSignal.aidl \ core/java/android/os/IDeviceIdleController.aidl \ + core/java/android/os/IHardwarePropertiesManager.aidl \ core/java/android/os/IMaintenanceActivityListener.aidl \ core/java/android/os/IMessenger.aidl \ core/java/android/os/INetworkActivityListener.aidl \ diff --git a/api/current.txt b/api/current.txt index 69eaa87d91f0..abc9e9a2b163 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4880,7 +4880,6 @@ package android.app { method public android.graphics.drawable.Icon getLargeIcon(); method public android.graphics.drawable.Icon getSmallIcon(); method public java.lang.String getSortKey(); - method public android.app.Notification.Topic getTopic(); method public void writeToParcel(android.os.Parcel, int); field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT; field public static final java.lang.String CATEGORY_ALARM = "alarm"; @@ -4944,7 +4943,6 @@ package android.app { field public static final int PRIORITY_MAX = 2; // 0x2 field public static final int PRIORITY_MIN = -2; // 0xfffffffe field public static final deprecated int STREAM_DEFAULT = -1; // 0xffffffff - field public static final java.lang.String TOPIC_DEFAULT = "system_default_topic"; field public static final int VISIBILITY_PRIVATE = 0; // 0x0 field public static final int VISIBILITY_PUBLIC = 1; // 0x1 field public static final int VISIBILITY_SECRET = -1; // 0xffffffff @@ -5096,7 +5094,6 @@ package android.app { method public android.app.Notification.Builder setSubText(java.lang.CharSequence); method public android.app.Notification.Builder setTicker(java.lang.CharSequence); method public deprecated android.app.Notification.Builder setTicker(java.lang.CharSequence, android.widget.RemoteViews); - method public android.app.Notification.Builder setTopic(android.app.Notification.Topic); method public android.app.Notification.Builder setUsesChronometer(boolean); method public android.app.Notification.Builder setVibrate(long[]); method public android.app.Notification.Builder setVisibility(int); @@ -5134,6 +5131,16 @@ package android.app { method public android.app.PendingIntent getReplyPendingIntent(); } + public static class Notification.DecoratedCustomViewStyle extends android.app.Notification.Style { + ctor public Notification.DecoratedCustomViewStyle(); + ctor public Notification.DecoratedCustomViewStyle(android.app.Notification.Builder); + } + + public static class Notification.DecoratedMediaCustomViewStyle extends android.app.Notification.MediaStyle { + ctor public Notification.DecoratedMediaCustomViewStyle(); + ctor public Notification.DecoratedMediaCustomViewStyle(android.app.Notification.Builder); + } + public static abstract interface Notification.Extender { method public abstract android.app.Notification.Builder extend(android.app.Notification.Builder); } @@ -5164,16 +5171,6 @@ package android.app { field protected android.app.Notification.Builder mBuilder; } - public static class Notification.Topic implements android.os.Parcelable { - ctor public Notification.Topic(java.lang.String, java.lang.CharSequence); - method public android.app.Notification.Topic clone(); - method public int describeContents(); - method public java.lang.String getId(); - method public java.lang.CharSequence getLabel(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.app.Notification.Topic> CREATOR; - } - public static final class Notification.WearableExtender implements android.app.Notification.Extender { ctor public Notification.WearableExtender(); ctor public Notification.WearableExtender(android.app.Notification); @@ -5236,7 +5233,7 @@ package android.app { method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String); method public java.util.List<android.app.AutomaticZenRule> getAutomaticZenRules(); method public final int getCurrentInterruptionFilter(); - method public int getImportance(java.lang.String); + method public int getImportance(); method public android.app.NotificationManager.Policy getNotificationPolicy(); method public boolean isNotificationPolicyAccessGranted(); method public void notify(int, android.app.Notification); @@ -19167,9 +19164,9 @@ package android.location { method public double getDriftInNsPerSec(); method public double getDriftUncertaintyInNsPerSec(); method public long getFullBiasInNs(); + method public int getHardwareClockDiscontinuityCount(); method public short getLeapSecond(); method public long getTimeInNs(); - method public long getTimeOfLastHwClockDiscontinuityInNs(); method public double getTimeUncertaintyInNs(); method public byte getType(); method public boolean hasBiasInNs(); @@ -19193,9 +19190,9 @@ package android.location { method public void setDriftInNsPerSec(double); method public void setDriftUncertaintyInNsPerSec(double); method public void setFullBiasInNs(long); + method public void setHardwareClockDiscontinuityCount(int); method public void setLeapSecond(short); method public void setTimeInNs(long); - method public void setTimeOfLastHwClockDiscontinuityInNs(long); method public void setTimeUncertaintyInNs(double); method public void setType(byte); method public void writeToParcel(android.os.Parcel, int); @@ -19223,6 +19220,7 @@ package android.location { method public double getCn0InDbHz(); method public double getCodePhaseInChips(); method public double getCodePhaseUncertaintyInChips(); + method public byte getConstellationType(); method public double getDopplerShiftInHz(); method public double getDopplerShiftUncertaintyInHz(); method public double getElevationInDeg(); @@ -19230,13 +19228,11 @@ package android.location { method public byte getLossOfLock(); method public byte getMultipathIndicator(); method public double getPseudorangeInMeters(); - method public double getPseudorangeRateCarrierInMetersPerSec(); - method public double getPseudorangeRateCarrierUncertaintyInMetersPerSec(); method public double getPseudorangeRateInMetersPerSec(); method public double getPseudorangeRateUncertaintyInMetersPerSec(); method public double getPseudorangeUncertaintyInMeters(); - method public long getReceivedGpsTowInNs(); - method public long getReceivedGpsTowUncertaintyInNs(); + method public long getReceivedSvTimeInNs(); + method public long getReceivedSvTimeUncertaintyInNs(); method public double getSnrInDb(); method public short getState(); method public short getSvid(); @@ -19293,6 +19289,7 @@ package android.location { method public void setCn0InDbHz(double); method public void setCodePhaseInChips(double); method public void setCodePhaseUncertaintyInChips(double); + method public void setConstellationType(byte); method public void setDopplerShiftInHz(double); method public void setDopplerShiftUncertaintyInHz(double); method public void setElevationInDeg(double); @@ -19300,13 +19297,11 @@ package android.location { method public void setLossOfLock(byte); method public void setMultipathIndicator(byte); method public void setPseudorangeInMeters(double); - method public void setPseudorangeRateCarrierInMetersPerSec(double); - method public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double); method public void setPseudorangeRateInMetersPerSec(double); method public void setPseudorangeRateUncertaintyInMetersPerSec(double); method public void setPseudorangeUncertaintyInMeters(double); - method public void setReceivedGpsTowInNs(long); - method public void setReceivedGpsTowUncertaintyInNs(long); + method public void setReceivedSvTimeInNs(long); + method public void setReceivedSvTimeUncertaintyInNs(long); method public void setSnrInDb(double); method public void setState(short); method public void setSvid(short); @@ -19367,7 +19362,7 @@ package android.location { method public short getStatus(); method public short getSubmessageId(); method public short getSvid(); - method public byte getType(); + method public short getType(); method public void reset(); method public void set(android.location.GnssNavigationMessage); method public void setData(byte[]); @@ -19375,14 +19370,19 @@ package android.location { method public void setStatus(short); method public void setSubmessageId(short); method public void setSvid(short); - method public void setType(byte); + method public void setType(short); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR; - field public static final byte MESSAGE_TYPE_CNAV2 = 4; // 0x4 - field public static final byte MESSAGE_TYPE_L1CA = 1; // 0x1 - field public static final byte MESSAGE_TYPE_L2CNAV = 2; // 0x2 - field public static final byte MESSAGE_TYPE_L5CNAV = 3; // 0x3 - field public static final byte MESSAGE_TYPE_UNKNOWN = 0; // 0x0 + field public static final short MESSAGE_TYPE_BDS_D1 = 1281; // 0x501 + field public static final short MESSAGE_TYPE_BDS_D2 = 1282; // 0x502 + field public static final short MESSAGE_TYPE_GAL_F = 1538; // 0x602 + field public static final short MESSAGE_TYPE_GAL_I = 1537; // 0x601 + field public static final short MESSAGE_TYPE_GLO_L1CA = 769; // 0x301 + field public static final short MESSAGE_TYPE_GPS_CNAV2 = 260; // 0x104 + field public static final short MESSAGE_TYPE_GPS_L1CA = 257; // 0x101 + field public static final short MESSAGE_TYPE_GPS_L2CNAV = 258; // 0x102 + field public static final short MESSAGE_TYPE_GPS_L5CNAV = 259; // 0x103 + field public static final short MESSAGE_TYPE_UNKNOWN = 0; // 0x0 field public static final short STATUS_PARITY_PASSED = 1; // 0x1 field public static final short STATUS_PARITY_REBUILT = 2; // 0x2 field public static final short STATUS_UNKNOWN = 0; // 0x0 @@ -19417,7 +19417,7 @@ package android.location { public final class GnssStatus { method public float getAzimuth(int); - method public int getConstellationType(int); + method public byte getConstellationType(int); method public float getElevation(int); method public int getNumSatellites(); method public float getSnr(int); @@ -19425,13 +19425,16 @@ package android.location { method public boolean hasAlmanac(int); method public boolean hasEphemeris(int); method public boolean usedInFix(int); - field public static final int CONSTELLATION_BEIDOU = 5; // 0x5 - field public static final int CONSTELLATION_GALILEO = 6; // 0x6 - field public static final int CONSTELLATION_GLONASS = 3; // 0x3 - field public static final int CONSTELLATION_GPS = 1; // 0x1 - field public static final int CONSTELLATION_QZSS = 4; // 0x4 - field public static final int CONSTELLATION_SBAS = 2; // 0x2 - field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0 + field public static final byte CONSTELLATION_BEIDOU = 5; // 0x5 + field public static final byte CONSTELLATION_GALILEO = 6; // 0x6 + field public static final byte CONSTELLATION_GLONASS = 3; // 0x3 + field public static final byte CONSTELLATION_GPS = 1; // 0x1 + field public static final byte CONSTELLATION_QZSS = 4; // 0x4 + field public static final byte CONSTELLATION_SBAS = 2; // 0x2 + field public static final byte CONSTELLATION_UNKNOWN = 0; // 0x0 + } + + public static abstract class GnssStatus.ConstellationType implements java.lang.annotation.Annotation { } public abstract class GnssStatusCallback { @@ -20975,6 +20978,7 @@ package android.media { field public static final java.lang.String KEY_MAX_WIDTH = "max-width"; field public static final java.lang.String KEY_MIME = "mime"; field public static final java.lang.String KEY_OPERATING_RATE = "operating-rate"; + field public static final java.lang.String KEY_PCM_ENCODING = "pcm-encoding"; field public static final java.lang.String KEY_PRIORITY = "priority"; field public static final java.lang.String KEY_PROFILE = "profile"; field public static final java.lang.String KEY_PUSH_BLANK_BUFFERS_ON_STOP = "push-blank-buffers-on-shutdown"; @@ -22549,6 +22553,10 @@ package android.media.session { method public void playFromMediaId(java.lang.String, android.os.Bundle); method public void playFromSearch(java.lang.String, android.os.Bundle); method public void playFromUri(android.net.Uri, android.os.Bundle); + method public void prepare(); + method public void prepareFromMediaId(java.lang.String, android.os.Bundle); + method public void prepareFromSearch(java.lang.String, android.os.Bundle); + method public void prepareFromUri(android.net.Uri, android.os.Bundle); method public void rewind(); method public void seekTo(long); method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle); @@ -22582,7 +22590,6 @@ package android.media.session { method public void setRatingType(int); method public void setSessionActivity(android.app.PendingIntent); field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1 - field public static final int FLAG_HANDLES_PREPARE_ONLY = 4; // 0x4 field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2 } @@ -22597,6 +22604,10 @@ package android.media.session { method public void onPlayFromMediaId(java.lang.String, android.os.Bundle); method public void onPlayFromSearch(java.lang.String, android.os.Bundle); method public void onPlayFromUri(android.net.Uri, android.os.Bundle); + method public void onPrepare(); + method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle); + method public void onPrepareFromSearch(java.lang.String, android.os.Bundle); + method public void onPrepareFromUri(android.net.Uri, android.os.Bundle); method public void onRewind(); method public void onSeekTo(long); method public void onSetRating(android.media.Rating); @@ -22653,6 +22664,10 @@ package android.media.session { field public static final long ACTION_PLAY_FROM_SEARCH = 2048L; // 0x800L field public static final long ACTION_PLAY_FROM_URI = 8192L; // 0x2000L field public static final long ACTION_PLAY_PAUSE = 512L; // 0x200L + field public static final long ACTION_PREPARE = 16384L; // 0x4000L + field public static final long ACTION_PREPARE_FROM_MEDIA_ID = 32768L; // 0x8000L + field public static final long ACTION_PREPARE_FROM_SEARCH = 65536L; // 0x10000L + field public static final long ACTION_PREPARE_FROM_URI = 131072L; // 0x20000L field public static final long ACTION_REWIND = 8L; // 0x8L field public static final long ACTION_SEEK_TO = 256L; // 0x100L field public static final long ACTION_SET_RATING = 128L; // 0x80L @@ -22661,7 +22676,6 @@ package android.media.session { field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L field public static final long ACTION_STOP = 1L; // 0x1L field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR; - field public static final java.lang.String EXTRA_PREPARE_ONLY = "android.media.session.extra.PREPARE_ONLY"; field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL field public static final int STATE_BUFFERING = 6; // 0x6 field public static final int STATE_CONNECTING = 8; // 0x8 @@ -34591,6 +34605,7 @@ package android.service.quicksettings { method public final void startActivityAndCollapse(android.content.Intent); method public final void unlockAndRun(java.lang.Runnable); field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE"; + field public static final java.lang.String ACTION_QS_TILE_PREFERENCES = "android.service.quicksettings.action.QS_TILE_PREFERENCES"; field public static final int TILE_MODE_ACTIVE = 2; // 0x2 field public static final int TILE_MODE_PASSIVE = 1; // 0x1 } @@ -53058,7 +53073,7 @@ package java.nio.channels { ctor public ConnectionPendingException(); } - public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.ScatteringByteChannel { + public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.NetworkChannel java.nio.channels.ScatteringByteChannel { ctor protected DatagramChannel(java.nio.channels.spi.SelectorProvider); method public abstract java.nio.channels.DatagramChannel bind(java.net.SocketAddress) throws java.io.IOException; method public abstract java.nio.channels.DatagramChannel connect(java.net.SocketAddress) throws java.io.IOException; diff --git a/api/system-current.txt b/api/system-current.txt index 276fbd9858c1..b36d7e89cb8d 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5012,7 +5012,6 @@ package android.app { method public android.graphics.drawable.Icon getLargeIcon(); method public android.graphics.drawable.Icon getSmallIcon(); method public java.lang.String getSortKey(); - method public android.app.Notification.Topic getTopic(); method public void writeToParcel(android.os.Parcel, int); field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT; field public static final java.lang.String CATEGORY_ALARM = "alarm"; @@ -5076,7 +5075,6 @@ package android.app { field public static final int PRIORITY_MAX = 2; // 0x2 field public static final int PRIORITY_MIN = -2; // 0xfffffffe field public static final deprecated int STREAM_DEFAULT = -1; // 0xffffffff - field public static final java.lang.String TOPIC_DEFAULT = "system_default_topic"; field public static final int VISIBILITY_PRIVATE = 0; // 0x0 field public static final int VISIBILITY_PUBLIC = 1; // 0x1 field public static final int VISIBILITY_SECRET = -1; // 0xffffffff @@ -5228,7 +5226,6 @@ package android.app { method public android.app.Notification.Builder setSubText(java.lang.CharSequence); method public android.app.Notification.Builder setTicker(java.lang.CharSequence); method public deprecated android.app.Notification.Builder setTicker(java.lang.CharSequence, android.widget.RemoteViews); - method public android.app.Notification.Builder setTopic(android.app.Notification.Topic); method public android.app.Notification.Builder setUsesChronometer(boolean); method public android.app.Notification.Builder setVibrate(long[]); method public android.app.Notification.Builder setVisibility(int); @@ -5266,6 +5263,16 @@ package android.app { method public android.app.PendingIntent getReplyPendingIntent(); } + public static class Notification.DecoratedCustomViewStyle extends android.app.Notification.Style { + ctor public Notification.DecoratedCustomViewStyle(); + ctor public Notification.DecoratedCustomViewStyle(android.app.Notification.Builder); + } + + public static class Notification.DecoratedMediaCustomViewStyle extends android.app.Notification.MediaStyle { + ctor public Notification.DecoratedMediaCustomViewStyle(); + ctor public Notification.DecoratedMediaCustomViewStyle(android.app.Notification.Builder); + } + public static abstract interface Notification.Extender { method public abstract android.app.Notification.Builder extend(android.app.Notification.Builder); } @@ -5296,16 +5303,6 @@ package android.app { field protected android.app.Notification.Builder mBuilder; } - public static class Notification.Topic implements android.os.Parcelable { - ctor public Notification.Topic(java.lang.String, java.lang.CharSequence); - method public android.app.Notification.Topic clone(); - method public int describeContents(); - method public java.lang.String getId(); - method public java.lang.CharSequence getLabel(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.app.Notification.Topic> CREATOR; - } - public static final class Notification.WearableExtender implements android.app.Notification.Extender { ctor public Notification.WearableExtender(); ctor public Notification.WearableExtender(android.app.Notification); @@ -5368,7 +5365,7 @@ package android.app { method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String); method public java.util.List<android.app.AutomaticZenRule> getAutomaticZenRules(); method public final int getCurrentInterruptionFilter(); - method public int getImportance(java.lang.String); + method public int getImportance(); method public android.app.NotificationManager.Policy getNotificationPolicy(); method public boolean isNotificationPolicyAccessGranted(); method public void notify(int, android.app.Notification); @@ -20348,9 +20345,9 @@ package android.location { method public double getDriftInNsPerSec(); method public double getDriftUncertaintyInNsPerSec(); method public long getFullBiasInNs(); + method public int getHardwareClockDiscontinuityCount(); method public short getLeapSecond(); method public long getTimeInNs(); - method public long getTimeOfLastHwClockDiscontinuityInNs(); method public double getTimeUncertaintyInNs(); method public byte getType(); method public boolean hasBiasInNs(); @@ -20374,9 +20371,9 @@ package android.location { method public void setDriftInNsPerSec(double); method public void setDriftUncertaintyInNsPerSec(double); method public void setFullBiasInNs(long); + method public void setHardwareClockDiscontinuityCount(int); method public void setLeapSecond(short); method public void setTimeInNs(long); - method public void setTimeOfLastHwClockDiscontinuityInNs(long); method public void setTimeUncertaintyInNs(double); method public void setType(byte); method public void writeToParcel(android.os.Parcel, int); @@ -20404,6 +20401,7 @@ package android.location { method public double getCn0InDbHz(); method public double getCodePhaseInChips(); method public double getCodePhaseUncertaintyInChips(); + method public byte getConstellationType(); method public double getDopplerShiftInHz(); method public double getDopplerShiftUncertaintyInHz(); method public double getElevationInDeg(); @@ -20411,13 +20409,11 @@ package android.location { method public byte getLossOfLock(); method public byte getMultipathIndicator(); method public double getPseudorangeInMeters(); - method public double getPseudorangeRateCarrierInMetersPerSec(); - method public double getPseudorangeRateCarrierUncertaintyInMetersPerSec(); method public double getPseudorangeRateInMetersPerSec(); method public double getPseudorangeRateUncertaintyInMetersPerSec(); method public double getPseudorangeUncertaintyInMeters(); - method public long getReceivedGpsTowInNs(); - method public long getReceivedGpsTowUncertaintyInNs(); + method public long getReceivedSvTimeInNs(); + method public long getReceivedSvTimeUncertaintyInNs(); method public double getSnrInDb(); method public short getState(); method public short getSvid(); @@ -20474,6 +20470,7 @@ package android.location { method public void setCn0InDbHz(double); method public void setCodePhaseInChips(double); method public void setCodePhaseUncertaintyInChips(double); + method public void setConstellationType(byte); method public void setDopplerShiftInHz(double); method public void setDopplerShiftUncertaintyInHz(double); method public void setElevationInDeg(double); @@ -20481,13 +20478,11 @@ package android.location { method public void setLossOfLock(byte); method public void setMultipathIndicator(byte); method public void setPseudorangeInMeters(double); - method public void setPseudorangeRateCarrierInMetersPerSec(double); - method public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double); method public void setPseudorangeRateInMetersPerSec(double); method public void setPseudorangeRateUncertaintyInMetersPerSec(double); method public void setPseudorangeUncertaintyInMeters(double); - method public void setReceivedGpsTowInNs(long); - method public void setReceivedGpsTowUncertaintyInNs(long); + method public void setReceivedSvTimeInNs(long); + method public void setReceivedSvTimeUncertaintyInNs(long); method public void setSnrInDb(double); method public void setState(short); method public void setSvid(short); @@ -20548,7 +20543,7 @@ package android.location { method public short getStatus(); method public short getSubmessageId(); method public short getSvid(); - method public byte getType(); + method public short getType(); method public void reset(); method public void set(android.location.GnssNavigationMessage); method public void setData(byte[]); @@ -20556,14 +20551,19 @@ package android.location { method public void setStatus(short); method public void setSubmessageId(short); method public void setSvid(short); - method public void setType(byte); + method public void setType(short); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR; - field public static final byte MESSAGE_TYPE_CNAV2 = 4; // 0x4 - field public static final byte MESSAGE_TYPE_L1CA = 1; // 0x1 - field public static final byte MESSAGE_TYPE_L2CNAV = 2; // 0x2 - field public static final byte MESSAGE_TYPE_L5CNAV = 3; // 0x3 - field public static final byte MESSAGE_TYPE_UNKNOWN = 0; // 0x0 + field public static final short MESSAGE_TYPE_BDS_D1 = 1281; // 0x501 + field public static final short MESSAGE_TYPE_BDS_D2 = 1282; // 0x502 + field public static final short MESSAGE_TYPE_GAL_F = 1538; // 0x602 + field public static final short MESSAGE_TYPE_GAL_I = 1537; // 0x601 + field public static final short MESSAGE_TYPE_GLO_L1CA = 769; // 0x301 + field public static final short MESSAGE_TYPE_GPS_CNAV2 = 260; // 0x104 + field public static final short MESSAGE_TYPE_GPS_L1CA = 257; // 0x101 + field public static final short MESSAGE_TYPE_GPS_L2CNAV = 258; // 0x102 + field public static final short MESSAGE_TYPE_GPS_L5CNAV = 259; // 0x103 + field public static final short MESSAGE_TYPE_UNKNOWN = 0; // 0x0 field public static final short STATUS_PARITY_PASSED = 1; // 0x1 field public static final short STATUS_PARITY_REBUILT = 2; // 0x2 field public static final short STATUS_UNKNOWN = 0; // 0x0 @@ -20598,7 +20598,7 @@ package android.location { public final class GnssStatus { method public float getAzimuth(int); - method public int getConstellationType(int); + method public byte getConstellationType(int); method public float getElevation(int); method public int getNumSatellites(); method public float getSnr(int); @@ -20606,13 +20606,16 @@ package android.location { method public boolean hasAlmanac(int); method public boolean hasEphemeris(int); method public boolean usedInFix(int); - field public static final int CONSTELLATION_BEIDOU = 5; // 0x5 - field public static final int CONSTELLATION_GALILEO = 6; // 0x6 - field public static final int CONSTELLATION_GLONASS = 3; // 0x3 - field public static final int CONSTELLATION_GPS = 1; // 0x1 - field public static final int CONSTELLATION_QZSS = 4; // 0x4 - field public static final int CONSTELLATION_SBAS = 2; // 0x2 - field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0 + field public static final byte CONSTELLATION_BEIDOU = 5; // 0x5 + field public static final byte CONSTELLATION_GALILEO = 6; // 0x6 + field public static final byte CONSTELLATION_GLONASS = 3; // 0x3 + field public static final byte CONSTELLATION_GPS = 1; // 0x1 + field public static final byte CONSTELLATION_QZSS = 4; // 0x4 + field public static final byte CONSTELLATION_SBAS = 2; // 0x2 + field public static final byte CONSTELLATION_UNKNOWN = 0; // 0x0 + } + + public static abstract class GnssStatus.ConstellationType implements java.lang.annotation.Annotation { } public abstract class GnssStatusCallback { @@ -22475,6 +22478,7 @@ package android.media { field public static final java.lang.String KEY_MAX_WIDTH = "max-width"; field public static final java.lang.String KEY_MIME = "mime"; field public static final java.lang.String KEY_OPERATING_RATE = "operating-rate"; + field public static final java.lang.String KEY_PCM_ENCODING = "pcm-encoding"; field public static final java.lang.String KEY_PRIORITY = "priority"; field public static final java.lang.String KEY_PROFILE = "profile"; field public static final java.lang.String KEY_PUSH_BLANK_BUFFERS_ON_STOP = "push-blank-buffers-on-shutdown"; @@ -24122,6 +24126,10 @@ package android.media.session { method public void playFromMediaId(java.lang.String, android.os.Bundle); method public void playFromSearch(java.lang.String, android.os.Bundle); method public void playFromUri(android.net.Uri, android.os.Bundle); + method public void prepare(); + method public void prepareFromMediaId(java.lang.String, android.os.Bundle); + method public void prepareFromSearch(java.lang.String, android.os.Bundle); + method public void prepareFromUri(android.net.Uri, android.os.Bundle); method public void rewind(); method public void seekTo(long); method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle); @@ -24155,7 +24163,6 @@ package android.media.session { method public void setRatingType(int); method public void setSessionActivity(android.app.PendingIntent); field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1 - field public static final int FLAG_HANDLES_PREPARE_ONLY = 4; // 0x4 field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2 } @@ -24170,6 +24177,10 @@ package android.media.session { method public void onPlayFromMediaId(java.lang.String, android.os.Bundle); method public void onPlayFromSearch(java.lang.String, android.os.Bundle); method public void onPlayFromUri(android.net.Uri, android.os.Bundle); + method public void onPrepare(); + method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle); + method public void onPrepareFromSearch(java.lang.String, android.os.Bundle); + method public void onPrepareFromUri(android.net.Uri, android.os.Bundle); method public void onRewind(); method public void onSeekTo(long); method public void onSetRating(android.media.Rating); @@ -24226,6 +24237,10 @@ package android.media.session { field public static final long ACTION_PLAY_FROM_SEARCH = 2048L; // 0x800L field public static final long ACTION_PLAY_FROM_URI = 8192L; // 0x2000L field public static final long ACTION_PLAY_PAUSE = 512L; // 0x200L + field public static final long ACTION_PREPARE = 16384L; // 0x4000L + field public static final long ACTION_PREPARE_FROM_MEDIA_ID = 32768L; // 0x8000L + field public static final long ACTION_PREPARE_FROM_SEARCH = 65536L; // 0x10000L + field public static final long ACTION_PREPARE_FROM_URI = 131072L; // 0x20000L field public static final long ACTION_REWIND = 8L; // 0x8L field public static final long ACTION_SEEK_TO = 256L; // 0x100L field public static final long ACTION_SET_RATING = 128L; // 0x80L @@ -24234,7 +24249,6 @@ package android.media.session { field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L field public static final long ACTION_STOP = 1L; // 0x1L field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR; - field public static final java.lang.String EXTRA_PREPARE_ONLY = "android.media.session.extra.PREPARE_ONLY"; field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL field public static final int STATE_BUFFERING = 6; // 0x6 field public static final int STATE_CONNECTING = 8; // 0x8 @@ -36983,9 +36997,8 @@ package android.service.notification { field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb field public static final int REASON_PACKAGE_BANNED = 7; // 0x7 field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5 - field public static final int REASON_PACKAGE_SUSPENDED = 15; // 0xf - field public static final int REASON_PROFILE_TURNED_OFF = 16; // 0x10 - field public static final int REASON_TOPIC_BANNED = 14; // 0xe + field public static final int REASON_PACKAGE_SUSPENDED = 14; // 0xe + field public static final int REASON_PROFILE_TURNED_OFF = 15; // 0xf field public static final int REASON_USER_STOPPED = 6; // 0x6 field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService"; } @@ -37147,6 +37160,7 @@ package android.service.quicksettings { method public final void startActivityAndCollapse(android.content.Intent); method public final void unlockAndRun(java.lang.Runnable); field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE"; + field public static final java.lang.String ACTION_QS_TILE_PREFERENCES = "android.service.quicksettings.action.QS_TILE_PREFERENCES"; field public static final int TILE_MODE_ACTIVE = 2; // 0x2 field public static final int TILE_MODE_PASSIVE = 1; // 0x1 } @@ -48561,6 +48575,7 @@ package android.webkit { method public abstract void onConfigurationChanged(android.content.res.Configuration); method public abstract android.view.inputmethod.InputConnection onCreateInputConnection(android.view.inputmethod.EditorInfo); method public abstract void onDetachedFromWindow(); + method public abstract boolean onDragEvent(android.view.DragEvent); method public abstract void onDraw(android.graphics.Canvas); method public abstract void onDrawVerticalScrollBar(android.graphics.Canvas, android.graphics.drawable.Drawable, int, int, int, int); method public abstract void onFinishTemporaryDetach(); @@ -56154,7 +56169,7 @@ package java.nio.channels { ctor public ConnectionPendingException(); } - public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.ScatteringByteChannel { + public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.NetworkChannel java.nio.channels.ScatteringByteChannel { ctor protected DatagramChannel(java.nio.channels.spi.SelectorProvider); method public abstract java.nio.channels.DatagramChannel bind(java.net.SocketAddress) throws java.io.IOException; method public abstract java.nio.channels.DatagramChannel connect(java.net.SocketAddress) throws java.io.IOException; diff --git a/api/test-current.txt b/api/test-current.txt index 81c3f0bfd4d4..3878fbf25e31 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -4880,7 +4880,6 @@ package android.app { method public android.graphics.drawable.Icon getLargeIcon(); method public android.graphics.drawable.Icon getSmallIcon(); method public java.lang.String getSortKey(); - method public android.app.Notification.Topic getTopic(); method public void writeToParcel(android.os.Parcel, int); field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT; field public static final java.lang.String CATEGORY_ALARM = "alarm"; @@ -4944,7 +4943,6 @@ package android.app { field public static final int PRIORITY_MAX = 2; // 0x2 field public static final int PRIORITY_MIN = -2; // 0xfffffffe field public static final deprecated int STREAM_DEFAULT = -1; // 0xffffffff - field public static final java.lang.String TOPIC_DEFAULT = "system_default_topic"; field public static final int VISIBILITY_PRIVATE = 0; // 0x0 field public static final int VISIBILITY_PUBLIC = 1; // 0x1 field public static final int VISIBILITY_SECRET = -1; // 0xffffffff @@ -5096,7 +5094,6 @@ package android.app { method public android.app.Notification.Builder setSubText(java.lang.CharSequence); method public android.app.Notification.Builder setTicker(java.lang.CharSequence); method public deprecated android.app.Notification.Builder setTicker(java.lang.CharSequence, android.widget.RemoteViews); - method public android.app.Notification.Builder setTopic(android.app.Notification.Topic); method public android.app.Notification.Builder setUsesChronometer(boolean); method public android.app.Notification.Builder setVibrate(long[]); method public android.app.Notification.Builder setVisibility(int); @@ -5134,6 +5131,16 @@ package android.app { method public android.app.PendingIntent getReplyPendingIntent(); } + public static class Notification.DecoratedCustomViewStyle extends android.app.Notification.Style { + ctor public Notification.DecoratedCustomViewStyle(); + ctor public Notification.DecoratedCustomViewStyle(android.app.Notification.Builder); + } + + public static class Notification.DecoratedMediaCustomViewStyle extends android.app.Notification.MediaStyle { + ctor public Notification.DecoratedMediaCustomViewStyle(); + ctor public Notification.DecoratedMediaCustomViewStyle(android.app.Notification.Builder); + } + public static abstract interface Notification.Extender { method public abstract android.app.Notification.Builder extend(android.app.Notification.Builder); } @@ -5164,16 +5171,6 @@ package android.app { field protected android.app.Notification.Builder mBuilder; } - public static class Notification.Topic implements android.os.Parcelable { - ctor public Notification.Topic(java.lang.String, java.lang.CharSequence); - method public android.app.Notification.Topic clone(); - method public int describeContents(); - method public java.lang.String getId(); - method public java.lang.CharSequence getLabel(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.app.Notification.Topic> CREATOR; - } - public static final class Notification.WearableExtender implements android.app.Notification.Extender { ctor public Notification.WearableExtender(); ctor public Notification.WearableExtender(android.app.Notification); @@ -5236,7 +5233,7 @@ package android.app { method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String); method public java.util.List<android.app.AutomaticZenRule> getAutomaticZenRules(); method public final int getCurrentInterruptionFilter(); - method public int getImportance(java.lang.String); + method public int getImportance(); method public android.app.NotificationManager.Policy getNotificationPolicy(); method public boolean isNotificationPolicyAccessGranted(); method public void notify(int, android.app.Notification); @@ -19175,9 +19172,9 @@ package android.location { method public double getDriftInNsPerSec(); method public double getDriftUncertaintyInNsPerSec(); method public long getFullBiasInNs(); + method public int getHardwareClockDiscontinuityCount(); method public short getLeapSecond(); method public long getTimeInNs(); - method public long getTimeOfLastHwClockDiscontinuityInNs(); method public double getTimeUncertaintyInNs(); method public byte getType(); method public boolean hasBiasInNs(); @@ -19201,9 +19198,9 @@ package android.location { method public void setDriftInNsPerSec(double); method public void setDriftUncertaintyInNsPerSec(double); method public void setFullBiasInNs(long); + method public void setHardwareClockDiscontinuityCount(int); method public void setLeapSecond(short); method public void setTimeInNs(long); - method public void setTimeOfLastHwClockDiscontinuityInNs(long); method public void setTimeUncertaintyInNs(double); method public void setType(byte); method public void writeToParcel(android.os.Parcel, int); @@ -19231,6 +19228,7 @@ package android.location { method public double getCn0InDbHz(); method public double getCodePhaseInChips(); method public double getCodePhaseUncertaintyInChips(); + method public byte getConstellationType(); method public double getDopplerShiftInHz(); method public double getDopplerShiftUncertaintyInHz(); method public double getElevationInDeg(); @@ -19238,13 +19236,11 @@ package android.location { method public byte getLossOfLock(); method public byte getMultipathIndicator(); method public double getPseudorangeInMeters(); - method public double getPseudorangeRateCarrierInMetersPerSec(); - method public double getPseudorangeRateCarrierUncertaintyInMetersPerSec(); method public double getPseudorangeRateInMetersPerSec(); method public double getPseudorangeRateUncertaintyInMetersPerSec(); method public double getPseudorangeUncertaintyInMeters(); - method public long getReceivedGpsTowInNs(); - method public long getReceivedGpsTowUncertaintyInNs(); + method public long getReceivedSvTimeInNs(); + method public long getReceivedSvTimeUncertaintyInNs(); method public double getSnrInDb(); method public short getState(); method public short getSvid(); @@ -19301,6 +19297,7 @@ package android.location { method public void setCn0InDbHz(double); method public void setCodePhaseInChips(double); method public void setCodePhaseUncertaintyInChips(double); + method public void setConstellationType(byte); method public void setDopplerShiftInHz(double); method public void setDopplerShiftUncertaintyInHz(double); method public void setElevationInDeg(double); @@ -19308,13 +19305,11 @@ package android.location { method public void setLossOfLock(byte); method public void setMultipathIndicator(byte); method public void setPseudorangeInMeters(double); - method public void setPseudorangeRateCarrierInMetersPerSec(double); - method public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double); method public void setPseudorangeRateInMetersPerSec(double); method public void setPseudorangeRateUncertaintyInMetersPerSec(double); method public void setPseudorangeUncertaintyInMeters(double); - method public void setReceivedGpsTowInNs(long); - method public void setReceivedGpsTowUncertaintyInNs(long); + method public void setReceivedSvTimeInNs(long); + method public void setReceivedSvTimeUncertaintyInNs(long); method public void setSnrInDb(double); method public void setState(short); method public void setSvid(short); @@ -19375,7 +19370,7 @@ package android.location { method public short getStatus(); method public short getSubmessageId(); method public short getSvid(); - method public byte getType(); + method public short getType(); method public void reset(); method public void set(android.location.GnssNavigationMessage); method public void setData(byte[]); @@ -19383,14 +19378,19 @@ package android.location { method public void setStatus(short); method public void setSubmessageId(short); method public void setSvid(short); - method public void setType(byte); + method public void setType(short); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR; - field public static final byte MESSAGE_TYPE_CNAV2 = 4; // 0x4 - field public static final byte MESSAGE_TYPE_L1CA = 1; // 0x1 - field public static final byte MESSAGE_TYPE_L2CNAV = 2; // 0x2 - field public static final byte MESSAGE_TYPE_L5CNAV = 3; // 0x3 - field public static final byte MESSAGE_TYPE_UNKNOWN = 0; // 0x0 + field public static final short MESSAGE_TYPE_BDS_D1 = 1281; // 0x501 + field public static final short MESSAGE_TYPE_BDS_D2 = 1282; // 0x502 + field public static final short MESSAGE_TYPE_GAL_F = 1538; // 0x602 + field public static final short MESSAGE_TYPE_GAL_I = 1537; // 0x601 + field public static final short MESSAGE_TYPE_GLO_L1CA = 769; // 0x301 + field public static final short MESSAGE_TYPE_GPS_CNAV2 = 260; // 0x104 + field public static final short MESSAGE_TYPE_GPS_L1CA = 257; // 0x101 + field public static final short MESSAGE_TYPE_GPS_L2CNAV = 258; // 0x102 + field public static final short MESSAGE_TYPE_GPS_L5CNAV = 259; // 0x103 + field public static final short MESSAGE_TYPE_UNKNOWN = 0; // 0x0 field public static final short STATUS_PARITY_PASSED = 1; // 0x1 field public static final short STATUS_PARITY_REBUILT = 2; // 0x2 field public static final short STATUS_UNKNOWN = 0; // 0x0 @@ -19425,7 +19425,7 @@ package android.location { public final class GnssStatus { method public float getAzimuth(int); - method public int getConstellationType(int); + method public byte getConstellationType(int); method public float getElevation(int); method public int getNumSatellites(); method public float getSnr(int); @@ -19433,13 +19433,16 @@ package android.location { method public boolean hasAlmanac(int); method public boolean hasEphemeris(int); method public boolean usedInFix(int); - field public static final int CONSTELLATION_BEIDOU = 5; // 0x5 - field public static final int CONSTELLATION_GALILEO = 6; // 0x6 - field public static final int CONSTELLATION_GLONASS = 3; // 0x3 - field public static final int CONSTELLATION_GPS = 1; // 0x1 - field public static final int CONSTELLATION_QZSS = 4; // 0x4 - field public static final int CONSTELLATION_SBAS = 2; // 0x2 - field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0 + field public static final byte CONSTELLATION_BEIDOU = 5; // 0x5 + field public static final byte CONSTELLATION_GALILEO = 6; // 0x6 + field public static final byte CONSTELLATION_GLONASS = 3; // 0x3 + field public static final byte CONSTELLATION_GPS = 1; // 0x1 + field public static final byte CONSTELLATION_QZSS = 4; // 0x4 + field public static final byte CONSTELLATION_SBAS = 2; // 0x2 + field public static final byte CONSTELLATION_UNKNOWN = 0; // 0x0 + } + + public static abstract class GnssStatus.ConstellationType implements java.lang.annotation.Annotation { } public abstract class GnssStatusCallback { @@ -19545,8 +19548,8 @@ package android.location { method public void clearTestProviderStatus(java.lang.String); method public java.util.List<java.lang.String> getAllProviders(); method public java.lang.String getBestProvider(android.location.Criteria, boolean); + method public int getGnssYearOfHardware(); method public deprecated android.location.GpsStatus getGpsStatus(android.location.GpsStatus); - method public int getGpsYearOfHardware(); method public android.location.Location getLastKnownLocation(java.lang.String); method public android.location.LocationProvider getProvider(java.lang.String); method public java.util.List<java.lang.String> getProviders(boolean); @@ -20984,6 +20987,7 @@ package android.media { field public static final java.lang.String KEY_MAX_WIDTH = "max-width"; field public static final java.lang.String KEY_MIME = "mime"; field public static final java.lang.String KEY_OPERATING_RATE = "operating-rate"; + field public static final java.lang.String KEY_PCM_ENCODING = "pcm-encoding"; field public static final java.lang.String KEY_PRIORITY = "priority"; field public static final java.lang.String KEY_PROFILE = "profile"; field public static final java.lang.String KEY_PUSH_BLANK_BUFFERS_ON_STOP = "push-blank-buffers-on-shutdown"; @@ -22558,6 +22562,10 @@ package android.media.session { method public void playFromMediaId(java.lang.String, android.os.Bundle); method public void playFromSearch(java.lang.String, android.os.Bundle); method public void playFromUri(android.net.Uri, android.os.Bundle); + method public void prepare(); + method public void prepareFromMediaId(java.lang.String, android.os.Bundle); + method public void prepareFromSearch(java.lang.String, android.os.Bundle); + method public void prepareFromUri(android.net.Uri, android.os.Bundle); method public void rewind(); method public void seekTo(long); method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle); @@ -22591,7 +22599,6 @@ package android.media.session { method public void setRatingType(int); method public void setSessionActivity(android.app.PendingIntent); field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1 - field public static final int FLAG_HANDLES_PREPARE_ONLY = 4; // 0x4 field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2 } @@ -22606,6 +22613,10 @@ package android.media.session { method public void onPlayFromMediaId(java.lang.String, android.os.Bundle); method public void onPlayFromSearch(java.lang.String, android.os.Bundle); method public void onPlayFromUri(android.net.Uri, android.os.Bundle); + method public void onPrepare(); + method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle); + method public void onPrepareFromSearch(java.lang.String, android.os.Bundle); + method public void onPrepareFromUri(android.net.Uri, android.os.Bundle); method public void onRewind(); method public void onSeekTo(long); method public void onSetRating(android.media.Rating); @@ -22662,6 +22673,10 @@ package android.media.session { field public static final long ACTION_PLAY_FROM_SEARCH = 2048L; // 0x800L field public static final long ACTION_PLAY_FROM_URI = 8192L; // 0x2000L field public static final long ACTION_PLAY_PAUSE = 512L; // 0x200L + field public static final long ACTION_PREPARE = 16384L; // 0x4000L + field public static final long ACTION_PREPARE_FROM_MEDIA_ID = 32768L; // 0x8000L + field public static final long ACTION_PREPARE_FROM_SEARCH = 65536L; // 0x10000L + field public static final long ACTION_PREPARE_FROM_URI = 131072L; // 0x20000L field public static final long ACTION_REWIND = 8L; // 0x8L field public static final long ACTION_SEEK_TO = 256L; // 0x100L field public static final long ACTION_SET_RATING = 128L; // 0x80L @@ -22670,7 +22685,6 @@ package android.media.session { field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L field public static final long ACTION_STOP = 1L; // 0x1L field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR; - field public static final java.lang.String EXTRA_PREPARE_ONLY = "android.media.session.extra.PREPARE_ONLY"; field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL field public static final int STATE_BUFFERING = 6; // 0x6 field public static final int STATE_CONNECTING = 8; // 0x8 @@ -34606,6 +34620,7 @@ package android.service.quicksettings { method public final void startActivityAndCollapse(android.content.Intent); method public final void unlockAndRun(java.lang.Runnable); field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE"; + field public static final java.lang.String ACTION_QS_TILE_PREFERENCES = "android.service.quicksettings.action.QS_TILE_PREFERENCES"; field public static final int TILE_MODE_ACTIVE = 2; // 0x2 field public static final int TILE_MODE_PASSIVE = 1; // 0x1 } @@ -53075,7 +53090,7 @@ package java.nio.channels { ctor public ConnectionPendingException(); } - public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.ScatteringByteChannel { + public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.NetworkChannel java.nio.channels.ScatteringByteChannel { ctor protected DatagramChannel(java.nio.channels.spi.SelectorProvider); method public abstract java.nio.channels.DatagramChannel bind(java.net.SocketAddress) throws java.io.IOException; method public abstract java.nio.channels.DatagramChannel connect(java.net.SocketAddress) throws java.io.IOException; diff --git a/cmds/hid/jni/Android.mk b/cmds/hid/jni/Android.mk index 8163a9d764ff..d41d39d27f5b 100644 --- a/cmds/hid/jni/Android.mk +++ b/cmds/hid/jni/Android.mk @@ -18,6 +18,6 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_MODULE := libhidcommand_jni LOCAL_MODULE_TAGS := optional -LOCAL_CFLAGS += -Wall +LOCAL_CFLAGS += -Wall -Wextra -Werror include $(BUILD_SHARED_LIBRARY) diff --git a/cmds/hid/jni/com_android_commands_hid_Device.cpp b/cmds/hid/jni/com_android_commands_hid_Device.cpp index 4278e7d3ac12..1ea33ced7bbf 100644 --- a/cmds/hid/jni/com_android_commands_hid_Device.cpp +++ b/cmds/hid/jni/com_android_commands_hid_Device.cpp @@ -49,7 +49,7 @@ static struct { jmethodID onDeviceError; } gDeviceCallbackClassInfo; -static int handleLooperEvents(int fd, int events, void* data) { +static int handleLooperEvents(int /* fd */, int events, void* data) { Device* d = reinterpret_cast<Device*>(data); return d->handleEvents(events); } @@ -183,7 +183,7 @@ std::unique_ptr<uint8_t[]> getData(JNIEnv* env, jbyteArray javaArray, size_t& ou return data; } -static jlong openDevice(JNIEnv* env, jclass clazz, jstring rawName, jint id, jint vid, jint pid, +static jlong openDevice(JNIEnv* env, jclass /* clazz */, jstring rawName, jint id, jint vid, jint pid, jbyteArray rawDescriptor, jobject queue, jobject callback) { ScopedUtfChars name(env, rawName); if (name.c_str() == nullptr) { @@ -202,7 +202,7 @@ static jlong openDevice(JNIEnv* env, jclass clazz, jstring rawName, jint id, jin return reinterpret_cast<jlong>(d); } -static void sendReport(JNIEnv* env, jclass clazz, jlong ptr,jbyteArray rawReport) { +static void sendReport(JNIEnv* env, jclass /* clazz */, jlong ptr,jbyteArray rawReport) { size_t size; std::unique_ptr<uint8_t[]> report = getData(env, rawReport, size); uhid::Device* d = reinterpret_cast<uhid::Device*>(ptr); @@ -211,7 +211,7 @@ static void sendReport(JNIEnv* env, jclass clazz, jlong ptr,jbyteArray rawReport } } -static void closeDevice(JNIEnv* env, jclass clazz, jlong ptr) { +static void closeDevice(JNIEnv* /* env */, jclass /* clazz */, jlong ptr) { uhid::Device* d = reinterpret_cast<uhid::Device*>(ptr); if (d) { delete d; diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java index 980329fe31c8..3385a17002bc 100644 --- a/core/java/android/animation/AnimatorSet.java +++ b/core/java/android/animation/AnimatorSet.java @@ -807,6 +807,8 @@ public final class AnimatorSet extends Animator { } /** + * AnimatorSet is only reversible when the set contains no sequential animation, and no child + * animators have a start delay. * @hide */ @Override diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 04979ef7c18c..bb36a3e587b9 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1532,6 +1532,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case SET_LENIENT_BACKGROUND_CHECK_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + boolean enabled = data.readInt() != 0; + setLenientBackgroundCheck(enabled); + reply.writeNoException(); + return true; + } + case ENTER_SAFE_MODE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); enterSafeMode(); @@ -4855,6 +4863,17 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); reply.recycle(); } + public void setLenientBackgroundCheck(boolean enabled) throws RemoteException + { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeInt(enabled ? 1 : 0); + mRemote.transact(SET_LENIENT_BACKGROUND_CHECK_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } public void enterSafeMode() throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index f0453e9c45cc..93452fda1e1a 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -1265,6 +1265,14 @@ public class AppOpsManager { } /** @hide */ + public void setUserRestriction(int code, boolean restricted, IBinder token) { + try { + mService.setUserRestriction(code, restricted, token, mContext.getUserId()); + } catch (RemoteException e) { + } + } + + /** @hide */ public void setMode(int code, int uid, String packageName, int mode) { try { mService.setMode(code, uid, packageName, mode); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index ca86c18492d3..e4d6835a5d3e 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -307,6 +307,7 @@ public interface IActivityManager extends IInterface { public void setAlwaysFinish(boolean enabled) throws RemoteException; public void setActivityController(IActivityController watcher) throws RemoteException; + public void setLenientBackgroundCheck(boolean enabled) throws RemoteException; public void enterSafeMode() throws RemoteException; @@ -978,4 +979,5 @@ public interface IActivityManager extends IInterface { int SUPPORTS_LOCAL_VOICE_INTERACTION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 365; int NOTIFY_PINNED_STACK_ANIMATION_ENDED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 366; int REMOVE_STACK = IBinder.FIRST_CALL_TRANSACTION + 367; + int SET_LENIENT_BACKGROUND_CHECK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+368; } diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 3c8dfcea7282..8be00aa50ca3 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -48,16 +48,13 @@ interface INotificationManager boolean areNotificationsEnabledForPackage(String pkg, int uid); boolean areNotificationsEnabled(String pkg); - ParceledListSlice getTopics(String pkg, int uid); - void setVisibilityOverride(String pkg, int uid, in Notification.Topic topic, int visibility); - int getVisibilityOverride(String pkg, int uid, in Notification.Topic topic); - void setPriority(String pkg, int uid, in Notification.Topic topic, int priority); - int getPriority(String pkg, int uid, in Notification.Topic topic); - void setImportance(String pkg, int uid, in Notification.Topic topic, int importance); - int getImportance(String pkg, int uid, in Notification.Topic topic); - int getTopicImportance(String pkg, String topicId); - boolean doesUserUseTopics(String pkg, int uid); - boolean hasBannedTopics(String pkg, int uid); + void setVisibilityOverride(String pkg, int uid, int visibility); + int getVisibilityOverride(String pkg, int uid); + void setPriority(String pkg, int uid, int priority); + int getPriority(String pkg, int uid); + void setImportance(String pkg, int uid, int importance); + int getImportance(String pkg, int uid); + int getPackageImportance(String pkg); // TODO: Remove this when callers have been migrated to the equivalent // INotificationListener method. diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 52631d130e5c..402c112fdb63 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -895,6 +895,11 @@ public class Notification implements Parcelable */ public static final String EXTRA_BUILDER_APPLICATION_INFO = "android.appInfo"; + /** + * @hide + */ + public static final String EXTRA_CONTAINS_CUSTOM_VIEW = "android.contains.customView"; + private Icon mSmallIcon; private Icon mLargeIcon; @@ -1366,98 +1371,6 @@ public class Notification implements Parcelable public Notification publicVersion; /** - * Structure to encapsulate a topic that is shown in Notification settings. - * It must include an id and label. - */ - public static class Topic implements Parcelable { - private final String id; - private final CharSequence label; - - public Topic(String id, CharSequence label) { - this.id = id; - this.label = safeCharSequence(label); - } - - private Topic(Parcel in) { - if (in.readInt() != 0) { - id = in.readString(); - } else { - id = null; - } - label = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); - } - - public String getId() { - return id; - } - - public CharSequence getLabel() { - return label; - } - - @Override - public String toString() { - return new StringBuilder(Topic.class.getSimpleName()).append('[') - .append("id=").append(id) - .append(",label=").append(label) - .append(']').toString(); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof Topic)) return false; - if (o == this) return true; - final Topic other = (Topic) o; - return Objects.equals(other.id, id) - && Objects.equals(other.label, label); - } - - @Override - public int hashCode() { - return Objects.hash(id, label); - } - - @Override - public Topic clone() { - return new Topic(id, label); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - if (id != null) { - out.writeInt(1); - out.writeString(id); - } else { - out.writeInt(0); - } - TextUtils.writeToParcel(label, out, flags); - } - public static final Parcelable.Creator<Topic> CREATOR = - new Parcelable.Creator<Topic>() { - public Topic createFromParcel(Parcel in) { - return new Topic(in); - } - public Topic[] newArray(int size) { - return new Topic[size]; - } - }; - } - - @SystemApi - public static final String TOPIC_DEFAULT = "system_default_topic"; - - private Topic topic; - - public Topic getTopic() { - return topic; - } - - /** * Constructs a Notification object with default values. * You might want to consider using {@link Builder} instead. */ @@ -1583,10 +1496,6 @@ public class Notification implements Parcelable } color = parcel.readInt(); - - if (parcel.readInt() != 0) { - topic = Topic.CREATOR.createFromParcel(parcel); - } } @Override @@ -1687,10 +1596,6 @@ public class Notification implements Parcelable that.color = this.color; - if (this.topic != null) { - that.topic = this.topic.clone(); - } - if (!heavy) { that.lightenPayload(); // will clean out extras } @@ -1871,13 +1776,6 @@ public class Notification implements Parcelable } parcel.writeInt(color); - - if (topic != null) { - parcel.writeInt(1); - topic.writeToParcel(parcel, 0); - } else { - parcel.writeInt(0); - } } /** @@ -2020,10 +1918,6 @@ public class Notification implements Parcelable sb.append(" publicVersion="); sb.append(publicVersion.toString()); } - if (topic != null) { - sb.append("topic="); - sb.append(topic.toString()); - } sb.append(")"); return sb.toString(); } @@ -2995,19 +2889,6 @@ public class Notification implements Parcelable return this; } - /** - * Sets the topic of this notification. Topics are typically displayed in Notification - * settings. - * <p> - * Every topic must have an id and a textual label. - * - * @param topic The topic to add. - */ - public Builder setTopic(Topic topic) { - mN.topic = topic; - return this; - } - private Drawable getProfileBadgeDrawable() { // Note: This assumes that the current user can read the profile badge of the // originating user. @@ -3353,7 +3234,7 @@ public class Notification implements Parcelable * 3. Standard template view */ public RemoteViews makeContentView() { - if (mN.contentView != null) { + if (mN.contentView != null && (mStyle == null || !mStyle.displayCustomViewInline())) { return mN.contentView; } else if (mStyle != null) { final RemoteViews styleView = mStyle.makeContentView(); @@ -3369,7 +3250,8 @@ public class Notification implements Parcelable */ public RemoteViews makeBigContentView() { RemoteViews result = null; - if (mN.bigContentView != null) { + if (mN.bigContentView != null + && (mStyle == null || !mStyle.displayCustomViewInline())) { return mN.bigContentView; } else if (mStyle != null) { result = mStyle.makeBigContentView(); @@ -3410,7 +3292,8 @@ public class Notification implements Parcelable * Construct a RemoteViews for the final heads-up notification layout. */ public RemoteViews makeHeadsUpContentView() { - if (mN.headsUpContentView != null) { + if (mN.headsUpContentView != null + && (mStyle == null || !mStyle.displayCustomViewInline())) { return mN.headsUpContentView; } else if (mStyle != null) { final RemoteViews styleView = mStyle.makeHeadsUpContentView(); @@ -3547,6 +3430,10 @@ public class Notification implements Parcelable mN.extras.putStringArray(EXTRA_PEOPLE, mPersonList.toArray(new String[mPersonList.size()])); } + if (mN.bigContentView != null || mN.contentView != null + || mN.headsUpContentView != null) { + mN.extras.putBoolean(EXTRA_CONTAINS_CUSTOM_VIEW, true); + } return mN; } @@ -3571,8 +3458,9 @@ public class Notification implements Parcelable } private static Class<? extends Style> getNotificationStyleClass(String templateClass) { - Class<? extends Style>[] classes = new Class[]{ - BigTextStyle.class, BigPictureStyle.class, InboxStyle.class, MediaStyle.class}; + Class<? extends Style>[] classes = new Class[] { + BigTextStyle.class, BigPictureStyle.class, InboxStyle.class, MediaStyle.class, + DecoratedCustomViewStyle.class, DecoratedMediaCustomViewStyle.class }; for (Class<? extends Style> innerClass : classes) { if (templateClass.equals(innerClass.getName())) { return innerClass; @@ -3877,6 +3765,14 @@ public class Notification implements Parcelable public boolean hasSummaryInHeader() { return true; } + + /** + * @hide + * @return Whether custom content views are displayed inline in the style + */ + public boolean displayCustomViewInline() { + return false; + } } /** @@ -4250,6 +4146,7 @@ public class Notification implements Parcelable final float density = mBuilder.mContext.getResources().getDisplayMetrics().density; int topPadding = (int) (5 * density); int bottomPadding = (int) (13 * density); + boolean first = true; while (i < mTexts.size() && i < rowIds.length) { CharSequence str = mTexts.get(i); if (str != null && !str.equals("")) { @@ -4261,23 +4158,26 @@ public class Notification implements Parcelable } contentView.setViewPadding(rowIds[i], 0, topPadding, 0, i == rowIds.length - 1 || i == mTexts.size() - 1 ? bottomPadding : 0); + handleInboxImageMargin(contentView, rowIds[i], first); + first = false; } i++; } - handleInboxImageMargin(contentView, rowIds[0]); return contentView; } - private void handleInboxImageMargin(RemoteViews contentView, int id) { - final int max = mBuilder.mN.extras.getInt(EXTRA_PROGRESS_MAX, 0); - final boolean ind = mBuilder.mN.extras.getBoolean(EXTRA_PROGRESS_INDETERMINATE); - boolean hasProgress = max != 0 || ind; + private void handleInboxImageMargin(RemoteViews contentView, int id, boolean first) { int endMargin = 0; - if (mTexts.size() > 0 && mBuilder.mN.mLargeIcon != null && !hasProgress) { - endMargin = mBuilder.mContext.getResources().getDimensionPixelSize( - R.dimen.notification_content_picture_margin); + if (first) { + final int max = mBuilder.mN.extras.getInt(EXTRA_PROGRESS_MAX, 0); + final boolean ind = mBuilder.mN.extras.getBoolean(EXTRA_PROGRESS_INDETERMINATE); + boolean hasProgress = max != 0 || ind; + if (mBuilder.mN.mLargeIcon != null && !hasProgress) { + endMargin = mBuilder.mContext.getResources().getDimensionPixelSize( + R.dimen.notification_content_picture_margin); + } } contentView.setViewLayoutMarginEnd(id, endMargin); } @@ -4460,13 +4360,11 @@ public class Notification implements Parcelable } handleImage(view); // handle the content margin - int endMargin; + int endMargin = mBuilder.mContext.getResources().getDimensionPixelSize( + R.dimen.notification_content_margin_end);; if (mBuilder.mN.mLargeIcon != null) { - endMargin = mBuilder.mContext.getResources().getDimensionPixelSize( - R.dimen.notification_content_picture_margin_media); - } else { - endMargin = mBuilder.mContext.getResources().getDimensionPixelSize( - R.dimen.notification_content_margin_end); + endMargin += mBuilder.mContext.getResources().getDimensionPixelSize( + R.dimen.notification_content_picture_margin); } view.setViewLayoutMarginEnd(R.id.notification_main_column, endMargin); return view; @@ -4513,6 +4411,214 @@ public class Notification implements Parcelable } } + /** + * Notification style for custom views that are decorated by the system + * + * <p>Instead of providing a notification that is completely custom, a developer can set this + * style and still obtain system decorations like the notification header with the expand + * affordance and actions. + * + * <p>Use {@link android.app.Notification.Builder#setCustomContentView(RemoteViews)}, + * {@link android.app.Notification.Builder#setCustomBigContentView(RemoteViews)} and + * {@link android.app.Notification.Builder#setCustomHeadsUpContentView(RemoteViews)} to set the + * corresponding custom views to display. + * + * To use this style with your Notification, feed it to + * {@link Notification.Builder#setStyle(android.app.Notification.Style)} like so: + * <pre class="prettyprint"> + * Notification noti = new Notification.Builder() + * .setSmallIcon(R.drawable.ic_stat_player) + * .setLargeIcon(albumArtBitmap)) + * .setCustomContentView(contentView); + * .setStyle(<b>new Notification.DecoratedCustomViewStyle()</b>) + * .build(); + * </pre> + */ + public static class DecoratedCustomViewStyle extends Style { + + public DecoratedCustomViewStyle() { + } + + public DecoratedCustomViewStyle(Builder builder) { + setBuilder(builder); + } + + /** + * @hide + */ + public boolean displayCustomViewInline() { + return true; + } + + /** + * @hide + */ + @Override + public RemoteViews makeContentView() { + return makeStandardTemplateWithCustomContent(mBuilder.mN.contentView); + } + + /** + * @hide + */ + @Override + public RemoteViews makeBigContentView() { + return makeDecoratedBigContentView(); + } + + /** + * @hide + */ + @Override + public RemoteViews makeHeadsUpContentView() { + return makeDecoratedHeadsUpContentView(); + } + + private RemoteViews makeDecoratedHeadsUpContentView() { + RemoteViews headsUpContentView = mBuilder.mN.headsUpContentView == null + ? mBuilder.mN.contentView + : mBuilder.mN.headsUpContentView; + if (mBuilder.mActions.size() == 0) { + return makeStandardTemplateWithCustomContent(headsUpContentView); + } + RemoteViews remoteViews = mBuilder.applyStandardTemplateWithActions( + mBuilder.getBigBaseLayoutResource()); + buildIntoRemoteViewContent(remoteViews, headsUpContentView); + return remoteViews; + } + + private RemoteViews makeStandardTemplateWithCustomContent(RemoteViews customContent) { + RemoteViews remoteViews = mBuilder.applyStandardTemplate( + mBuilder.getBaseLayoutResource()); + buildIntoRemoteViewContent(remoteViews, customContent); + return remoteViews; + } + + private RemoteViews makeDecoratedBigContentView() { + RemoteViews bigContentView = mBuilder.mN.bigContentView == null + ? mBuilder.mN.contentView + : mBuilder.mN.bigContentView; + if (mBuilder.mActions.size() == 0) { + return makeStandardTemplateWithCustomContent(bigContentView); + } + RemoteViews remoteViews = mBuilder.applyStandardTemplateWithActions( + mBuilder.getBigBaseLayoutResource()); + buildIntoRemoteViewContent(remoteViews, bigContentView); + return remoteViews; + } + + private void buildIntoRemoteViewContent(RemoteViews remoteViews, + RemoteViews customContent) { + remoteViews.removeAllViews(R.id.notification_main_column); + remoteViews.addView(R.id.notification_main_column, customContent); + // also update the end margin if there is an image + int endMargin = mBuilder.mContext.getResources().getDimensionPixelSize( + R.dimen.notification_content_margin_end); + if (mBuilder.mN.mLargeIcon != null) { + endMargin += mBuilder.mContext.getResources().getDimensionPixelSize( + R.dimen.notification_content_picture_margin); + } + remoteViews.setViewLayoutMarginEnd(R.id.notification_main_column, endMargin); + } + } + + /** + * Notification style for media custom views that are decorated by the system + * + * <p>Instead of providing a media notification that is completely custom, a developer can set + * this style and still obtain system decorations like the notification header with the expand + * affordance and actions. + * + * <p>Use {@link android.app.Notification.Builder#setCustomContentView(RemoteViews)}, + * {@link android.app.Notification.Builder#setCustomBigContentView(RemoteViews)} and + * {@link android.app.Notification.Builder#setCustomHeadsUpContentView(RemoteViews)} to set the + * corresponding custom views to display. + * + * To use this style with your Notification, feed it to + * {@link Notification.Builder#setStyle(android.app.Notification.Style)} like so: + * <pre class="prettyprint"> + * Notification noti = new Notification.Builder() + * .setSmallIcon(R.drawable.ic_stat_player) + * .setLargeIcon(albumArtBitmap)) + * .setCustomContentView(contentView); + * .setStyle(<b>new Notification.DecoratedMediaCustomViewStyle()</b> + * .setMediaSession(mySession)) + * .build(); + * </pre> + * + * @see android.app.Notification.DecoratedCustomViewStyle + * @see android.app.Notification.MediaStyle + */ + public static class DecoratedMediaCustomViewStyle extends MediaStyle { + + public DecoratedMediaCustomViewStyle() { + } + + public DecoratedMediaCustomViewStyle(Builder builder) { + setBuilder(builder); + } + + /** + * @hide + */ + public boolean displayCustomViewInline() { + return true; + } + + /** + * @hide + */ + @Override + public RemoteViews makeContentView() { + RemoteViews remoteViews = super.makeContentView(); + return buildIntoRemoteView(remoteViews, R.id.notification_content_container, + mBuilder.mN.contentView); + } + + /** + * @hide + */ + @Override + public RemoteViews makeBigContentView() { + RemoteViews customRemoteView = mBuilder.mN.bigContentView != null + ? mBuilder.mN.bigContentView + : mBuilder.mN.contentView; + return makeBigContentViewWithCustomContent(customRemoteView); + } + + private RemoteViews makeBigContentViewWithCustomContent(RemoteViews customRemoteView) { + RemoteViews remoteViews = super.makeBigContentView(); + if (remoteViews != null) { + return buildIntoRemoteView(remoteViews, R.id.notification_main_column, + customRemoteView); + } else if (customRemoteView != mBuilder.mN.contentView){ + remoteViews = super.makeContentView(); + return buildIntoRemoteView(remoteViews, R.id.notification_content_container, + customRemoteView); + } else { + return null; + } + } + + /** + * @hide + */ + @Override + public RemoteViews makeHeadsUpContentView() { + RemoteViews customRemoteView = mBuilder.mN.headsUpContentView != null + ? mBuilder.mN.headsUpContentView + : mBuilder.mN.contentView; + return makeBigContentViewWithCustomContent(customRemoteView); + } + + private RemoteViews buildIntoRemoteView(RemoteViews remoteViews, int id, + RemoteViews customContent) { + remoteViews.removeAllViews(id); + remoteViews.addView(id, customContent); + return remoteViews; + } + } + // When adding a new Style subclass here, don't forget to update // Builder.getNotificationStyleClass. diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index ff2cfd61cd12..324a0ab8fc0c 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -507,11 +507,10 @@ public class NotificationManager return false; } - public int getImportance(String topicId) { - Preconditions.checkNotNull(topicId); + public int getImportance() { INotificationManager service = getService(); try { - return service.getTopicImportance(mContext.getPackageName(), topicId); + return service.getPackageImportance(mContext.getPackageName()); } catch (RemoteException e) { } return NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED; diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java index c552cfc98677..c1180e25a0d3 100644 --- a/core/java/android/app/SharedPreferencesImpl.java +++ b/core/java/android/app/SharedPreferencesImpl.java @@ -87,20 +87,20 @@ final class SharedPreferencesImpl implements SharedPreferences { } new Thread("SharedPreferencesImpl-load") { public void run() { - synchronized (SharedPreferencesImpl.this) { - loadFromDiskLocked(); - } + loadFromDisk(); } }.start(); } - private void loadFromDiskLocked() { - if (mLoaded) { - return; - } - if (mBackupFile.exists()) { - mFile.delete(); - mBackupFile.renameTo(mFile); + private void loadFromDisk() { + synchronized (SharedPreferencesImpl.this) { + if (mLoaded) { + return; + } + if (mBackupFile.exists()) { + mFile.delete(); + mBackupFile.renameTo(mFile); + } } // Debugging @@ -118,27 +118,27 @@ final class SharedPreferencesImpl implements SharedPreferences { str = new BufferedInputStream( new FileInputStream(mFile), 16*1024); map = XmlUtils.readMapXml(str); - } catch (XmlPullParserException e) { - Log.w(TAG, "getSharedPreferences", e); - } catch (FileNotFoundException e) { - Log.w(TAG, "getSharedPreferences", e); - } catch (IOException e) { + } catch (XmlPullParserException | IOException e) { Log.w(TAG, "getSharedPreferences", e); } finally { IoUtils.closeQuietly(str); } } } catch (ErrnoException e) { + /* ignore */ } - mLoaded = true; - if (map != null) { - mMap = map; - mStatTimestamp = stat.st_mtime; - mStatSize = stat.st_size; - } else { - mMap = new HashMap<String, Object>(); + + synchronized (SharedPreferencesImpl.this) { + mLoaded = true; + if (map != null) { + mMap = map; + mStatTimestamp = stat.st_mtime; + mStatSize = stat.st_size; + } else { + mMap = new HashMap<>(); + } + notifyAll(); } - notifyAll(); } static File makeBackupFile(File prefsFile) { diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 5eed781d76c3..52fba3b7b840 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -89,6 +89,7 @@ import android.os.BatteryManager; import android.os.DropBoxManager; import android.os.HardwarePropertiesManager; import android.os.IBinder; +import android.os.IHardwarePropertiesManager; import android.os.IPowerManager; import android.os.IUserManager; import android.os.PowerManager; @@ -715,7 +716,14 @@ final class SystemServiceRegistry { new CachedServiceFetcher<HardwarePropertiesManager>() { @Override public HardwarePropertiesManager createService(ContextImpl ctx) { - return new HardwarePropertiesManager(); + IBinder b = ServiceManager.getService(Context.HARDWARE_PROPERTIES_SERVICE); + IHardwarePropertiesManager service = + IHardwarePropertiesManager.Stub.asInterface(b); + if (service == null) { + Log.wtf(TAG, "Failed to get hardwareproperties service."); + return null; + } + return new HardwarePropertiesManager(ctx, service); }}); registerService(Context.SOUND_TRIGGER_SERVICE, SoundTriggerManager.class, diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 1875e6145dbd..c3512eca3b50 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -282,6 +282,10 @@ public class WallpaperManager { } public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault) { + return peekWallpaperBitmap(context, returnDefault, context.getUserId()); + } + + public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault, int userId) { synchronized (this) { if (mService != null) { try { @@ -300,7 +304,7 @@ public class WallpaperManager { } mWallpaper = null; try { - mWallpaper = getCurrentWallpaperLocked(context); + mWallpaper = getCurrentWallpaperLocked(userId); } catch (OutOfMemoryError e) { Log.w(TAG, "No memory load current wallpaper", e); } @@ -323,7 +327,7 @@ public class WallpaperManager { } } - private Bitmap getCurrentWallpaperLocked(Context context) { + private Bitmap getCurrentWallpaperLocked(int userId) { if (mService == null) { Log.w(TAG, "WallpaperService not running"); return null; @@ -332,7 +336,7 @@ public class WallpaperManager { try { Bundle params = new Bundle(); ParcelFileDescriptor fd = mService.getWallpaper(this, FLAG_SET_SYSTEM, - params, context.getUserId()); + params, userId); if (fd != null) { try { BitmapFactory.Options options = new BitmapFactory.Options(); @@ -644,7 +648,16 @@ public class WallpaperManager { * @hide */ public Bitmap getBitmap() { - return sGlobals.peekWallpaperBitmap(mContext, true); + return getBitmapAsUser(mContext.getUserId()); + } + + /** + * Like {@link #getDrawable()} but returns a Bitmap for the provided user. + * + * @hide + */ + public Bitmap getBitmapAsUser(int userId) { + return sGlobals.peekWallpaperBitmap(mContext, true, userId); } /** diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index aa697eadcbca..13ba6cc37d22 100644 --- a/core/java/android/hardware/display/DisplayManagerInternal.java +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -211,6 +211,9 @@ public abstract class DisplayManagerInternal { public int dozeScreenBrightness; public int dozeScreenState; + // If true, use twilight to affect the brightness. + public boolean useTwilight; + public DisplayPowerRequest() { policy = POLICY_BRIGHT; useProximitySensor = false; @@ -242,6 +245,7 @@ public abstract class DisplayManagerInternal { boostScreenBrightness = other.boostScreenBrightness; dozeScreenBrightness = other.dozeScreenBrightness; dozeScreenState = other.dozeScreenState; + useTwilight = other.useTwilight; } @Override @@ -262,7 +266,8 @@ public abstract class DisplayManagerInternal { && lowPowerMode == other.lowPowerMode && boostScreenBrightness == other.boostScreenBrightness && dozeScreenBrightness == other.dozeScreenBrightness - && dozeScreenState == other.dozeScreenState; + && dozeScreenState == other.dozeScreenState + && useTwilight == other.useTwilight; } @Override @@ -282,7 +287,8 @@ public abstract class DisplayManagerInternal { + ", lowPowerMode=" + lowPowerMode + ", boostScreenBrightness=" + boostScreenBrightness + ", dozeScreenBrightness=" + dozeScreenBrightness - + ", dozeScreenState=" + Display.stateToString(dozeScreenState); + + ", dozeScreenState=" + Display.stateToString(dozeScreenState) + + ", useTwilight=" + useTwilight; } public static String policyToString(int policy) { diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java index 4487cab9e182..c6d919f4d77e 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -57,90 +57,6 @@ public class NetworkUtils { public native static int resetConnections(String interfaceName, int mask); /** - * Start the DHCP client daemon, in order to have it request addresses - * for the named interface. This returns {@code true} if the DHCPv4 daemon - * starts, {@code false} otherwise. This call blocks until such time as a - * result is available or the default discovery timeout has been reached. - * Callers should check {@link #getDhcpResults} to determine whether DHCP - * succeeded or failed, and if it succeeded, to fetch the {@link DhcpResults}. - * @param interfaceName the name of the interface to configure - * @return {@code true} for success, {@code false} for failure - */ - public native static boolean startDhcp(String interfaceName); - - /** - * Initiate renewal on the DHCP client daemon for the named interface. This - * returns {@code true} if the DHCPv4 daemon has been notified, {@code false} - * otherwise. This call blocks until such time as a result is available or - * the default renew timeout has been reached. Callers should check - * {@link #getDhcpResults} to determine whether DHCP succeeded or failed, - * and if it succeeded, to fetch the {@link DhcpResults}. - * @param interfaceName the name of the interface to configure - * @return {@code true} for success, {@code false} for failure - */ - public native static boolean startDhcpRenew(String interfaceName); - - /** - * Start the DHCP client daemon, in order to have it request addresses - * for the named interface, and then configure the interface with those - * addresses. This call blocks until it obtains a result (either success - * or failure) from the daemon. - * @param interfaceName the name of the interface to configure - * @param dhcpResults if the request succeeds, this object is filled in with - * the IP address information. - * @return {@code true} for success, {@code false} for failure - */ - public static boolean runDhcp(String interfaceName, DhcpResults dhcpResults) { - return startDhcp(interfaceName) && getDhcpResults(interfaceName, dhcpResults); - } - - /** - * Initiate renewal on the DHCP client daemon. This call blocks until it obtains - * a result (either success or failure) from the daemon. - * @param interfaceName the name of the interface to configure - * @param dhcpResults if the request succeeds, this object is filled in with - * the IP address information. - * @return {@code true} for success, {@code false} for failure - */ - public static boolean runDhcpRenew(String interfaceName, DhcpResults dhcpResults) { - return startDhcpRenew(interfaceName) && getDhcpResults(interfaceName, dhcpResults); - } - - /** - * Fetch results from the DHCP client daemon. This call returns {@code true} if - * if there are results available to be read, {@code false} otherwise. - * @param interfaceName the name of the interface to configure - * @param dhcpResults if the request succeeds, this object is filled in with - * the IP address information. - * @return {@code true} for success, {@code false} for failure - */ - public native static boolean getDhcpResults(String interfaceName, DhcpResults dhcpResults); - - /** - * Shut down the DHCP client daemon. - * @param interfaceName the name of the interface for which the daemon - * should be stopped - * @return {@code true} for success, {@code false} for failure - */ - public native static boolean stopDhcp(String interfaceName); - - /** - * Release the current DHCP lease. - * @param interfaceName the name of the interface for which the lease should - * be released - * @return {@code true} for success, {@code false} for failure - */ - public native static boolean releaseDhcpLease(String interfaceName); - - /** - * Return the last DHCP-related error message that was recorded. - * <p/>NOTE: This string is not localized, but currently it is only - * used in logging. - * @return the most recent error message, if any - */ - public native static String getDhcpError(); - - /** * Attaches a socket filter that accepts DHCP packets to the given socket. */ public native static void attachDhcpFilter(FileDescriptor fd) throws SocketException; diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index b33e807235bf..a738b2e9bf61 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -2827,7 +2827,7 @@ public abstract class BatteryStats implements Parcelable { final long wifiOnTime = getWifiOnTime(rawRealtime, which); final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which); dumpLine(pw, 0 /* uid */, category, GLOBAL_WIFI_DATA, wifiOnTime / 1000, - wifiRunningTime / 1000, /* legacy fields follow, keep at 0 */ 0, 0, 0, 0); + wifiRunningTime / 1000, /* legacy fields follow, keep at 0 */ 0, 0, 0); dumpControllerActivityLine(pw, 0 /* uid */, category, GLOBAL_WIFI_CONTROLLER_DATA, getWifiControllerActivity(), which); diff --git a/core/java/android/os/CpuUsageInfo.aidl b/core/java/android/os/CpuUsageInfo.aidl new file mode 100644 index 000000000000..f81aefe4423f --- /dev/null +++ b/core/java/android/os/CpuUsageInfo.aidl @@ -0,0 +1,18 @@ +/* Copyright 2016, 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.os; + +parcelable CpuUsageInfo; diff --git a/core/java/android/os/HardwarePropertiesManager.java b/core/java/android/os/HardwarePropertiesManager.java index bc317b672d9c..c72a6481ebed 100644 --- a/core/java/android/os/HardwarePropertiesManager.java +++ b/core/java/android/os/HardwarePropertiesManager.java @@ -17,10 +17,12 @@ package android.os; import android.annotation.IntDef; import android.annotation.NonNull; +import android.content.Context; +import android.util.Log; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; - /** * The HardwarePropertiesManager class provides a mechanism of accessing hardware state of a * device: CPU, GPU and battery temperatures, CPU usage per core, fan speed, etc. @@ -29,11 +31,7 @@ public class HardwarePropertiesManager { private static final String TAG = HardwarePropertiesManager.class.getSimpleName(); - private static native void nativeInit(); - - private static native float[] nativeGetFanSpeeds(); - private static native float[] nativeGetDeviceTemperatures(int type); - private static native CpuUsageInfo[] nativeGetCpuUsages(); + private final IHardwarePropertiesManager mService; @Retention(RetentionPolicy.SOURCE) @IntDef({ @@ -54,9 +52,13 @@ public class HardwarePropertiesManager { /** Temperature of battery in Celsius. */ public static final int DEVICE_TEMPERATURE_BATTERY = 2; + /** Calling app context. */ + private final Context mContext; + /** @hide */ - public HardwarePropertiesManager() { - nativeInit(); + public HardwarePropertiesManager(Context context, IHardwarePropertiesManager service) { + mContext = context; + mService = service; } /** @@ -68,13 +70,19 @@ public class HardwarePropertiesManager { * Empty if platform doesn't provide the queried temperature. * * @throws IllegalArgumentException if an incorrect temperature type is queried. + * @throws SecurityException if a non profile or device owner tries to call this method. */ public @NonNull float[] getDeviceTemperatures(@DeviceTemperatureType int type) { switch (type) { case DEVICE_TEMPERATURE_CPU: case DEVICE_TEMPERATURE_GPU: case DEVICE_TEMPERATURE_BATTERY: - return nativeGetDeviceTemperatures(type); + try { + return mService.getDeviceTemperatures(mContext.getOpPackageName(), type); + } catch (RemoteException e) { + Log.w(TAG, "Could not get device temperatures", e); + return new float[0]; + } default: throw new IllegalArgumentException(); } @@ -85,18 +93,32 @@ public class HardwarePropertiesManager { * * @return an array of {@link android.os.CpuUsageInfo} for each core. * Empty if CPU usage is not supported on this system. + * + * @throws SecurityException if a non profile or device owner tries to call this method. */ public @NonNull CpuUsageInfo[] getCpuUsages() { - return nativeGetCpuUsages(); + try { + return mService.getCpuUsages(mContext.getOpPackageName()); + } catch (RemoteException e) { + Log.w(TAG, "Could not get CPU usages", e); + return new CpuUsageInfo[0]; + } } /** * Return an array of fan speeds in RPM. * - * @return an arrat of float fan speeds. Empty if there is no fans or fan speed - * not supported on this system. + * @return an array of float fan speeds in RPM. Empty if there are no fans or fan speed is not + * supported on this system. + * + * @throws SecurityException if a non profile or device owner tries to call this method. */ public @NonNull float[] getFanSpeeds() { - return nativeGetFanSpeeds(); + try { + return mService.getFanSpeeds(mContext.getOpPackageName()); + } catch (RemoteException e) { + Log.w(TAG, "Could not get fan speeds", e); + return new float[0]; + } } } diff --git a/core/java/android/os/IHardwarePropertiesManager.aidl b/core/java/android/os/IHardwarePropertiesManager.aidl new file mode 100644 index 000000000000..bcf0dc85a5e1 --- /dev/null +++ b/core/java/android/os/IHardwarePropertiesManager.aidl @@ -0,0 +1,28 @@ +/* +** +** Copyright 2016, 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.os; + +import android.os.CpuUsageInfo; + +/** @hide */ + +interface IHardwarePropertiesManager { + float[] getDeviceTemperatures(String callingPackage, int type); + CpuUsageInfo[] getCpuUsages(String callingPackage); + float[] getFanSpeeds(String callingPackage); +} diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index ec810502b4fa..770cde7053bc 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -114,6 +114,21 @@ public final class Settings { "android.settings.LOCATION_SOURCE_SETTINGS"; /** + * Activity Action: Show settings to allow configuration of users. + * <p> + * In some cases, a matching Activity may not exist, so ensure you + * safeguard against this. + * <p> + * Input: Nothing. + * <p> + * Output: Nothing. + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_USER_SETTINGS = + "android.settings.USER_SETTINGS"; + + /** * Activity Action: Show settings to allow configuration of wireless controls * such as Wi-Fi, Bluetooth and Mobile networks. * <p> @@ -5924,6 +5939,52 @@ public final class Settings { "camera_double_tap_power_gesture_disabled"; /** + + /** + * Behavior of twilight on the device. + * One of {@link #TWILIGHT_MODE_LOCKED_OFF}, {@link #TWILIGHT_MODE_LOCKED_ON} + * or {@link #TWILIGHT_MODE_AUTO}. + * @hide + */ + public static final String TWILIGHT_MODE = "twilight_mode"; + + /** + * Twilight mode always off. + * @hide + */ + public static final int TWILIGHT_MODE_LOCKED_OFF = 0; + + /** + * Twilight mode always on. + * @hide + */ + public static final int TWILIGHT_MODE_LOCKED_ON = 1; + + /** + * Twilight mode auto. + * @hide + */ + public static final int TWILIGHT_MODE_AUTO = 2; + + /** + * Twilight mode auto, temporarily overriden to on. + * @hide + */ + public static final int TWILIGHT_MODE_AUTO_OVERRIDE_OFF = 3; + + /** + * Twilight mode auto, temporarily overriden to off. + * @hide + */ + public static final int TWILIGHT_MODE_AUTO_OVERRIDE_ON = 4; + + /** + * Whether brightness should automatically adjust based on twilight state. + * @hide + */ + public static final String BRIGHTNESS_USE_TWILIGHT = "brightness_use_twilight"; + + /** * This are the settings to be backed up. * * NOTE: Settings are backed up and restored in the order they appear @@ -7783,13 +7844,20 @@ public final class Settings { public static final String LOW_POWER_MODE_TRIGGER_LEVEL = "low_power_trigger_level"; /** - * If 1, the activity manager will aggressively finish activities and + * If not 0, the activity manager will aggressively finish activities and * processes as soon as they are no longer needed. If 0, the normal * extended lifetime is used. */ public static final String ALWAYS_FINISH_ACTIVITIES = "always_finish_activities"; /** + * @hide + * If not 0, the activity manager will implement a looser version of background + * check that is more compatible with existing apps. + */ + public static final String LENIENT_BACKGROUND_CHECK = "lenient_background_check"; + + /** * Use Dock audio output for media: * 0 = disabled * 1 = enabled diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java index fb58f4e519c3..b5387f14e40c 100644 --- a/core/java/android/service/notification/NotificationAssistantService.java +++ b/core/java/android/service/notification/NotificationAssistantService.java @@ -97,14 +97,11 @@ public abstract class NotificationAssistantService extends NotificationListenerS /** Notification was canceled because it was an invisible member of a group. */ public static final int REASON_GROUP_OPTIMIZATION = 13; - /** Notification was canceled by the user banning the topic. */ - public static final int REASON_TOPIC_BANNED = 14; - /** Notification was canceled by the device administrator suspending the package. */ - public static final int REASON_PACKAGE_SUSPENDED = 15; + public static final int REASON_PACKAGE_SUSPENDED = 14; /** Notification was canceled by the owning managed profile being turned off. */ - public static final int REASON_PROFILE_TURNED_OFF = 16; + public static final int REASON_PROFILE_TURNED_OFF = 15; public class Adjustment { int mImportance; diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java index 0cf1175f8bc5..553d539eafee 100644 --- a/core/java/android/service/quicksettings/TileService.java +++ b/core/java/android/service/quicksettings/TileService.java @@ -16,6 +16,8 @@ package android.service.quicksettings; import android.Manifest; +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.app.Dialog; import android.app.Service; @@ -74,6 +76,14 @@ import android.view.WindowManager; public class TileService extends Service { /** + * An activity that provides a user interface for adjusting TileService preferences. + * Optional but recommended for apps that implement a TileService. + */ + @SdkConstant(SdkConstantType.INTENT_CATEGORY) + public static final String ACTION_QS_TILE_PREFERENCES + = "android.service.quicksettings.action.QS_TILE_PREFERENCES"; + + /** * Action that identifies a Service as being a TileService. */ public static final String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE"; diff --git a/core/java/android/text/style/ReplacementSpan.java b/core/java/android/text/style/ReplacementSpan.java index 26c725faed15..07190b2f1d6a 100644 --- a/core/java/android/text/style/ReplacementSpan.java +++ b/core/java/android/text/style/ReplacementSpan.java @@ -16,18 +16,49 @@ package android.text.style; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.graphics.Paint; import android.graphics.Canvas; import android.text.TextPaint; public abstract class ReplacementSpan extends MetricAffectingSpan { - public abstract int getSize(Paint paint, CharSequence text, - int start, int end, - Paint.FontMetricsInt fm); - public abstract void draw(Canvas canvas, CharSequence text, - int start, int end, float x, - int top, int y, int bottom, Paint paint); + /** + * Returns the width of the span. Extending classes can set the height of the span by updating + * attributes of {@link android.graphics.Paint.FontMetricsInt}. If the span covers the whole + * text, and the height is not set, + * {@link #draw(Canvas, CharSequence, int, int, float, int, int, int, Paint)} will not be + * called for the span. + * + * @param paint Paint instance. + * @param text Current text. + * @param start Start character index for span. + * @param end End character index for span. + * @param fm Font metrics, can be null. + * @return Width of the span. + */ + public abstract int getSize(@NonNull Paint paint, CharSequence text, + @IntRange(from = 0) int start, @IntRange(from = 0) int end, + @Nullable Paint.FontMetricsInt fm); + + /** + * Draws the span into the canvas. + * + * @param canvas Canvas into which the span should be rendered. + * @param text Current text. + * @param start Start character index for span. + * @param end End character index for span. + * @param x Edge of the replacement closest to the leading margin. + * @param top Top of the line. + * @param y Baseline. + * @param bottom Bottom of the line. + * @param paint Paint instance. + */ + public abstract void draw(@NonNull Canvas canvas, CharSequence text, + @IntRange(from = 0) int start, @IntRange(from = 0) int end, float x, + int top, int y, int bottom, @NonNull Paint paint); /** * This method does nothing, since ReplacementSpans are measured diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java index 664c02a70771..c7b1d03b120b 100644 --- a/core/java/android/view/AccessibilityInteractionController.java +++ b/core/java/android/view/AccessibilityInteractionController.java @@ -1053,6 +1053,7 @@ final class AccessibilityInteractionController { private void prefetchPredecessorsOfVirtualNode(AccessibilityNodeInfo root, View providerHost, AccessibilityNodeProvider provider, List<AccessibilityNodeInfo> outInfos) { + final int initialResultSize = outInfos.size(); long parentNodeId = root.getParentNodeId(); int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(parentNodeId); while (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) { @@ -1071,6 +1072,12 @@ final class AccessibilityInteractionController { AccessibilityNodeProvider.HOST_VIEW_ID); } if (parent == null) { + // Going up the parent relation we found a null predecessor, + // so remove these disconnected nodes form the result. + final int currentResultSize = outInfos.size(); + for (int i = currentResultSize - 1; i >= initialResultSize; i--) { + outInfos.remove(i); + } // Couldn't obtain the parent, which means we have a // disconnected sub-tree. Abort prefetch immediately. return; diff --git a/core/java/android/view/IDockedStackListener.aidl b/core/java/android/view/IDockedStackListener.aidl index 77fa7e25f9df..cbc8dbdd1726 100644 --- a/core/java/android/view/IDockedStackListener.aidl +++ b/core/java/android/view/IDockedStackListener.aidl @@ -33,4 +33,13 @@ oneway interface IDockedStackListener { * Called when the docked stack gets created or removed. */ void onDockedStackExistsChanged(boolean exists); + + /** + * Called when window manager decides to minimize the docked stack. The divider should make + * itself not interactable and shrink a bit in this state. + * + * @param minimized Whether the docked stack is currently minimized. + * @param animDuration The duration of the animation for changing the minimized state. + */ + void onDockedStackMinimizedChanged(boolean minimized, long animDuration); } diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java index 7017ff5a3fa0..a4cb7035f2f9 100644 --- a/core/java/android/view/RenderNode.java +++ b/core/java/android/view/RenderNode.java @@ -775,6 +775,10 @@ public class RenderNode { mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this); } + public boolean isAttached() { + return mOwningView != null && mOwningView.mAttachInfo != null; + } + public void addAnimator(AnimatedVectorDrawable.VectorDrawableAnimator animatorSet) { if (mOwningView == null || mOwningView.mAttachInfo == null) { throw new IllegalStateException("Cannot start this animator on a detached view!"); diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index ca41d7867feb..c97247656540 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -380,7 +380,7 @@ public final class ThreadedRenderer { void destroy() { mInitialized = false; updateEnabledState(null); - nDestroy(mNativeProxy); + nDestroy(mNativeProxy, mRootNode.mNativeRenderNode); } /** @@ -994,7 +994,7 @@ public final class ThreadedRenderer { float lightX, float lightY, float lightZ); private static native void nSetOpaque(long nativeProxy, boolean opaque); private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size); - private static native void nDestroy(long nativeProxy); + private static native void nDestroy(long nativeProxy, long rootRenderNode); private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode); private static native void nInvokeFunctor(long functor, boolean waitForCompletion); diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 609c471dfa18..a8b7a7b8a8db 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -631,7 +631,7 @@ public interface WindowManagerPolicy { /** * Return the display width available after excluding any screen - * decorations that can never be removed. That is, system bar or + * decorations that could never be removed in Honeycomb. That is, system bar or * button bar. */ public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, @@ -639,7 +639,7 @@ public interface WindowManagerPolicy { /** * Return the display height available after excluding any screen - * decorations that can never be removed. That is, system bar or + * decorations that could never be removed in Honeycomb. That is, system bar or * button bar. */ public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, @@ -1350,4 +1350,16 @@ public interface WindowManagerPolicy { */ public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight, Rect outInsets); + + /** + * Calculates the insets for the areas that could never be removed in Honeycomb, i.e. system + * bar or button bar. See {@link #getNonDecorDisplayWidth}. + * + * @param displayRotation the current display rotation + * @param displayWidth the current display width + * @param displayHeight the current display height + * @param outInsets the insets to return + */ + public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight, + Rect outInsets); } diff --git a/core/java/android/view/animation/ClipRectTBAnimation.java b/core/java/android/view/animation/ClipRectTBAnimation.java deleted file mode 100644 index 06f86ceda82f..000000000000 --- a/core/java/android/view/animation/ClipRectTBAnimation.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2015 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.animation; - -import android.graphics.Rect; - -/** - * Special case of ClipRectAnimation that animates only the top/bottom - * dimensions of the clip, picking up the other dimensions from whatever is - * set on the transform already. - * - * @hide - */ -public class ClipRectTBAnimation extends ClipRectAnimation { - - /** - * Constructor. Passes in 0 for Left/Right parameters of ClipRectAnimation - */ - public ClipRectTBAnimation(int fromT, int fromB, int toT, int toB) { - super(0, fromT, 0, fromB, 0, toT, 0, toB); - } - - /** - * Calculates and sets clip rect on given transformation. It uses existing values - * on the Transformation for Left/Right clip parameters. - */ - @Override - protected void applyTransformation(float it, Transformation tr) { - Rect oldClipRect = tr.getClipRect(); - tr.setClipRect(oldClipRect.left, mFromRect.top + (int) ((mToRect.top - mFromRect.top) * it), - oldClipRect.right, - mFromRect.bottom + (int) ((mToRect.bottom - mFromRect.bottom) * it)); - } - -} diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java index d97f8af28c3c..281babeb367a 100644 --- a/core/java/android/view/inputmethod/InputMethodInfo.java +++ b/core/java/android/view/inputmethod/InputMethodInfo.java @@ -428,18 +428,6 @@ public final class InputMethodInfo implements Parcelable { } } - /** - * @return {@code true} if the {@link android.inputmethodservice.InputMethodService} is marked - * to be Encryption-Aware. - * @hide - */ - public boolean isEncryptionAware() { - if (mService == null || mService.serviceInfo == null) { - return false; - } - return mService.serviceInfo.encryptionAware; - } - public void dump(Printer pw, String prefix) { pw.println(prefix + "mId=" + mId + " mSettingsActivityName=" + mSettingsActivityName diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 0f58ba3c002c..647d4dcbc347 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -39,6 +39,7 @@ import android.print.PrintDocumentAdapter; import android.security.KeyChain; import android.util.AttributeSet; import android.util.Log; +import android.view.DragEvent; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -2528,6 +2529,11 @@ public class WebView extends AbsoluteLayout } @Override + public boolean onDragEvent(DragEvent event) { + return mProvider.getViewDelegate().onDragEvent(event); + } + + @Override protected void onVisibilityChanged(View changedView, int visibility) { super.onVisibilityChanged(changedView, visibility); // This method may be called in the constructor chain, before the WebView provider is diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java index 3ce034cf24cb..94d231c45b98 100644 --- a/core/java/android/webkit/WebViewProvider.java +++ b/core/java/android/webkit/WebViewProvider.java @@ -30,6 +30,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.Message; import android.print.PrintDocumentAdapter; +import android.view.DragEvent; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -334,6 +335,8 @@ public interface WebViewProvider { public InputConnection onCreateInputConnection(EditorInfo outAttrs); + public boolean onDragEvent(DragEvent event); + public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event); public boolean onKeyDown(int keyCode, KeyEvent event); diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl index 9fa2c23dc953..b13be97dfb98 100644 --- a/core/java/com/android/internal/app/IAppOpsService.aidl +++ b/core/java/com/android/internal/app/IAppOpsService.aidl @@ -44,6 +44,7 @@ interface IAppOpsService { int checkAudioOperation(int code, int usage, int uid, String packageName); void setAudioRestriction(int code, int usage, int uid, int mode, in String[] exceptionPackages); - void setUserRestrictions(in Bundle restrictions, int userHandle); + void setUserRestrictions(in Bundle restrictions, IBinder token, int userHandle); + void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle); void removeUser(int userHandle); } diff --git a/core/java/com/android/internal/policy/DockedDividerUtils.java b/core/java/com/android/internal/policy/DockedDividerUtils.java index 00c65bd13e50..c68e50692c2a 100644 --- a/core/java/com/android/internal/policy/DockedDividerUtils.java +++ b/core/java/com/android/internal/policy/DockedDividerUtils.java @@ -17,9 +17,9 @@ package com.android.internal.policy; import android.graphics.Rect; -import android.view.WindowManager; import static android.view.WindowManager.DOCKED_BOTTOM; +import static android.view.WindowManager.DOCKED_INVALID; import static android.view.WindowManager.DOCKED_LEFT; import static android.view.WindowManager.DOCKED_RIGHT; import static android.view.WindowManager.DOCKED_TOP; @@ -35,46 +35,61 @@ public class DockedDividerUtils { int displayWidth, int displayHeight, int dividerSize) { outRect.set(0, 0, displayWidth, displayHeight); switch (dockSide) { - case WindowManager.DOCKED_LEFT: + case DOCKED_LEFT: outRect.right = position; break; - case WindowManager.DOCKED_TOP: + case DOCKED_TOP: outRect.bottom = position; break; - case WindowManager.DOCKED_RIGHT: + case DOCKED_RIGHT: outRect.left = position + dividerSize; break; - case WindowManager.DOCKED_BOTTOM: + case DOCKED_BOTTOM: outRect.top = position + dividerSize; break; } - sanitizeStackBounds(outRect); + sanitizeStackBounds(outRect, dockSide == DOCKED_LEFT || dockSide == DOCKED_TOP); } - public static void sanitizeStackBounds(Rect bounds) { - if (bounds.left >= bounds.right) { - bounds.left = bounds.right - 1; - } - if (bounds.top >= bounds.bottom) { - bounds.top = bounds.bottom - 1; - } - if (bounds.right <= bounds.left) { - bounds.right = bounds.left + 1; - } - if (bounds.bottom <= bounds.top) { - bounds.bottom = bounds.top + 1; + /** + * Makes sure that the bounds are always valid, i. e. they are at least one pixel high and wide. + * + * @param bounds The bounds to sanitize. + * @param topLeft Pass true if the bounds are at the top/left of the screen, false if they are + * at the bottom/right. This is used to determine in which direction to extend + * the bounds. + */ + public static void sanitizeStackBounds(Rect bounds, boolean topLeft) { + + // If the bounds are either on the top or left of the screen, rather move it further to the + // left/top to make it more offscreen. If they are on the bottom or right, push them off the + // screen by moving it even more to the bottom/right. + if (topLeft) { + if (bounds.left >= bounds.right) { + bounds.left = bounds.right - 1; + } + if (bounds.top >= bounds.bottom) { + bounds.top = bounds.bottom - 1; + } + } else { + if (bounds.right <= bounds.left) { + bounds.right = bounds.left + 1; + } + if (bounds.bottom <= bounds.top) { + bounds.bottom = bounds.top + 1; + } } } public static int calculatePositionForBounds(Rect bounds, int dockSide, int dividerSize) { switch (dockSide) { - case WindowManager.DOCKED_LEFT: + case DOCKED_LEFT: return bounds.right; - case WindowManager.DOCKED_TOP: + case DOCKED_TOP: return bounds.bottom; - case WindowManager.DOCKED_RIGHT: + case DOCKED_RIGHT: return bounds.left - dividerSize; - case WindowManager.DOCKED_BOTTOM: + case DOCKED_BOTTOM: return bounds.top - dividerSize; default: return 0; @@ -109,16 +124,16 @@ public class DockedDividerUtils { public static int invertDockSide(int dockSide) { switch (dockSide) { - case WindowManager.DOCKED_LEFT: - return WindowManager.DOCKED_RIGHT; - case WindowManager.DOCKED_TOP: - return WindowManager.DOCKED_BOTTOM; - case WindowManager.DOCKED_RIGHT: - return WindowManager.DOCKED_LEFT; - case WindowManager.DOCKED_BOTTOM: - return WindowManager.DOCKED_TOP; + case DOCKED_LEFT: + return DOCKED_RIGHT; + case DOCKED_TOP: + return DOCKED_BOTTOM; + case DOCKED_RIGHT: + return DOCKED_LEFT; + case DOCKED_BOTTOM: + return DOCKED_TOP; default: - return WindowManager.DOCKED_INVALID; + return DOCKED_INVALID; } } } diff --git a/core/java/com/android/internal/widget/MediaNotificationView.java b/core/java/com/android/internal/widget/MediaNotificationView.java index b45fd06c8a71..6bba1b3e1aec 100644 --- a/core/java/com/android/internal/widget/MediaNotificationView.java +++ b/core/java/com/android/internal/widget/MediaNotificationView.java @@ -21,6 +21,7 @@ import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; +import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.RemoteViews; @@ -31,16 +32,16 @@ import android.widget.RemoteViews; * @hide */ @RemoteViews.RemoteView -public class MediaNotificationView extends RelativeLayout { +public class MediaNotificationView extends FrameLayout { private final int mMaxImageSize; - private final int mImageMarginBottom; private final int mImageMinTopMargin; private final int mNotificationContentMarginEnd; private final int mNotificationContentImageMarginEnd; private ImageView mRightIcon; private View mActions; private View mHeader; + private View mMainColumn; public MediaNotificationView(Context context) { this(context, null); @@ -61,39 +62,49 @@ public class MediaNotificationView extends RelativeLayout { if (hasIcon && mode != MeasureSpec.UNSPECIFIED) { measureChild(mActions, widthMeasureSpec, heightMeasureSpec); int size = MeasureSpec.getSize(widthMeasureSpec); - int height = MeasureSpec.getSize(heightMeasureSpec); size = size - mActions.getMeasuredWidth(); ViewGroup.MarginLayoutParams layoutParams = (MarginLayoutParams) mRightIcon.getLayoutParams(); - size -= layoutParams.getMarginEnd(); + int imageEndMargin = layoutParams.getMarginEnd(); + size -= imageEndMargin; size = Math.min(size, mMaxImageSize); size = Math.max(size, mRightIcon.getMinimumWidth()); layoutParams.width = size; layoutParams.height = size; - // because we can't allign it to the bottom with a margin, we add a topmargin to it - layoutParams.topMargin = height - size - mImageMarginBottom; - // If the topMargin is high enough we can also remove the header constraint! - if (layoutParams.topMargin >= mImageMinTopMargin) { - resetHeaderIndention(); - } else { - int paddingEnd = mNotificationContentImageMarginEnd; - ViewGroup.MarginLayoutParams headerParams = - (MarginLayoutParams) mHeader.getLayoutParams(); - headerParams.setMarginEnd(size + layoutParams.getMarginEnd()); - if (mHeader.getPaddingEnd() != paddingEnd) { - mHeader.setPadding( - isLayoutRtl() ? paddingEnd : mHeader.getPaddingLeft(), - mHeader.getPaddingTop(), - isLayoutRtl() ? mHeader.getPaddingLeft() : paddingEnd, - mHeader.getPaddingBottom()); - mHeader.setLayoutParams(headerParams); - } - } mRightIcon.setLayoutParams(layoutParams); - } else if (!hasIcon && mHeader.getPaddingEnd() != mNotificationContentMarginEnd) { - resetHeaderIndention(); + + // lets ensure that the main column doesn't run into the image + ViewGroup.MarginLayoutParams mainParams + = (MarginLayoutParams) mMainColumn.getLayoutParams(); + int marginEnd = size + imageEndMargin + mNotificationContentMarginEnd; + if (marginEnd != mainParams.getMarginEnd()) { + mainParams.setMarginEnd(marginEnd); + mMainColumn.setLayoutParams(mainParams); + } + } super.onMeasure(widthMeasureSpec, heightMeasureSpec); + ViewGroup.MarginLayoutParams iconParams = + (MarginLayoutParams) mRightIcon.getLayoutParams(); + int topMargin = getMeasuredHeight() - mRightIcon.getMeasuredHeight() + - iconParams.bottomMargin; + // If the topMargin is high enough we can also remove the header constraint! + if (!hasIcon || topMargin >= mImageMinTopMargin) { + resetHeaderIndention(); + } else { + int paddingEnd = mNotificationContentImageMarginEnd; + ViewGroup.MarginLayoutParams headerParams = + (MarginLayoutParams) mHeader.getLayoutParams(); + headerParams.setMarginEnd(mRightIcon.getMeasuredWidth() + iconParams.getMarginEnd()); + if (mHeader.getPaddingEnd() != paddingEnd) { + mHeader.setPadding( + isLayoutRtl() ? paddingEnd : mHeader.getPaddingLeft(), + mHeader.getPaddingTop(), + isLayoutRtl() ? mHeader.getPaddingLeft() : paddingEnd, + mHeader.getPaddingBottom()); + mHeader.setLayoutParams(headerParams); + } + } } private void resetHeaderIndention() { @@ -115,8 +126,6 @@ public class MediaNotificationView extends RelativeLayout { super(context, attrs, defStyleAttr, defStyleRes); mMaxImageSize = context.getResources().getDimensionPixelSize( com.android.internal.R.dimen.media_notification_expanded_image_max_size); - mImageMarginBottom = context.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.media_notification_expanded_image_margin_bottom); mImageMinTopMargin = (int) (context.getResources().getDimensionPixelSize( com.android.internal.R.dimen.notification_content_margin_top) + getResources().getDisplayMetrics().density * 2); @@ -132,5 +141,6 @@ public class MediaNotificationView extends RelativeLayout { mRightIcon = (ImageView) findViewById(com.android.internal.R.id.right_icon); mActions = findViewById(com.android.internal.R.id.media_actions); mHeader = findViewById(com.android.internal.R.id.notification_header); + mMainColumn = findViewById(com.android.internal.R.id.notification_main_column); } } diff --git a/core/jni/Android.mk b/core/jni/Android.mk index 1b6b53ae49f4..8b686b70041d 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -177,8 +177,7 @@ LOCAL_SRC_FILES:= \ com_android_internal_net_NetworkStatsFactory.cpp \ com_android_internal_os_Zygote.cpp \ com_android_internal_util_VirtualRefBasePtr.cpp \ - com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp \ - android_os_HardwarePropertiesManager.cpp + com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 223fc1af46d5..017fb533723c 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -198,7 +198,6 @@ extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env extern int register_com_android_internal_net_NetworkStatsFactory(JNIEnv *env); extern int register_com_android_internal_os_Zygote(JNIEnv *env); extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env); -extern int register_android_os_HardwarePropertiesManager(JNIEnv *env); static AndroidRuntime* gCurRuntime = NULL; @@ -1390,7 +1389,6 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_animation_PropertyValuesHolder), REG_JNI(register_com_android_internal_content_NativeLibraryHelper), REG_JNI(register_com_android_internal_net_NetworkStatsFactory), - REG_JNI(register_android_os_HardwarePropertiesManager), }; diff --git a/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp b/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp index ae99f0bff330..731d22ada710 100644 --- a/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp +++ b/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp @@ -39,7 +39,6 @@ #include <SkPoint.h> #include <SkRect.h> #include <SkTypeface.h> -#include <SkUtils.h> #include <hb.h> @@ -82,17 +81,16 @@ static void SkiaGetGlyphWidthAndExtents(SkPaint* paint, hb_codepoint_t codepoint static hb_bool_t harfbuzzGetGlyph(hb_font_t* hbFont, void* fontData, hb_codepoint_t unicode, hb_codepoint_t variationSelector, hb_codepoint_t* glyph, void* userData) { HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData); + SkPaint* paint = hbFontData->m_paint; + paint->setTextEncoding(SkPaint::kUTF32_TextEncoding); if (unicode > 0x10ffff) { unicode = 0xfffd; } - SkPaint* paint = hbFontData->m_paint; - // It would be better to use kUTF32_TextEncoding directly - paint->setTextEncoding(SkPaint::kUTF16_TextEncoding); + SkUnichar unichar = unicode; + uint16_t glyph16; - uint16_t unichar[2]; - size_t size = SkUTF16_FromUnichar(unicode, unichar); - paint->textToGlyphs(unichar, size * sizeof(*unichar), &glyph16); + paint->textToGlyphs(&unichar, sizeof(unichar), &glyph16); *glyph = glyph16; return !!*glyph; } diff --git a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp index 7a3c598e0aed..14badb72a195 100644 --- a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp +++ b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp @@ -43,12 +43,13 @@ static JNIEnv* getEnv(JavaVM* vm) { return env; } -static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishListener) { +static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishListener, jint id) { class AnimationListenerBridge : public AnimationListener { public: - AnimationListenerBridge(JNIEnv* env, jobject finishListener) { + AnimationListenerBridge(JNIEnv* env, jobject finishListener, jint id) { mFinishListener = env->NewGlobalRef(finishListener); env->GetJavaVM(&mJvm); + mId = id; } virtual ~AnimationListenerBridge() { @@ -63,7 +64,7 @@ static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishLis env->CallStaticVoidMethod( gVectorDrawableAnimatorClassInfo.clazz, gVectorDrawableAnimatorClassInfo.callOnFinished, - mFinishListener); + mFinishListener, mId); releaseJavaObject(); } @@ -76,8 +77,9 @@ static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishLis JavaVM* mJvm; jobject mFinishListener; + jint mId; }; - return new AnimationListenerBridge(env, finishListener); + return new AnimationListenerBridge(env, finishListener, id); } static void addAnimator(JNIEnv*, jobject, jlong animatorSetPtr, jlong propertyHolderPtr, @@ -142,15 +144,16 @@ static void setPropertyHolderData(JNIEnv* env, jobject, jlong propertyHolderPtr, holder->setPropertyDataSource(propertyData, length); env->ReleaseFloatArrayElements(srcData, propertyData, JNI_ABORT); } -static void start(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener) { +static void start(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener, jint id) { PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr); - // TODO: keep a ref count in finish listener - AnimationListener* listener = createAnimationListener(env, finishListener); + AnimationListener* listener = createAnimationListener(env, finishListener, id); set->start(listener); } -static void reverse(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener) { - // TODO: implement reverse +static void reverse(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener, jint id) { + PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr); + AnimationListener* listener = createAnimationListener(env, finishListener, id); + set->reverse(listener); } static void end(JNIEnv*, jobject, jlong animatorSetPtr) { @@ -172,8 +175,8 @@ static const JNINativeMethod gMethods[] = { {"nCreatePathPropertyHolder", "!(JIFF)J", (void*)createPathPropertyHolder}, {"nCreateRootAlphaPropertyHolder", "!(JFF)J", (void*)createRootAlphaPropertyHolder}, {"nSetPropertyHolderData", "(J[FI)V", (void*)setPropertyHolderData}, - {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V", (void*)start}, - {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V", (void*)reverse}, + {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;I)V", (void*)start}, + {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;I)V", (void*)reverse}, {"nEnd", "!(J)V", (void*)end}, {"nReset", "!(J)V", (void*)reset}, }; @@ -186,7 +189,7 @@ int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env) { gVectorDrawableAnimatorClassInfo.callOnFinished = GetStaticMethodIDOrDie( env, gVectorDrawableAnimatorClassInfo.clazz, "callOnFinished", - "(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V"); + "(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;I)V"); return RegisterMethodsOrDie(env, "android/graphics/drawable/AnimatedVectorDrawable", gMethods, NELEM(gMethods)); } diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp index ba0876d74b17..defb88a9712f 100644 --- a/core/jni/android_net_NetUtils.cpp +++ b/core/jni/android_net_NetUtils.cpp @@ -39,23 +39,6 @@ extern "C" { int ifc_enable(const char *ifname); int ifc_disable(const char *ifname); int ifc_reset_connections(const char *ifname, int reset_mask); - -int dhcp_start(const char * const ifname); -int dhcp_start_renew(const char * const ifname); -int dhcp_get_results(const char * const ifname, - const char *ipaddr, - const char *gateway, - uint32_t *prefixLength, - const char *dns[], - const char *server, - uint32_t *lease, - const char *vendorInfo, - const char *domains, - const char *mtu); - -int dhcp_stop(const char *ifname); -int dhcp_release_lease(const char *ifname); -char *dhcp_get_errmsg(); } #define NETUTILS_PKG_NAME "android/net/NetworkUtils" @@ -64,22 +47,6 @@ namespace android { static const uint16_t kDhcpClientPort = 68; -/* - * The following remembers the jfieldID's of the fields - * of the DhcpInfo Java object, so that we don't have - * to look them up every time. - */ -static struct fieldIds { - jmethodID clear; - jmethodID setIpAddress; - jmethodID setGateway; - jmethodID addDns; - jmethodID setDomains; - jmethodID setServerAddress; - jmethodID setLeaseDuration; - jmethodID setVendorInfo; -} dhcpResultsFieldIds; - static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz, jstring ifname, jint mask) { @@ -95,137 +62,6 @@ static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz, return (jint)result; } -static jboolean android_net_utils_getDhcpResults(JNIEnv* env, jobject clazz, jstring ifname, - jobject dhcpResults) -{ - int result; - char ipaddr[PROPERTY_VALUE_MAX]; - uint32_t prefixLength; - char gateway[PROPERTY_VALUE_MAX]; - char dns1[PROPERTY_VALUE_MAX]; - char dns2[PROPERTY_VALUE_MAX]; - char dns3[PROPERTY_VALUE_MAX]; - char dns4[PROPERTY_VALUE_MAX]; - const char *dns[5] = {dns1, dns2, dns3, dns4, NULL}; - char server[PROPERTY_VALUE_MAX]; - uint32_t lease; - char vendorInfo[PROPERTY_VALUE_MAX]; - char domains[PROPERTY_VALUE_MAX]; - char mtu[PROPERTY_VALUE_MAX]; - - const char *nameStr = env->GetStringUTFChars(ifname, NULL); - if (nameStr == NULL) return (jboolean)false; - - result = ::dhcp_get_results(nameStr, ipaddr, gateway, &prefixLength, - dns, server, &lease, vendorInfo, domains, mtu); - if (result != 0) { - ALOGD("dhcp_get_results failed : %s (%s)", nameStr, ::dhcp_get_errmsg()); - } - - env->ReleaseStringUTFChars(ifname, nameStr); - if (result == 0) { - env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.clear); - - // set the linkAddress - // dhcpResults->addLinkAddress(inetAddress, prefixLength) - result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.setIpAddress, - env->NewStringUTF(ipaddr), prefixLength); - } - - if (result == 0) { - // set the gateway - result = env->CallBooleanMethod(dhcpResults, - dhcpResultsFieldIds.setGateway, env->NewStringUTF(gateway)); - } - - if (result == 0) { - // dhcpResults->addDns(new InetAddress(dns1)) - result = env->CallBooleanMethod(dhcpResults, - dhcpResultsFieldIds.addDns, env->NewStringUTF(dns1)); - } - - if (result == 0) { - env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setDomains, - env->NewStringUTF(domains)); - - result = env->CallBooleanMethod(dhcpResults, - dhcpResultsFieldIds.addDns, env->NewStringUTF(dns2)); - - if (result == 0) { - result = env->CallBooleanMethod(dhcpResults, - dhcpResultsFieldIds.addDns, env->NewStringUTF(dns3)); - if (result == 0) { - result = env->CallBooleanMethod(dhcpResults, - dhcpResultsFieldIds.addDns, env->NewStringUTF(dns4)); - } - } - } - - if (result == 0) { - // dhcpResults->setServerAddress(new InetAddress(server)) - result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.setServerAddress, - env->NewStringUTF(server)); - } - - if (result == 0) { - // dhcpResults->setLeaseDuration(lease) - env->CallVoidMethod(dhcpResults, - dhcpResultsFieldIds.setLeaseDuration, lease); - - // dhcpResults->setVendorInfo(vendorInfo) - env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setVendorInfo, - env->NewStringUTF(vendorInfo)); - } - return (jboolean)(result == 0); -} - -static jboolean android_net_utils_startDhcp(JNIEnv* env, jobject clazz, jstring ifname) -{ - const char *nameStr = env->GetStringUTFChars(ifname, NULL); - if (nameStr == NULL) return (jboolean)false; - if (::dhcp_start(nameStr) != 0) { - ALOGD("dhcp_start failed : %s", nameStr); - return (jboolean)false; - } - return (jboolean)true; -} - -static jboolean android_net_utils_startDhcpRenew(JNIEnv* env, jobject clazz, jstring ifname) -{ - const char *nameStr = env->GetStringUTFChars(ifname, NULL); - if (nameStr == NULL) return (jboolean)false; - if (::dhcp_start_renew(nameStr) != 0) { - ALOGD("dhcp_start_renew failed : %s", nameStr); - return (jboolean)false; - } - return (jboolean)true; -} - -static jboolean android_net_utils_stopDhcp(JNIEnv* env, jobject clazz, jstring ifname) -{ - int result; - - const char *nameStr = env->GetStringUTFChars(ifname, NULL); - result = ::dhcp_stop(nameStr); - env->ReleaseStringUTFChars(ifname, nameStr); - return (jboolean)(result == 0); -} - -static jboolean android_net_utils_releaseDhcpLease(JNIEnv* env, jobject clazz, jstring ifname) -{ - int result; - - const char *nameStr = env->GetStringUTFChars(ifname, NULL); - result = ::dhcp_release_lease(nameStr); - env->ReleaseStringUTFChars(ifname, nameStr); - return (jboolean)(result == 0); -} - -static jstring android_net_utils_getDhcpError(JNIEnv* env, jobject clazz) -{ - return env->NewStringUTF(::dhcp_get_errmsg()); -} - static void android_net_utils_attachDhcpFilter(JNIEnv *env, jobject clazz, jobject javaFd) { int fd = jniGetFDFromFileDescriptor(env, javaFd); @@ -305,12 +141,6 @@ static jboolean android_net_utils_queryUserAccess(JNIEnv *env, jobject thiz, jin static const JNINativeMethod gNetworkUtilMethods[] = { /* name, signature, funcPtr */ { "resetConnections", "(Ljava/lang/String;I)I", (void *)android_net_utils_resetConnections }, - { "startDhcp", "(Ljava/lang/String;)Z", (void *)android_net_utils_startDhcp }, - { "startDhcpRenew", "(Ljava/lang/String;)Z", (void *)android_net_utils_startDhcpRenew }, - { "getDhcpResults", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z", (void *)android_net_utils_getDhcpResults }, - { "stopDhcp", "(Ljava/lang/String;)Z", (void *)android_net_utils_stopDhcp }, - { "releaseDhcpLease", "(Ljava/lang/String;)Z", (void *)android_net_utils_releaseDhcpLease }, - { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError }, { "bindProcessToNetwork", "(I)Z", (void*) android_net_utils_bindProcessToNetwork }, { "getBoundNetworkForProcess", "()I", (void*) android_net_utils_getBoundNetworkForProcess }, { "bindProcessToNetworkForHostResolution", "(I)Z", (void*) android_net_utils_bindProcessToNetworkForHostResolution }, @@ -322,24 +152,6 @@ static const JNINativeMethod gNetworkUtilMethods[] = { int register_android_net_NetworkUtils(JNIEnv* env) { - jclass dhcpResultsClass = FindClassOrDie(env, "android/net/DhcpResults"); - - dhcpResultsFieldIds.clear = GetMethodIDOrDie(env, dhcpResultsClass, "clear", "()V"); - dhcpResultsFieldIds.setIpAddress =GetMethodIDOrDie(env, dhcpResultsClass, "setIpAddress", - "(Ljava/lang/String;I)Z"); - dhcpResultsFieldIds.setGateway = GetMethodIDOrDie(env, dhcpResultsClass, "setGateway", - "(Ljava/lang/String;)Z"); - dhcpResultsFieldIds.addDns = GetMethodIDOrDie(env, dhcpResultsClass, "addDns", - "(Ljava/lang/String;)Z"); - dhcpResultsFieldIds.setDomains = GetMethodIDOrDie(env, dhcpResultsClass, "setDomains", - "(Ljava/lang/String;)V"); - dhcpResultsFieldIds.setServerAddress = GetMethodIDOrDie(env, dhcpResultsClass, - "setServerAddress", "(Ljava/lang/String;)Z"); - dhcpResultsFieldIds.setLeaseDuration = GetMethodIDOrDie(env, dhcpResultsClass, - "setLeaseDuration", "(I)V"); - dhcpResultsFieldIds.setVendorInfo = GetMethodIDOrDie(env, dhcpResultsClass, "setVendorInfo", - "(Ljava/lang/String;)V"); - return RegisterMethodsOrDie(env, NETUTILS_PKG_NAME, gNetworkUtilMethods, NELEM(gNetworkUtilMethods)); } diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp index 0926e9b76691..c9eac79ef9b6 100644 --- a/core/jni/android_view_RenderNodeAnimator.cpp +++ b/core/jni/android_view_RenderNodeAnimator.cpp @@ -184,7 +184,7 @@ static void start(JNIEnv* env, jobject clazz, jlong animatorPtr) { static void end(JNIEnv* env, jobject clazz, jlong animatorPtr) { BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); - animator->end(); + animator->cancel(); } // ---------------------------------------------------------------------------- diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp index cd2c0d6643a1..07868c54cf52 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -164,6 +164,13 @@ public: mPendingAnimatingRenderNodes.clear(); } + void destroy() { + for (auto& renderNode : mPendingAnimatingRenderNodes) { + renderNode->animators().endAllStagingAnimators(); + } + mPendingAnimatingRenderNodes.clear(); + } + private: sp<Looper> mLooper; JavaVM* mVm; @@ -476,7 +483,9 @@ static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject c } static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz, - jlong proxyPtr) { + jlong proxyPtr, jlong rootNodePtr) { + RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr); + rootRenderNode->destroy(); RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); proxy->destroy(); } @@ -698,7 +707,7 @@ static const JNINativeMethod gMethods[] = { { "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter }, { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque }, { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame }, - { "nDestroy", "(J)V", (void*) android_view_ThreadedRenderer_destroy }, + { "nDestroy", "(JJ)V", (void*) android_view_ThreadedRenderer_destroy }, { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode }, { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor }, { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer }, diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index 4194aa410792..612f4dfd1505 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -608,8 +608,12 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( jlong capabilities = 0; // Grant CAP_WAKE_ALARM to the Bluetooth process. + // Additionally, allow bluetooth to open packet sockets so it can start the DHCP client. + // TODO: consider making such functionality an RPC to netd. if (multiuser_get_app_id(uid) == AID_BLUETOOTH) { capabilities |= (1LL << CAP_WAKE_ALARM); + capabilities |= (1LL << CAP_NET_RAW); + capabilities |= (1LL << CAP_NET_BIND_SERVICE); } // Grant CAP_BLOCK_SUSPEND to processes that belong to GID "wakelock" diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 9b989b94d49f..eeff00f54c86 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -452,6 +452,8 @@ <protected-broadcast android:name="android.bluetooth.input.profile.action.HANDSHAKE" /> <protected-broadcast android:name="android.bluetooth.input.profile.action.REPORT" /> + <protected-broadcast android:name="android.intent.action.TWILIGHT_CHANGED" /> + <!-- ====================================================================== --> <!-- RUNTIME PERMISSIONS --> <!-- ====================================================================== --> @@ -2006,6 +2008,12 @@ <permission android:name="android.permission.UPDATE_APP_OPS_STATS" android:protectionLevel="signature|privileged|installer" /> + <!-- Allows an application to update the user app op restrictions. + Not for use by third party apps. + @hide --> + <permission android:name="android.permission.MANAGE_APP_OPS_RESTRICTIONS" + android:protectionLevel="signature|installer" /> + <!-- @SystemApi Allows an application to open windows that are for use by parts of the system user interface. <p>Not for use by third-party applications. diff --git a/core/res/res/layout/notification_template_material_big_media.xml b/core/res/res/layout/notification_template_material_big_media.xml index aa78eff612c8..a5ed1875d830 100644 --- a/core/res/res/layout/notification_template_material_big_media.xml +++ b/core/res/res/layout/notification_template_material_big_media.xml @@ -19,41 +19,45 @@ <com.android.internal.widget.MediaNotificationView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/status_bar_latest_event_content" android:layout_width="match_parent" - android:layout_height="126dp" + android:layout_height="wrap_content" android:background="#00000000" android:tag="bigMediaNarrow" > <include layout="@layout/notification_template_header" android:layout_width="match_parent" android:layout_height="48dp" - android:layout_alignParentStart="true"/> + android:layout_gravity="start"/> <LinearLayout - android:id="@+id/notification_main_column" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="@dimen/notification_content_margin_top" - android:layout_marginStart="@dimen/notification_content_margin_start" - android:layout_marginBottom="@dimen/notification_content_margin_bottom" - android:layout_marginEnd="@dimen/notification_content_margin_end" - android:layout_toStartOf="@id/right_icon" - android:minHeight="@dimen/notification_min_content_height" android:orientation="vertical" > - <include layout="@layout/notification_template_part_line1" /> - <include layout="@layout/notification_template_text" /> - </LinearLayout> - <LinearLayout - android:id="@+id/media_actions" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentBottom="true" - android:layout_alignParentStart="true" - android:paddingStart="8dp" - android:paddingBottom="8dp" - android:orientation="horizontal" - android:layoutDirection="ltr" - > - <!-- media buttons will be added here --> + <LinearLayout + android:id="@+id/notification_main_column" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/notification_content_margin_top" + android:layout_marginStart="@dimen/notification_content_margin_start" + android:layout_marginBottom="@dimen/notification_content_margin_bottom" + android:layout_marginEnd="@dimen/notification_content_margin_end" + android:minHeight="@dimen/notification_min_content_height" + android:orientation="vertical" + > + <include layout="@layout/notification_template_part_line1" /> + <include layout="@layout/notification_template_text" /> + </LinearLayout> + <LinearLayout + android:id="@+id/media_actions" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="-15dp" + android:paddingStart="8dp" + android:paddingBottom="8dp" + android:orientation="horizontal" + android:layoutDirection="ltr" + > + <!-- media buttons will be added here --> + </LinearLayout> </LinearLayout> <ImageView android:id="@+id/right_icon" @@ -61,9 +65,8 @@ android:layout_height="@dimen/media_notification_expanded_image_max_size" android:minWidth="40dp" android:layout_marginEnd="16dp" - android:layout_marginTop="16dp" - android:layout_alignParentEnd="true" - android:layout_alignParentTop="true" + android:layout_marginBottom="16dp" + android:layout_gravity="bottom|end" android:scaleType="centerCrop" /> </com.android.internal.widget.MediaNotificationView> diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml index aea9b44622c4..cda063627dc5 100644 --- a/core/res/res/layout/notification_template_material_media.xml +++ b/core/res/res/layout/notification_template_material_media.xml @@ -36,6 +36,7 @@ android:tag="media" > <LinearLayout + android:id="@+id/notification_content_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="fill_vertical" @@ -45,7 +46,6 @@ android:orientation="vertical" > <include layout="@layout/notification_template_part_line1"/> - <include layout="@layout/notification_template_progress"/> <include layout="@layout/notification_template_text"/> </LinearLayout> <LinearLayout diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 016ed60eeea3..3a185d60fda5 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1992,10 +1992,10 @@ See {@link com.android.server.notification.NotificationSignalExtractor} --> <string-array name="config_notificationSignalExtractors"> <item>com.android.server.notification.ValidateNotificationPeople</item> - <item>com.android.server.notification.TopicPriorityExtractor</item> - <item>com.android.server.notification.TopicImportanceExtractor</item> + <item>com.android.server.notification.PriorityExtractor</item> + <item>com.android.server.notification.ImportanceExtractor</item> <item>com.android.server.notification.NotificationIntrusivenessExtractor</item> - <item>com.android.server.notification.TopicVisibilityExtractor</item> + <item>com.android.server.notification.VisibilityExtractor</item> </string-array> <!-- Flag indicating that this device does not rotate and will always remain in its default diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 8e86f78e02fd..100570422b17 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -56,6 +56,10 @@ calculate the bounds of the stacks--> <dimen name="docked_stack_divider_insets">19dp</dimen> + <!-- To how much the docked stack gets reduced when we decide to minimize the docked stack, i.e. + when the user opens homescreen. --> + <dimen name="docked_stack_minimize_thickness">8dp</dimen> + <!-- Min width for a tablet device --> <dimen name="min_xlarge_screen_width">800dp</dimen> @@ -146,9 +150,6 @@ <!-- The margin on the end of the content view with a picture.--> <dimen name="notification_content_picture_margin">56dp</dimen> - <!-- The margin on the end of the content view with a picture in the compact media.--> - <dimen name="notification_content_picture_margin_media">72dp</dimen> - <!-- height of the content margin to accomodate for the header --> <dimen name="notification_content_margin_top">30dp</dimen> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 1f0e96d46f44..da881462618c 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -4162,9 +4162,7 @@ <item quantity="other"><xliff:g id="count" example="3">%1$d</xliff:g> selected</item> </plurals> - <string name="default_notification_topic_label">Miscellaneous</string> - - <string name="importance_from_topic">You set the importance of these notifications.</string> + <string name="importance_from_user">You set the importance of these notifications.</string> <string name="importance_from_person">This is important because of the people involved.</string> <!-- Message to user that app trying to create user for an account that already exists. [CHAR LIMIT=none] --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 2d3ad176cbe7..746e7fdf1d0a 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1506,6 +1506,7 @@ <java-symbol type="bool" name="target_honeycomb_needs_options_menu" /> <java-symbol type="dimen" name="docked_stack_divider_thickness" /> <java-symbol type="dimen" name="docked_stack_divider_insets" /> + <java-symbol type="dimen" name="docked_stack_minimize_thickness" /> <java-symbol type="integer" name="config_dockedStackDividerSnapMode" /> <java-symbol type="fraction" name="docked_stack_divider_fixed_ratio" /> <java-symbol type="dimen" name="navigation_bar_height" /> @@ -2388,7 +2389,6 @@ <java-symbol type="string" name="config_iccHotswapPromptForRestartDialogComponent" /> <java-symbol type="string" name="config_packagedKeyboardName" /> - <java-symbol type="string" name="default_notification_topic_label" /> <java-symbol type="bool" name="config_forceWindowDrawsStatusBarBackground" /> <java-symbol type="color" name="system_bar_background_semi_transparent" /> @@ -2427,7 +2427,7 @@ <java-symbol type="dimen" name="notification_content_margin_end" /> <java-symbol type="dimen" name="notification_content_picture_margin" /> <java-symbol type="dimen" name="notification_content_margin_top" /> - <java-symbol type="string" name="importance_from_topic" /> + <java-symbol type="string" name="importance_from_user" /> <java-symbol type="string" name="importance_from_person" /> <java-symbol type="layout" name="work_widget_mask_view" /> @@ -2512,13 +2512,14 @@ <java-symbol type="dimen" name="media_notification_expanded_image_max_size" /> <java-symbol type="dimen" name="media_notification_expanded_image_margin_bottom" /> <java-symbol type="dimen" name="notification_content_image_margin_end" /> - <java-symbol type="dimen" name="notification_content_picture_margin_media" /> <java-symbol type="bool" name="config_strongAuthRequiredOnBoot" /> <java-symbol type="layout" name="app_anr_dialog" /> <java-symbol type="id" name="aerr_wait" /> + <java-symbol type="id" name="notification_content_container" /> + <!-- Encryption notification while accounts are locked by credential encryption --> <java-symbol type="string" name="user_encrypted_title" /> <java-symbol type="string" name="user_encrypted_message" /> diff --git a/core/tests/coretests/apks/install_jni_lib/Android.mk b/core/tests/coretests/apks/install_jni_lib/Android.mk index 7322e8d6949b..9e45d099b669 100644 --- a/core/tests/coretests/apks/install_jni_lib/Android.mk +++ b/core/tests/coretests/apks/install_jni_lib/Android.mk @@ -22,6 +22,8 @@ LOCAL_SRC_FILES := \ LOCAL_SHARED_LIBRARIES := \ libnativehelper +LOCAL_CFLAGS += -Wall -Werror + LOCAL_MODULE := libframeworks_coretests_jni # this does not prevent build system diff --git a/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp b/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp index 3e8301038359..8d9119275bc8 100644 --- a/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp +++ b/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp @@ -37,7 +37,7 @@ int register_com_android_frameworks_coretests_JNITests(JNIEnv* env) { /* * JNI Initialization */ -jint JNI_OnLoad(JavaVM *jvm, void *reserved) { +jint JNI_OnLoad(JavaVM *jvm, void */* reserved */) { JNIEnv *e; int status; diff --git a/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk b/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk index ff5a5359af12..994131a22ab3 100644 --- a/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk +++ b/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk @@ -32,6 +32,8 @@ LOCAL_SRC_FILES:= \ # All of the shard libraries we link against. LOCAL_SHARED_LIBRARIES := liblog +LOCAL_CFLAGS += -Wall -Wextra -Werror + # Also need the JNI headers. LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) diff --git a/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp index 67b12d775828..99cf587af2a6 100644 --- a/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp +++ b/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp @@ -22,7 +22,7 @@ #include "jni.h" static jint -add(JNIEnv *env, jobject thiz, jint a, jint b) { +add(JNIEnv */* env */, jobject /* thiz */, jint a, jint b) { int result = a + b; ALOGI("%d + %d = %d", a, b, result); return result; @@ -82,7 +82,7 @@ typedef union { void* venv; } UnionJNIEnvToVoid; -jint JNI_OnLoad(JavaVM* vm, void* reserved) +jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) { UnionJNIEnvToVoid uenv; uenv.venv = NULL; diff --git a/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk b/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk index abb1d9f6ca9f..6c2679b30bfb 100644 --- a/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk +++ b/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk @@ -34,6 +34,8 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := \ libutils liblog +LOCAL_CFLAGS += -Wall -Wextra -Werror + # Also need the JNI headers. LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) diff --git a/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp index 342b3bc0ac9a..0b6d7501dcae 100644 --- a/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp +++ b/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp @@ -22,7 +22,7 @@ #include "jni.h" static jint -add(JNIEnv *env, jobject thiz, jint a, jint b) { +add(JNIEnv */* env */, jobject /* thiz */, jint a, jint b) { int result = a + b; ALOGI("%d + %d = %d", a, b, result); return result; @@ -82,7 +82,7 @@ typedef union { void* venv; } UnionJNIEnvToVoid; -jint JNI_OnLoad(JavaVM* vm, void* reserved) +jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) { UnionJNIEnvToVoid uenv; uenv.venv = NULL; diff --git a/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk b/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk index ae8e636caf4b..d668f29456c8 100644 --- a/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk +++ b/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk @@ -33,6 +33,8 @@ LOCAL_SRC_FILES:= \ LOCAL_LDLIBS = -llog LOCAL_SHARED_LIBRARIES := liblog +LOCAL_CFLAGS += -Wall -Wextra -Werror + # Also need the JNI headers. LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) diff --git a/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp index 9b38e3e4c437..3947e21a77bd 100644 --- a/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp +++ b/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp @@ -22,7 +22,7 @@ #include "jni.h" static jint -add(JNIEnv *env, jobject thiz, jint a, jint b) { +add(JNIEnv */* env */, jobject /* thiz */, jint a, jint b) { int result = a + b; ALOGI("%d + %d = %d", a, b, result); return result; @@ -82,7 +82,7 @@ typedef union { void* venv; } UnionJNIEnvToVoid; -jint JNI_OnLoad(JavaVM* vm, void* reserved) +jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) { UnionJNIEnvToVoid uenv; uenv.venv = NULL; diff --git a/core/tests/utiltests/src/com/android/internal/util/AsyncChannelTest.java b/core/tests/utiltests/src/com/android/internal/util/AsyncChannelTest.java deleted file mode 100644 index 7088650792ef..000000000000 --- a/core/tests/utiltests/src/com/android/internal/util/AsyncChannelTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (C) 2010 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.internal.util; - -import android.os.Debug; -import android.test.suitebuilder.annotation.SmallTest; -import android.util.Log; - -import junit.framework.TestCase; - -/** - * Test for AsyncChannel. - */ -public class AsyncChannelTest extends TestCase { - private static final boolean DBG = true; - private static final boolean WAIT_FOR_DEBUGGER = false; - private static final String TAG = "AsyncChannelTest"; - - @SmallTest - public void test1() throws Exception { - if (DBG) log("test1"); - if (WAIT_FOR_DEBUGGER) Debug.waitForDebugger(); - assertTrue(1 == 1); - } - - protected void log(String s) { - Log.d(TAG, s); - } -} diff --git a/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java b/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java index be7116dffb89..5f36c2d0c29b 100644 --- a/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java +++ b/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java @@ -42,6 +42,6 @@ public class FastXmlSerializerTest extends TestCase { out.endDocument(); assertEquals("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" - + "<string name=\"meow\"></string>", stream.toString()); + + "<string name=\"meow\"></string>\n", stream.toString()); } } diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index af8ccf5018b9..c486c1fe17f0 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -154,7 +154,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false; /** Local, mutable animator set. */ - private final VectorDrawableAnimator mAnimatorSet = new VectorDrawableAnimator(); + private final VectorDrawableAnimator mAnimatorSet = new VectorDrawableAnimator(this); /** * The resources against which this drawable was created. Used to attempt @@ -238,9 +238,6 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { mAnimatorSet.recordLastSeenTarget((DisplayListCanvas) canvas); } mAnimatedVectorState.mVectorDrawable.draw(canvas); - if (isStarted()) { - invalidateSelf(); - } } @Override @@ -611,29 +608,17 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { return mAnimatorSet.isRunning(); } - private boolean isStarted() { - return mAnimatorSet.isStarted(); - } - /** * Resets the AnimatedVectorDrawable to the start state as specified in the animators. */ public void reset() { mAnimatorSet.reset(); - invalidateSelf(); } @Override public void start() { ensureAnimatorSet(); - - // If any one of the animator has not ended, do nothing. - if (isStarted()) { - return; - } - mAnimatorSet.start(); - invalidateSelf(); } @NonNull @@ -671,7 +656,6 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { } mAnimatorSet.reverse(); - invalidateSelf(); } /** @@ -774,6 +758,9 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { * @hide */ public static class VectorDrawableAnimator { + private static final int NONE = 0; + private static final int START_ANIMATION = 1; + private static final int REVERSE_ANIMATION = 2; private AnimatorListener mListener = null; private final LongArray mStartDelays = new LongArray(); private PropertyValuesHolder.PropertyValues mTmpValues = @@ -782,17 +769,18 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { private boolean mContainsSequentialAnimators = false; private boolean mStarted = false; private boolean mInitialized = false; - private boolean mAnimationPending = false; private boolean mIsReversible = false; // This needs to be set before parsing starts. private boolean mShouldIgnoreInvalidAnim; // TODO: Consider using NativeAllocationRegistery to track native allocation private final VirtualRefBasePtr mSetRefBasePtr; - private WeakReference<RenderNode> mTarget = null; private WeakReference<RenderNode> mLastSeenTarget = null; + private int mLastListenerId = 0; + private int mPendingAnimationAction = NONE; + private final Drawable mDrawable; - - VectorDrawableAnimator() { + VectorDrawableAnimator(AnimatedVectorDrawable drawable) { + mDrawable = drawable; mSetPtr = nCreateAnimatorSet(); // Increment ref count on native AnimatorSet, so it doesn't get released before Java // side is done using it. @@ -810,6 +798,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { mInitialized = true; // Check reversible. + mIsReversible = true; if (mContainsSequentialAnimators) { mIsReversible = false; } else { @@ -821,7 +810,6 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { } } } - mIsReversible = true; } private void parseAnimatorSet(AnimatorSet set, long startTime) { @@ -1042,51 +1030,44 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { * to the last seen RenderNode target and start right away. */ protected void recordLastSeenTarget(DisplayListCanvas canvas) { - if (mAnimationPending) { - mLastSeenTarget = new WeakReference<RenderNode>( - RenderNodeAnimatorSetHelper.getTarget(canvas)); + mLastSeenTarget = new WeakReference<RenderNode>( + RenderNodeAnimatorSetHelper.getTarget(canvas)); + if (mPendingAnimationAction != NONE) { if (DBG_ANIMATION_VECTOR_DRAWABLE) { Log.d(LOGTAG, "Target is set in the next frame"); } - mAnimationPending = false; - start(); - } else { - mLastSeenTarget = new WeakReference<RenderNode>( - RenderNodeAnimatorSetHelper.getTarget(canvas)); + if (mPendingAnimationAction == START_ANIMATION) { + start(); + } else if (mPendingAnimationAction == REVERSE_ANIMATION) { + reverse(); + } + mPendingAnimationAction = NONE; } - - } - - private boolean setTarget(RenderNode node) { - if (mTarget != null && mTarget.get() != null) { - // TODO: Maybe we want to support target change. - throw new IllegalStateException("Target already set!"); - } - - node.addAnimator(this); - mTarget = new WeakReference<RenderNode>(node); - return true; } private boolean useLastSeenTarget() { - if (mLastSeenTarget != null && mLastSeenTarget.get() != null) { - setTarget(mLastSeenTarget.get()); - return true; + if (mLastSeenTarget != null) { + final RenderNode target = mLastSeenTarget.get(); + if (target != null && target.isAttached()) { + target.addAnimator(this); + return true; + } } return false; } + private void invalidateOwningView() { + mDrawable.invalidateSelf(); + } + public void start() { if (!mInitialized) { return; } - if (mStarted) { - return; - } - if (!useLastSeenTarget()) { - mAnimationPending = true; + invalidateOwningView(); + mPendingAnimationAction = START_ANIMATION; return; } @@ -1094,38 +1075,50 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { Log.d(LOGTAG, "Target is set. Starting VDAnimatorSet from java"); } - nStart(mSetPtr, this); + mStarted = true; + nStart(mSetPtr, this, ++mLastListenerId); + invalidateOwningView(); if (mListener != null) { mListener.onAnimationStart(null); } - mStarted = true; } public void end() { - if (mInitialized && mStarted) { + if (mInitialized && useLastSeenTarget()) { + // If no target has ever been set, no-op nEnd(mSetPtr); - onAnimationEnd(); + invalidateOwningView(); } } - void reset() { - if (!mInitialized) { - return; + public void reset() { + if (mInitialized && useLastSeenTarget()) { + // If no target has ever been set, no-op + nReset(mSetPtr); + invalidateOwningView(); } - // TODO: Need to implement reset. - Log.w(LOGTAG, "Reset is yet to be implemented"); - nReset(mSetPtr); } // Current (imperfect) Java AnimatorSet cannot be reversed when the set contains sequential // animators or when the animator set has a start delay void reverse() { - if (!mIsReversible) { + if (!mIsReversible || !mInitialized) { return; } - // TODO: Need to support reverse (non-public API) - Log.w(LOGTAG, "Reverse is yet to be implemented"); - nReverse(mSetPtr, this); + if (!useLastSeenTarget()) { + invalidateOwningView(); + mPendingAnimationAction = REVERSE_ANIMATION; + return; + } + if (DBG_ANIMATION_VECTOR_DRAWABLE) { + Log.d(LOGTAG, "Target is set. Reversing VDAnimatorSet from java"); + } + mStarted = true; + nReverse(mSetPtr, this, ++mLastListenerId); + invalidateOwningView(); + if (mListener != null) { + mListener.onAnimationStart(null); + } } public long getAnimatorNativePtr() { @@ -1155,20 +1148,22 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { mListener = null; } - private void onAnimationEnd() { + private void onAnimationEnd(int listenerId) { + if (listenerId != mLastListenerId) { + return; + } + if (DBG_ANIMATION_VECTOR_DRAWABLE) { + Log.d(LOGTAG, "on finished called from native"); + } mStarted = false; if (mListener != null) { mListener.onAnimationEnd(null); } - mTarget = null; } // onFinished: should be called from native - private static void callOnFinished(VectorDrawableAnimator set) { - if (DBG_ANIMATION_VECTOR_DRAWABLE) { - Log.d(LOGTAG, "on finished called from native"); - } - set.onAnimationEnd(); + private static void callOnFinished(VectorDrawableAnimator set, int id) { + set.onAnimationEnd(id); } } @@ -1188,8 +1183,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { private static native long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue, float endValue); private static native void nSetPropertyHolderData(long nativePtr, float[] data, int length); - private static native void nStart(long animatorSetPtr, VectorDrawableAnimator set); - private static native void nReverse(long animatorSetPtr, VectorDrawableAnimator set); + private static native void nStart(long animatorSetPtr, VectorDrawableAnimator set, int id); + private static native void nReverse(long animatorSetPtr, VectorDrawableAnimator set, int id); private static native void nEnd(long animatorSetPtr); private static native void nReset(long animatorSetPtr); } diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index 625712292234..8660b75e702e 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -7,7 +7,7 @@ HWUI_NEW_OPS := true # Enables fine-grained GLES error checking # If set to true, every GLES call is wrapped & error checked # Has moderate overhead -HWUI_ENABLE_OPENGL_VALIDATION := false +HWUI_ENABLE_OPENGL_VALIDATION := true hwui_src_files := \ font/CacheTexture.cpp \ diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp index 7bd2b24bf56b..294edb6ecd46 100644 --- a/libs/hwui/Animator.cpp +++ b/libs/hwui/Animator.cpp @@ -33,6 +33,7 @@ namespace uirenderer { BaseRenderNodeAnimator::BaseRenderNodeAnimator(float finalValue) : mTarget(nullptr) + , mStagingTarget(nullptr) , mFinalValue(finalValue) , mDeltaValue(0) , mFromValue(0) @@ -42,7 +43,8 @@ BaseRenderNodeAnimator::BaseRenderNodeAnimator(float finalValue) , mStartTime(0) , mDuration(300) , mStartDelay(0) - , mMayRunAsync(true) { + , mMayRunAsync(true) + , mPlayTime(0) { } BaseRenderNodeAnimator::~BaseRenderNodeAnimator() { @@ -81,26 +83,129 @@ void BaseRenderNodeAnimator::setStartDelay(nsecs_t startDelay) { } void BaseRenderNodeAnimator::attach(RenderNode* target) { - mTarget = target; + mStagingTarget = target; onAttached(); } +void BaseRenderNodeAnimator::start() { + mStagingPlayState = PlayState::Running; + mStagingRequests.push_back(Request::Start); + onStagingPlayStateChanged(); +} + +void BaseRenderNodeAnimator::cancel() { + mStagingPlayState = PlayState::Finished; + mStagingRequests.push_back(Request::Cancel); + onStagingPlayStateChanged(); +} + +void BaseRenderNodeAnimator::reset() { + mStagingPlayState = PlayState::Finished; + mStagingRequests.push_back(Request::Reset); + onStagingPlayStateChanged(); +} + +void BaseRenderNodeAnimator::reverse() { + mStagingPlayState = PlayState::Reversing; + mStagingRequests.push_back(Request::Reverse); + onStagingPlayStateChanged(); +} + +void BaseRenderNodeAnimator::end() { + mStagingPlayState = PlayState::Finished; + mStagingRequests.push_back(Request::End); + onStagingPlayStateChanged(); +} + +void BaseRenderNodeAnimator::resolveStagingRequest(Request request) { + switch (request) { + case Request::Start: + mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ? + mPlayTime : 0; + mPlayState = PlayState::Running; + break; + case Request::Reverse: + mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ? + mPlayTime : mDuration; + mPlayState = PlayState::Reversing; + break; + case Request::Reset: + mPlayTime = 0; + mPlayState = PlayState::Finished; + break; + case Request::Cancel: + mPlayState = PlayState::Finished; + break; + case Request::End: + mPlayTime = mPlayState == PlayState::Reversing ? 0 : mDuration; + mPlayState = PlayState::Finished; + break; + default: + LOG_ALWAYS_FATAL("Invalid staging request: %d", static_cast<int>(request)); + }; +} + void BaseRenderNodeAnimator::pushStaging(AnimationContext& context) { + if (mStagingTarget) { + RenderNode* oldTarget = mTarget; + mTarget = mStagingTarget; + mStagingTarget = nullptr; + if (oldTarget && oldTarget != mTarget) { + oldTarget->onAnimatorTargetChanged(this); + } + } + if (!mHasStartValue) { doSetStartValue(getValue(mTarget)); } - if (mStagingPlayState > mPlayState) { - if (mStagingPlayState == PlayState::Restarted) { - mStagingPlayState = PlayState::Running; + + if (!mStagingRequests.empty()) { + // Keep track of the play state and play time before they are changed when + // staging requests are resolved. + nsecs_t currentPlayTime = mPlayTime; + PlayState prevFramePlayState = mPlayState; + + // Resolve staging requests one by one. + for (Request request : mStagingRequests) { + resolveStagingRequest(request); } - mPlayState = mStagingPlayState; - // Oh boy, we're starting! Man the battle stations! - if (mPlayState == PlayState::Running) { - transitionToRunning(context); - } else if (mPlayState == PlayState::Finished) { + mStagingRequests.clear(); + + if (mStagingPlayState == PlayState::Finished) { + // Set the staging play time and end the animation + updatePlayTime(mPlayTime); callOnFinishedListener(context); + } else if (mStagingPlayState == PlayState::Running + || mStagingPlayState == PlayState::Reversing) { + bool changed = currentPlayTime != mPlayTime || prevFramePlayState != mStagingPlayState; + if (prevFramePlayState != mStagingPlayState) { + transitionToRunning(context); + } + if (changed) { + // Now we need to seek to the stagingPlayTime (i.e. the animation progress that was + // requested from UI thread). It is achieved by modifying mStartTime, such that + // current time - mStartTime = stagingPlayTime (or mDuration -stagingPlayTime in the + // case of reversing) + nsecs_t currentFrameTime = context.frameTimeMs(); + if (mPlayState == PlayState::Reversing) { + // Reverse is not supported for animations with a start delay, so here we + // assume no start delay. + mStartTime = currentFrameTime - (mDuration - mPlayTime); + } else { + // Animation should play forward + if (mPlayTime == 0) { + // If the request is to start from the beginning, include start delay. + mStartTime = currentFrameTime + mStartDelay; + } else { + // If the request is to seek to a non-zero play time, then we skip start + // delay. + mStartTime = currentFrameTime - mPlayTime; + } + } + } } } + onPushStaging(); } void BaseRenderNodeAnimator::transitionToRunning(AnimationContext& context) { @@ -136,37 +241,37 @@ bool BaseRenderNodeAnimator::animate(AnimationContext& context) { // This should be set before setValue() so animators can query this time when setValue // is called. - nsecs_t currentFrameTime = context.frameTimeMs(); - onPlayTimeChanged(currentFrameTime - mStartTime); + nsecs_t currentPlayTime = context.frameTimeMs() - mStartTime; + bool finished = updatePlayTime(currentPlayTime); + if (finished && mPlayState != PlayState::Finished) { + mPlayState = PlayState::Finished; + callOnFinishedListener(context); + } + return finished; +} +bool BaseRenderNodeAnimator::updatePlayTime(nsecs_t playTime) { + mPlayTime = mPlayState == PlayState::Reversing ? mDuration - playTime : playTime; + onPlayTimeChanged(mPlayTime); // If BaseRenderNodeAnimator is handling the delay (not typical), then // because the staging properties reflect the final value, we always need // to call setValue even if the animation isn't yet running or is still // being delayed as we need to override the staging value - if (mStartTime > context.frameTimeMs()) { + if (playTime < 0) { setValue(mTarget, mFromValue); return false; } float fraction = 1.0f; - - if (mPlayState == PlayState::Running && mDuration > 0) { - fraction = (float)(currentFrameTime - mStartTime) / mDuration; - } - if (fraction >= 1.0f) { - fraction = 1.0f; - mPlayState = PlayState::Finished; + if ((mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) && mDuration > 0) { + fraction = mPlayTime / (float) mDuration; } + fraction = MathUtils::clamp(fraction, 0.0f, 1.0f); fraction = mInterpolator->interpolate(fraction); setValue(mTarget, mFromValue + (mDeltaValue * fraction)); - if (mPlayState == PlayState::Finished) { - callOnFinishedListener(context); - return true; - } - - return false; + return playTime >= mDuration; } void BaseRenderNodeAnimator::forceEndNow(AnimationContext& context) { @@ -215,18 +320,36 @@ RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property, float fi void RenderPropertyAnimator::onAttached() { if (!mHasStartValue - && mTarget->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) { - setStartValue((mTarget->stagingProperties().*mPropertyAccess->getter)()); + && mStagingTarget->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) { + setStartValue((mStagingTarget->stagingProperties().*mPropertyAccess->getter)()); } } void RenderPropertyAnimator::onStagingPlayStateChanged() { if (mStagingPlayState == PlayState::Running) { - (mTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue()); + if (mStagingTarget) { + (mStagingTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue()); + } else { + // In the case of start delay where stagingTarget has been sync'ed over and null'ed + // we delay the properties update to push staging. + mShouldUpdateStagingProperties = true; + } } else if (mStagingPlayState == PlayState::Finished) { // We're being canceled, so make sure that whatever values the UI thread // is observing for us is pushed over + mShouldSyncPropertyFields = true; + } +} + +void RenderPropertyAnimator::onPushStaging() { + if (mShouldUpdateStagingProperties) { + (mTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue()); + mShouldUpdateStagingProperties = false; + } + + if (mShouldSyncPropertyFields) { mTarget->setPropertyFieldsDirty(dirtyMask()); + mShouldSyncPropertyFields = false; } } diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h index 2c9c9c3fe0f9..fdae0f32d4e6 100644 --- a/libs/hwui/Animator.h +++ b/libs/hwui/Animator.h @@ -24,6 +24,8 @@ #include "utils/Macros.h" +#include <vector> + namespace android { namespace uirenderer { @@ -59,14 +61,14 @@ public: mMayRunAsync = mayRunAsync; } bool mayRunAsync() { return mMayRunAsync; } - ANDROID_API void start() { - if (mStagingPlayState == PlayState::NotStarted) { - mStagingPlayState = PlayState::Running; - } else { - mStagingPlayState = PlayState::Restarted; - } - onStagingPlayStateChanged(); } - ANDROID_API void end() { mStagingPlayState = PlayState::Finished; onStagingPlayStateChanged(); } + ANDROID_API void start(); + ANDROID_API void reset(); + ANDROID_API void reverse(); + // Terminates the animation at its current progress. + ANDROID_API void cancel(); + + // Terminates the animation and skip to the end of the animation. + ANDROID_API void end(); void attach(RenderNode* target); virtual void onAttached() {} @@ -74,36 +76,42 @@ public: void pushStaging(AnimationContext& context); bool animate(AnimationContext& context); - bool isRunning() { return mPlayState == PlayState::Running; } + bool isRunning() { return mPlayState == PlayState::Running + || mPlayState == PlayState::Reversing; } bool isFinished() { return mPlayState == PlayState::Finished; } float finalValue() { return mFinalValue; } ANDROID_API virtual uint32_t dirtyMask() = 0; void forceEndNow(AnimationContext& context); + RenderNode* target() { return mTarget; } + RenderNode* stagingTarget() { return mStagingTarget; } protected: // PlayState is used by mStagingPlayState and mPlayState to track the state initiated from UI // thread and Render Thread animation state, respectively. // From the UI thread, mStagingPlayState transition looks like - // NotStarted -> Running -> Finished - // ^ | - // | | - // Restarted <------ + // NotStarted -> Running/Reversing -> Finished + // ^ | + // | | + // ---------------------- // Note: For mStagingState, the Finished state (optional) is only set when the animation is // terminated by user. // // On Render Thread, mPlayState transition: - // NotStart -> Running -> Finished - // ^ | - // | | - // ------------- + // NotStart -> Running/Reversing-> Finished + // ^ | + // | | + // ------------------ + // Note that if the animation is in Running/Reversing state, calling start or reverse again + // would do nothing if the animation has the same play direction as the request; otherwise, + // the animation would start from where it is and change direction (i.e. Reversing <-> Running) enum class PlayState { NotStarted, Running, + Reversing, Finished, - Restarted, }; BaseRenderNodeAnimator(float finalValue); @@ -111,14 +119,15 @@ protected: virtual float getValue(RenderNode* target) const = 0; virtual void setValue(RenderNode* target, float value) = 0; - RenderNode* target() { return mTarget; } void callOnFinishedListener(AnimationContext& context); virtual void onStagingPlayStateChanged() {} virtual void onPlayTimeChanged(nsecs_t playTime) {} + virtual void onPushStaging() {} RenderNode* mTarget; + RenderNode* mStagingTarget; float mFinalValue; float mDeltaValue; @@ -132,13 +141,28 @@ protected: nsecs_t mDuration; nsecs_t mStartDelay; bool mMayRunAsync; + // Play Time tracks the progress of animation, it should always be [0, mDuration], 0 being + // the beginning of the animation, will reach mDuration at the end of an animation. + nsecs_t mPlayTime; sp<AnimationListener> mListener; private: + enum class Request { + Start, + Reverse, + Reset, + Cancel, + End + }; inline void checkMutable(); virtual void transitionToRunning(AnimationContext& context); void doSetStartValue(float value); + bool updatePlayTime(nsecs_t playTime); + void resolveStagingRequest(Request request); + + std::vector<Request> mStagingRequests; + }; class RenderPropertyAnimator : public BaseRenderNodeAnimator { @@ -167,6 +191,7 @@ protected: virtual void setValue(RenderNode* target, float value) override; virtual void onAttached() override; virtual void onStagingPlayStateChanged() override; + virtual void onPushStaging() override; private: typedef bool (RenderProperties::*SetFloatProperty)(float value); @@ -176,6 +201,8 @@ private: const PropertyAccessors* mPropertyAccess; static const PropertyAccessors PROPERTY_ACCESSOR_LUT[]; + bool mShouldSyncPropertyFields = false; + bool mShouldUpdateStagingProperties = false; }; class CanvasPropertyPrimitiveAnimator : public BaseRenderNodeAnimator { diff --git a/libs/hwui/AnimatorManager.cpp b/libs/hwui/AnimatorManager.cpp index cd30b1859384..2198fcc95fe5 100644 --- a/libs/hwui/AnimatorManager.cpp +++ b/libs/hwui/AnimatorManager.cpp @@ -27,9 +27,8 @@ namespace uirenderer { using namespace std; -static void unref(BaseRenderNodeAnimator* animator) { +static void detach(sp<BaseRenderNodeAnimator>& animator) { animator->detach(); - animator->decStrong(nullptr); } AnimatorManager::AnimatorManager(RenderNode& parent) @@ -38,14 +37,28 @@ AnimatorManager::AnimatorManager(RenderNode& parent) } AnimatorManager::~AnimatorManager() { - for_each(mNewAnimators.begin(), mNewAnimators.end(), unref); - for_each(mAnimators.begin(), mAnimators.end(), unref); + for_each(mNewAnimators.begin(), mNewAnimators.end(), detach); + for_each(mAnimators.begin(), mAnimators.end(), detach); } void AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) { - animator->incStrong(nullptr); + RenderNode* stagingTarget = animator->stagingTarget(); + if (stagingTarget == &mParent) { + return; + } + mNewAnimators.emplace_back(animator.get()); + // If the animator is already attached to other RenderNode, remove it from that RenderNode's + // new animator list. This ensures one animator only ends up in one newAnimatorList during one + // frame, even when it's added multiple times to multiple targets. + if (stagingTarget) { + stagingTarget->removeAnimator(animator); + } animator->attach(&mParent); - mNewAnimators.push_back(animator.get()); +} + +void AnimatorManager::removeAnimator(const sp<BaseRenderNodeAnimator>& animator) { + mNewAnimators.erase(std::remove(mNewAnimators.begin(), mNewAnimators.end(), animator), + mNewAnimators.end()); } void AnimatorManager::setAnimationHandle(AnimationHandle* handle) { @@ -56,38 +69,40 @@ void AnimatorManager::setAnimationHandle(AnimationHandle* handle) { &mParent, mParent.getName()); } -template<typename T> -static void move_all(T& source, T& dest) { - dest.reserve(source.size() + dest.size()); - for (typename T::iterator it = source.begin(); it != source.end(); it++) { - dest.push_back(*it); - } - source.clear(); -} - void AnimatorManager::pushStaging() { if (mNewAnimators.size()) { LOG_ALWAYS_FATAL_IF(!mAnimationHandle, "Trying to start new animators on %p (%s) without an animation handle!", &mParent, mParent.getName()); - // Since this is a straight move, we don't need to inc/dec the ref count - move_all(mNewAnimators, mAnimators); + + // Only add new animators that are not already in the mAnimators list + for (auto& anim : mNewAnimators) { + if (anim->target() != &mParent) { + mAnimators.push_back(std::move(anim)); + } + } + mNewAnimators.clear(); } - for (vector<BaseRenderNodeAnimator*>::iterator it = mAnimators.begin(); it != mAnimators.end(); it++) { - (*it)->pushStaging(mAnimationHandle->context()); + for (auto& animator : mAnimators) { + animator->pushStaging(mAnimationHandle->context()); } } +void AnimatorManager::onAnimatorTargetChanged(BaseRenderNodeAnimator* animator) { + LOG_ALWAYS_FATAL_IF(animator->target() == &mParent, "Target has not been changed"); + mAnimators.erase(std::remove(mAnimators.begin(), mAnimators.end(), animator), mAnimators.end()); +} + class AnimateFunctor { public: AnimateFunctor(TreeInfo& info, AnimationContext& context) : dirtyMask(0), mInfo(info), mContext(context) {} - bool operator() (BaseRenderNodeAnimator* animator) { + bool operator() (sp<BaseRenderNodeAnimator>& animator) { dirtyMask |= animator->dirtyMask(); bool remove = animator->animate(mContext); if (remove) { - animator->decStrong(nullptr); + animator->detach(); } else { if (animator->isRunning()) { mInfo.out.hasAnimations = true; @@ -129,20 +144,18 @@ void AnimatorManager::animateNoDamage(TreeInfo& info) { uint32_t AnimatorManager::animateCommon(TreeInfo& info) { AnimateFunctor functor(info, mAnimationHandle->context()); - std::vector< BaseRenderNodeAnimator* >::iterator newEnd; - newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor); + auto newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor); mAnimators.erase(newEnd, mAnimators.end()); mAnimationHandle->notifyAnimationsRan(); mParent.mProperties.updateMatrix(); return functor.dirtyMask; } -static void endStagingAnimator(BaseRenderNodeAnimator* animator) { - animator->end(); +static void endStagingAnimator(sp<BaseRenderNodeAnimator>& animator) { + animator->cancel(); if (animator->listener()) { - animator->listener()->onAnimationFinished(animator); + animator->listener()->onAnimationFinished(animator.get()); } - animator->decStrong(nullptr); } void AnimatorManager::endAllStagingAnimators() { @@ -157,9 +170,8 @@ class EndActiveAnimatorsFunctor { public: EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {} - void operator() (BaseRenderNodeAnimator* animator) { + void operator() (sp<BaseRenderNodeAnimator>& animator) { animator->forceEndNow(mContext); - animator->decStrong(nullptr); } private: diff --git a/libs/hwui/AnimatorManager.h b/libs/hwui/AnimatorManager.h index fb75eb8599b4..61f6179d217c 100644 --- a/libs/hwui/AnimatorManager.h +++ b/libs/hwui/AnimatorManager.h @@ -39,11 +39,13 @@ public: ~AnimatorManager(); void addAnimator(const sp<BaseRenderNodeAnimator>& animator); + void removeAnimator(const sp<BaseRenderNodeAnimator>& animator); void setAnimationHandle(AnimationHandle* handle); bool hasAnimationHandle() { return mAnimationHandle; } void pushStaging(); + void onAnimatorTargetChanged(BaseRenderNodeAnimator* animator); // Returns the combined dirty mask of all animators run uint32_t animate(TreeInfo& info); @@ -66,9 +68,8 @@ private: AnimationHandle* mAnimationHandle; // To improve the efficiency of resizing & removing from the vector - // use manual ref counting instead of sp<>. - std::vector<BaseRenderNodeAnimator*> mNewAnimators; - std::vector<BaseRenderNodeAnimator*> mAnimators; + std::vector< sp<BaseRenderNodeAnimator> > mNewAnimators; + std::vector< sp<BaseRenderNodeAnimator> > mAnimators; }; } /* namespace uirenderer */ diff --git a/libs/hwui/PropertyValuesAnimatorSet.cpp b/libs/hwui/PropertyValuesAnimatorSet.cpp index eca1afcc54dc..b29f91ff34aa 100644 --- a/libs/hwui/PropertyValuesAnimatorSet.cpp +++ b/libs/hwui/PropertyValuesAnimatorSet.cpp @@ -17,6 +17,8 @@ #include "PropertyValuesAnimatorSet.h" #include "RenderNode.h" +#include <algorithm> + namespace android { namespace uirenderer { @@ -53,16 +55,26 @@ void PropertyValuesAnimatorSet::setValue(RenderNode* target, float value) { } void PropertyValuesAnimatorSet::onPlayTimeChanged(nsecs_t playTime) { - for (size_t i = 0; i < mAnimators.size(); i++) { - mAnimators[i]->setCurrentPlayTime(playTime); + if (playTime == 0 && mDuration > 0) { + // Reset all the animators + for (auto it = mAnimators.rbegin(); it != mAnimators.rend(); it++) { + // Note that this set may containing animators modifying the same property, so when we + // reset the animators, we need to make sure the animators that end the first will + // have the final say on what the property value should be. + (*it)->setFraction(0); + } + } else if (playTime >= mDuration) { + // Skip all the animators to end + for (auto& anim : mAnimators) { + anim->setFraction(1); + } + } else { + for (auto& anim : mAnimators) { + anim->setCurrentPlayTime(playTime); + } } } -void PropertyValuesAnimatorSet::reset() { - // TODO: implement reset through adding a play state because we need to support reset() even - // during an animation run. -} - void PropertyValuesAnimatorSet::start(AnimationListener* listener) { init(); mOneShotListener = listener; @@ -70,20 +82,23 @@ void PropertyValuesAnimatorSet::start(AnimationListener* listener) { } void PropertyValuesAnimatorSet::reverse(AnimationListener* listener) { -// TODO: implement reverse + init(); + mOneShotListener = listener; + BaseRenderNodeAnimator::reverse(); } void PropertyValuesAnimatorSet::init() { if (mInitialized) { return; } - nsecs_t maxDuration = 0; - for (size_t i = 0; i < mAnimators.size(); i++) { - if (maxDuration < mAnimators[i]->getTotalDuration()) { - maxDuration = mAnimators[i]->getTotalDuration(); - } - } - mDuration = maxDuration; + + // Sort the animators by their total duration. Note that all the animators in the set start at + // the same time, so the ones with longer total duration (which includes start delay) will + // be the ones that end later. + std::sort(mAnimators.begin(), mAnimators.end(), [](auto& a, auto&b) { + return a->getTotalDuration() < b->getTotalDuration(); + }); + mDuration = mAnimators[mAnimators.size() - 1]->getTotalDuration(); mInitialized = true; } @@ -106,18 +121,19 @@ PropertyAnimator::PropertyAnimator(PropertyValuesHolder* holder, Interpolator* i void PropertyAnimator::setCurrentPlayTime(nsecs_t playTime) { if (playTime >= mStartDelay && playTime < mTotalDuration) { nsecs_t currentIterationPlayTime = (playTime - mStartDelay) % mDuration; - mLatestFraction = currentIterationPlayTime / (float) mDuration; + float fraction = currentIterationPlayTime / (float) mDuration; + setFraction(fraction); } else if (mLatestFraction < 1.0f && playTime >= mTotalDuration) { - mLatestFraction = 1.0f; - } else { - return; + // This makes sure we only set the fraction = 1 once. It is needed because there might + // be another animator modifying the same property after this animator finishes, we need + // to make sure we don't set conflicting values on the same property within one frame. + setFraction(1.0f); } - - setFraction(mLatestFraction); } void PropertyAnimator::setFraction(float fraction) { - float interpolatedFraction = mInterpolator->interpolate(mLatestFraction); + mLatestFraction = fraction; + float interpolatedFraction = mInterpolator->interpolate(fraction); mPropertyValuesHolder->setFraction(interpolatedFraction); } diff --git a/libs/hwui/PropertyValuesAnimatorSet.h b/libs/hwui/PropertyValuesAnimatorSet.h index 4c7ce528bb20..c7ae7c0e8ce1 100644 --- a/libs/hwui/PropertyValuesAnimatorSet.h +++ b/libs/hwui/PropertyValuesAnimatorSet.h @@ -50,7 +50,6 @@ public: void start(AnimationListener* listener); void reverse(AnimationListener* listener); - void reset(); void addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder, Interpolator* interpolators, int64_t startDelays, diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp index 269e590892d3..0adb21cd8884 100644 --- a/libs/hwui/RecordingCanvas.cpp +++ b/libs/hwui/RecordingCanvas.cpp @@ -406,12 +406,16 @@ void RecordingCanvas::drawOval(float left, float top, float right, float bottom, void RecordingCanvas::drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) { - addOp(alloc().create_trivial<ArcOp>( - Rect(left, top, right, bottom), - *(mState.currentSnapshot()->transform), - getRecordedClip(), - refPaint(&paint), - startAngle, sweepAngle, useCenter)); + if (fabs(sweepAngle) >= 360.0f) { + drawOval(left, top, right, bottom, paint); + } else { + addOp(alloc().create_trivial<ArcOp>( + Rect(left, top, right, bottom), + *(mState.currentSnapshot()->transform), + getRecordedClip(), + refPaint(&paint), + startAngle, sweepAngle, useCenter)); + } } void RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) { diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index bade216b3b21..9ac76a4339e1 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -218,6 +218,10 @@ void RenderNode::addAnimator(const sp<BaseRenderNodeAnimator>& animator) { mAnimatorManager.addAnimator(animator); } +void RenderNode::removeAnimator(const sp<BaseRenderNodeAnimator>& animator) { + mAnimatorManager.removeAnimator(animator); +} + void RenderNode::damageSelf(TreeInfo& info) { if (isRenderable()) { if (properties().getClipDamageToBounds()) { diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h index f248de54acba..e0376450178f 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -187,6 +187,12 @@ public: // UI thread only! ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator); + void removeAnimator(const sp<BaseRenderNodeAnimator>& animator); + + // This can only happen during pushStaging() + void onAnimatorTargetChanged(BaseRenderNodeAnimator* animator) { + mAnimatorManager.onAnimatorTargetChanged(animator); + } AnimatorManager& animators() { return mAnimatorManager; } diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp index 3440d03b4fc5..9595a85e99dd 100644 --- a/libs/hwui/tests/common/TestUtils.cpp +++ b/libs/hwui/tests/common/TestUtils.cpp @@ -162,6 +162,7 @@ void TestUtils::TestTask::run() { renderState.onGLContextCreated(); rtCallback(renderthread::RenderThread::getInstance()); + renderState.flush(Caches::FlushMode::Full); renderState.onGLContextDestroyed(); // Restore the previous signal handler diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp index 20d2f1f18c58..cd9ffc5590f8 100644 --- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp +++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp @@ -57,6 +57,22 @@ TEST(RecordingCanvas, clipRect) { << "Clip should be serialized once"; } +TEST(RecordingCanvas, drawArc) { + auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) { + canvas.drawArc(0, 0, 200, 200, 0, 180, true, SkPaint()); + canvas.drawArc(0, 0, 100, 100, 0, 360, true, SkPaint()); + }); + + auto&& ops = dl->getOps(); + ASSERT_EQ(2u, ops.size()) << "Must be exactly two ops"; + EXPECT_EQ(RecordedOpId::ArcOp, ops[0]->opId); + EXPECT_EQ(Rect(200, 200), ops[0]->unmappedBounds); + + EXPECT_EQ(RecordedOpId::OvalOp, ops[1]->opId) + << "Circular arcs should be converted to ovals"; + EXPECT_EQ(Rect(100, 100), ops[1]->unmappedBounds); +} + TEST(RecordingCanvas, drawLines) { auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) { SkPaint paint; diff --git a/location/java/android/location/GnssClock.java b/location/java/android/location/GnssClock.java index 37ef3df7990f..5ba3f2c27a13 100644 --- a/location/java/android/location/GnssClock.java +++ b/location/java/android/location/GnssClock.java @@ -73,7 +73,7 @@ public final class GnssClock implements Parcelable { private double mBiasUncertaintyInNs; private double mDriftInNsPerSec; private double mDriftUncertaintyInNsPerSec; - private long mTimeOfLastHwClockDiscontinuityInNs; + private int mHardwareClockDiscontinuityCount; GnssClock() { initialize(); @@ -93,7 +93,7 @@ public final class GnssClock implements Parcelable { mBiasUncertaintyInNs = clock.mBiasUncertaintyInNs; mDriftInNsPerSec = clock.mDriftInNsPerSec; mDriftUncertaintyInNsPerSec = clock.mDriftUncertaintyInNsPerSec; - mTimeOfLastHwClockDiscontinuityInNs = clock.mTimeOfLastHwClockDiscontinuityInNs; + mHardwareClockDiscontinuityCount = clock.mHardwareClockDiscontinuityCount; } /** @@ -395,17 +395,17 @@ public final class GnssClock implements Parcelable { } /** - * Gets time of last hardware clock discontinuity. + * Gets count of last hardware clock discontinuity. */ - public long getTimeOfLastHwClockDiscontinuityInNs() { - return mTimeOfLastHwClockDiscontinuityInNs; + public int getHardwareClockDiscontinuityCount() { + return mHardwareClockDiscontinuityCount; } /** - * Sets time of last hardware clock discontinuity. + * Sets count of last hardware clock discontinuity. */ - public void setTimeOfLastHwClockDiscontinuityInNs(long timeOfLastHwClockDiscontinuityInNs) { - mTimeOfLastHwClockDiscontinuityInNs = timeOfLastHwClockDiscontinuityInNs; + public void setHardwareClockDiscontinuityCount(int value) { + mHardwareClockDiscontinuityCount = value; } /** @@ -431,7 +431,7 @@ public final class GnssClock implements Parcelable { gpsClock.mBiasUncertaintyInNs = parcel.readDouble(); gpsClock.mDriftInNsPerSec = parcel.readDouble(); gpsClock.mDriftUncertaintyInNsPerSec = parcel.readDouble(); - gpsClock.mTimeOfLastHwClockDiscontinuityInNs = parcel.readLong(); + gpsClock.mHardwareClockDiscontinuityCount = parcel.readInt(); return gpsClock; } @@ -442,6 +442,7 @@ public final class GnssClock implements Parcelable { } }; + @Override public void writeToParcel(Parcel parcel, int flags) { parcel.writeInt(mFlags); parcel.writeInt(mLeapSecond); @@ -453,7 +454,7 @@ public final class GnssClock implements Parcelable { parcel.writeDouble(mBiasUncertaintyInNs); parcel.writeDouble(mDriftInNsPerSec); parcel.writeDouble(mDriftUncertaintyInNsPerSec); - parcel.writeLong(mTimeOfLastHwClockDiscontinuityInNs); + parcel.writeInt(mHardwareClockDiscontinuityCount); } @Override @@ -497,9 +498,9 @@ public final class GnssClock implements Parcelable { "DriftUncertaintyInNsPerSec", hasDriftUncertaintyInNsPerSec() ? mDriftUncertaintyInNsPerSec : null)); - builder.append(String.format(format, "TimeOfLastHwClockDiscontinuityInNs", + builder.append(String.format(format, "HardwareClockDiscontinuityCount", getType() == CLOCK_TYPE_LOCAL_HW_TIME - ? mTimeOfLastHwClockDiscontinuityInNs : null)); + ? mHardwareClockDiscontinuityCount : null)); return builder.toString(); } @@ -515,7 +516,7 @@ public final class GnssClock implements Parcelable { resetBiasUncertaintyInNs(); resetDriftInNsPerSec(); resetDriftUncertaintyInNsPerSec(); - setTimeOfLastHwClockDiscontinuityInNs(Long.MIN_VALUE); + setHardwareClockDiscontinuityCount(Integer.MIN_VALUE); } private void setFlag(short flag) { diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java index a490685a3a8b..a619ab293ded 100644 --- a/location/java/android/location/GnssMeasurement.java +++ b/location/java/android/location/GnssMeasurement.java @@ -24,15 +24,16 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** - * A class representing a GPS satellite measurement, containing raw and computed information. + * A class representing a GNSS satellite measurement, containing raw and computed information. */ public final class GnssMeasurement implements Parcelable { private int mFlags; private short mSvid; + private byte mConstellationType; private double mTimeOffsetInNs; private short mState; - private long mReceivedGpsTowInNs; - private long mReceivedGpsTowUncertaintyInNs; + private long mReceivedSvTimeInNs; + private long mReceivedSvTimeUncertaintyInNs; private double mCn0InDbHz; private double mPseudorangeRateInMetersPerSec; private double mPseudorangeRateUncertaintyInMetersPerSec; @@ -59,8 +60,6 @@ public final class GnssMeasurement implements Parcelable { private double mAzimuthInDeg; private double mAzimuthUncertaintyInDeg; private boolean mUsedInFix; - private double mPseudorangeRateCarrierInMetersPerSec; - private double mPseudorangeRateCarrierUncertaintyInMetersPerSec; // The following enumerations must be in sync with the values declared in gps.h @@ -82,8 +81,8 @@ public final class GnssMeasurement implements Parcelable { private static final int HAS_TIME_FROM_LAST_BIT = (1<<14); private static final int HAS_DOPPLER_SHIFT = (1<<15); private static final int HAS_DOPPLER_SHIFT_UNCERTAINTY = (1<<16); - private static final int HAS_USED_IN_FIX = (1<<17); - private static final int GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE = (1<<18); + // private static final int HAS_USED_IN_FIX = (1<<17); + private static final int HAS_UNCORRECTED_PSEUDORANGE_RATE = (1<<18); /** The status of 'loss of lock'. */ @Retention(RetentionPolicy.SOURCE) @@ -127,37 +126,37 @@ public final class GnssMeasurement implements Parcelable { public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; /** - * The state of GPS receiver the measurement is invalid or unknown. + * The state of GNSS receiver the measurement is invalid or unknown. */ public static final short STATE_UNKNOWN = 0; /** - * The state of the GPS receiver is ranging code lock. + * The state of the GNSS receiver is ranging code lock. */ public static final short STATE_CODE_LOCK = (1<<0); /** - * The state of the GPS receiver is in bit sync. + * The state of the GNSS receiver is in bit sync. */ public static final short STATE_BIT_SYNC = (1<<1); /** - *The state of the GPS receiver is in sub-frame sync. + *The state of the GNSS receiver is in sub-frame sync. */ public static final short STATE_SUBFRAME_SYNC = (1<<2); /** - * The state of the GPS receiver has TOW decoded. + * The state of the GNSS receiver has TOW decoded. */ public static final short STATE_TOW_DECODED = (1<<3); /** - * The state of the GPS receiver contains millisecond ambiguity. + * The state of the GNSS receiver contains millisecond ambiguity. */ public static final short STATE_MSEC_AMBIGUOUS = (1<<4); /** - * All the GPS receiver state flags. + * All the GNSS receiver state flags. */ private static final short STATE_ALL = STATE_CODE_LOCK | STATE_BIT_SYNC | STATE_SUBFRAME_SYNC | STATE_TOW_DECODED | STATE_MSEC_AMBIGUOUS; @@ -199,10 +198,11 @@ public final class GnssMeasurement implements Parcelable { public void set(GnssMeasurement measurement) { mFlags = measurement.mFlags; mSvid = measurement.mSvid; + mConstellationType = measurement.mConstellationType; mTimeOffsetInNs = measurement.mTimeOffsetInNs; mState = measurement.mState; - mReceivedGpsTowInNs = measurement.mReceivedGpsTowInNs; - mReceivedGpsTowUncertaintyInNs = measurement.mReceivedGpsTowUncertaintyInNs; + mReceivedSvTimeInNs = measurement.mReceivedSvTimeInNs; + mReceivedSvTimeUncertaintyInNs = measurement.mReceivedSvTimeUncertaintyInNs; mCn0InDbHz = measurement.mCn0InDbHz; mPseudorangeRateInMetersPerSec = measurement.mPseudorangeRateInMetersPerSec; mPseudorangeRateUncertaintyInMetersPerSec = @@ -231,10 +231,6 @@ public final class GnssMeasurement implements Parcelable { mAzimuthInDeg = measurement.mAzimuthInDeg; mAzimuthUncertaintyInDeg = measurement.mAzimuthUncertaintyInDeg; mUsedInFix = measurement.mUsedInFix; - mPseudorangeRateCarrierInMetersPerSec = - measurement.mPseudorangeRateCarrierInMetersPerSec; - mPseudorangeRateCarrierUncertaintyInMetersPerSec = - measurement.mPseudorangeRateCarrierUncertaintyInMetersPerSec; } /** @@ -260,6 +256,21 @@ public final class GnssMeasurement implements Parcelable { } /** + * Getst the constellation type. + */ + @GnssStatus.ConstellationType + public byte getConstellationType() { + return mConstellationType; + } + + /** + * Sets the constellation type. + */ + public void setConstellationType(@GnssStatus.ConstellationType byte value) { + mConstellationType = value; + } + + /** * Gets the time offset at which the measurement was taken in nanoseconds. * The reference receiver's time is specified by {@link GnssClock#getTimeInNs()} and should be * interpreted in the same way as indicated by {@link GnssClock#getType()}. @@ -285,7 +296,7 @@ public final class GnssMeasurement implements Parcelable { * Gets per-satellite sync state. * It represents the current sync state for the associated satellite. * - * This value helps interpret {@link #getReceivedGpsTowInNs()}. + * This value helps interpret {@link #getReceivedSvTimeInNs()}. */ public short getState() { return mState; @@ -333,39 +344,92 @@ public final class GnssMeasurement implements Parcelable { } /** - * Gets the received GPS Time-of-Week at the measurement time, in nanoseconds. - * The value is relative to the beginning of the current GPS week. + * Gets the received GNSS satellite time, at the measurement time, in nanoseconds. + * + * For GPS & QZSS, this is: + * Received GPS Time-of-Week at the measurement time, in nanoseconds. + * The value is relative to the beginning of the current GPS week. + * + * Given the highest sync state that can be achieved, per each satellite, valid range + * for this field can be: + * Searching : [ 0 ] : STATE_UNKNOWN + * C/A code lock : [ 0 1ms ] : STATE_CODE_LOCK is set + * Bit sync : [ 0 20ms ] : STATE_BIT_SYNC is set + * Subframe sync : [ 0 6s ] : STATE_SUBFRAME_SYNC is set + * TOW decoded : [ 0 1week ] : STATE_TOW_DECODED is set + * + * Note well: if there is any ambiguity in integer millisecond, + * STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field. + * + * This value must be populated if 'state' != STATE_UNKNOWN. + * + * For Glonass, this is: + * Received Glonass time of day, at the measurement time in nanoseconds. + * + * Given the highest sync state that can be achieved, per each satellite, valid range for + * this field can be: + * Searching : [ 0 ] : STATE_UNKNOWN + * C/A code lock : [ 0 1ms ] : STATE_CODE_LOCK is set + * Symbol sync : [ 0 10ms ] : STATE_SYMBOL_SYNC is set + * Bit sync : [ 0 20ms ] : STATE_BIT_SYNC is set + * String sync : [ 0 2s ] : STATE_GLO_STRING_SYNC is set + * Time of day : [ 0 1day ] : STATE_GLO_TOD_DECODED is set + * + * For Beidou, this is: + * Received Beidou time of week, at the measurement time in nanoseconds. + * + * Given the highest sync state that can be achieved, per each satellite, valid range for + * this field can be: + * Searching : [ 0 ] : STATE_UNKNOWN + * C/A code lock : [ 0 1ms ] : STATE_CODE_LOCK is set + * Bit sync (D2) : [ 0 2ms ] : STATE_BDS_D2_BIT_SYNC is set + * Bit sync (D1) : [ 0 20ms ] : STATE_BIT_SYNC is set + * Subframe (D2) : [ 0 0.6s ] : STATE_BDS_D2_SUBFRAME_SYNC is set + * Subframe (D1) : [ 0 6s ] : STATE_SUBFRAME_SYNC is set + * Time of week : [ 0 1week ] : STATE_TOW_DECODED is set + * + * For Galileo, this is: + * Received Galileo time of week, at the measurement time in nanoseconds. + * + * E1BC code lock : [ 0 4ms ] : STATE_GAL_E1BC_CODE_LOCK is set + * E1C 2nd code lock : [ 0 100ms ] : STATE_GAL_E1C_2ND_CODE_LOCK is set + * + * E1B page : [ 0 2s ] : STATE_GAL_E1B_PAGE_SYNC is set + * Time of week : [ 0 1week ] : STATE_GAL_TOW_DECODED is set * - * Given {@link #getState()} of the GPS receiver, the range of this field can be: - * Searching : [ 0 ] : {@link #STATE_UNKNOWN} is set - * Ranging code lock : [ 0 1 ms ] : {@link #STATE_CODE_LOCK} is set - * Bit sync : [ 0 20 ms ] : {@link #STATE_BIT_SYNC} is set - * Subframe sync : [ 0 6 ms ] : {@link #STATE_SUBFRAME_SYNC} is set - * TOW decoded : [ 0 1 week ] : {@link #STATE_TOW_DECODED} is set + * For SBAS, this is: + * Received SBAS time, at the measurement time in nanoseconds. + * + * Given the highest sync state that can be achieved, per each satellite, valid range for + * this field can be: + * Searching : [ 0 ] : STATE_UNKNOWN + * C/A code lock : [ 0 1ms ] : STATE_CODE_LOCK is set + * Symbol sync : [ 0 2ms ] : STATE_SYMBOL_SYNC is set + * Message : [ 0 1s ] : STATE_SBAS_SYNC is set */ - public long getReceivedGpsTowInNs() { - return mReceivedGpsTowInNs; + public long getReceivedSvTimeInNs() { + return mReceivedSvTimeInNs; } /** - * Sets the received GPS time-of-week in nanoseconds. + * Sets the received GNSS time in nanoseconds. */ - public void setReceivedGpsTowInNs(long value) { - mReceivedGpsTowInNs = value; + public void setReceivedSvTimeInNs(long value) { + mReceivedSvTimeInNs = value; } /** - * Gets the received GPS time-of-week's uncertainty (1-Sigma) in nanoseconds. + * Gets the received GNSS time uncertainty (1-Sigma) in nanoseconds. */ - public long getReceivedGpsTowUncertaintyInNs() { - return mReceivedGpsTowUncertaintyInNs; + public long getReceivedSvTimeUncertaintyInNs() { + return mReceivedSvTimeUncertaintyInNs; } /** - * Sets the received GPS time-of-week's uncertainty (1-Sigma) in nanoseconds. + * Sets the received GNSS time uncertainty (1-Sigma) in nanoseconds. */ - public void setReceivedGpsTowUncertaintyInNs(long value) { - mReceivedGpsTowUncertaintyInNs = value; + public void setReceivedSvTimeUncertaintyInNs(long value) { + mReceivedSvTimeUncertaintyInNs = value; } /** @@ -416,7 +480,7 @@ public final class GnssMeasurement implements Parcelable { * value, {@code false} if it contains an uncorrected value. */ public boolean isPseudorangeRateCorrected() { - return !isFlagSet(GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE); + return !isFlagSet(HAS_UNCORRECTED_PSEUDORANGE_RATE); } /** @@ -1160,7 +1224,7 @@ public final class GnssMeasurement implements Parcelable { } /** - * Gets a flag indicating whether the GPS represented by the measurement was used for computing + * Gets a flag indicating whether the GNSS represented by the measurement was used for computing * the most recent fix. * * @return A non-null value if the data is available, null otherwise. @@ -1176,34 +1240,6 @@ public final class GnssMeasurement implements Parcelable { mUsedInFix = value; } - /** - * Gets pseudorange rate (based on carrier phase changes) at the timestamp in m/s. - */ - public double getPseudorangeRateCarrierInMetersPerSec() { - return mPseudorangeRateCarrierInMetersPerSec; - } - - /** - * Sets pseudorange rate (based on carrier phase changes) at the timestamp in m/s. - */ - public void setPseudorangeRateCarrierInMetersPerSec(double value) { - mPseudorangeRateCarrierInMetersPerSec = value; - } - - /** - * Gets 1-Sigma uncertainty of the pseudorange rate carrier. - */ - public double getPseudorangeRateCarrierUncertaintyInMetersPerSec() { - return mPseudorangeRateCarrierUncertaintyInMetersPerSec; - } - - /** - * Sets 1-Sigma uncertainty of the pseudorange rate carrier. - */ - public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double value) { - mPseudorangeRateCarrierUncertaintyInMetersPerSec = value; - } - public static final Creator<GnssMeasurement> CREATOR = new Creator<GnssMeasurement>() { @Override public GnssMeasurement createFromParcel(Parcel parcel) { @@ -1211,10 +1247,11 @@ public final class GnssMeasurement implements Parcelable { gnssMeasurement.mFlags = parcel.readInt(); gnssMeasurement.mSvid = (short) parcel.readInt(); + gnssMeasurement.mConstellationType = parcel.readByte(); gnssMeasurement.mTimeOffsetInNs = parcel.readDouble(); gnssMeasurement.mState = (short) parcel.readInt(); - gnssMeasurement.mReceivedGpsTowInNs = parcel.readLong(); - gnssMeasurement.mReceivedGpsTowUncertaintyInNs = parcel.readLong(); + gnssMeasurement.mReceivedSvTimeInNs = parcel.readLong(); + gnssMeasurement.mReceivedSvTimeUncertaintyInNs = parcel.readLong(); gnssMeasurement.mCn0InDbHz = parcel.readDouble(); gnssMeasurement.mPseudorangeRateInMetersPerSec = parcel.readDouble(); gnssMeasurement.mPseudorangeRateUncertaintyInMetersPerSec = parcel.readDouble(); @@ -1241,8 +1278,6 @@ public final class GnssMeasurement implements Parcelable { gnssMeasurement.mAzimuthInDeg = parcel.readDouble(); gnssMeasurement.mAzimuthUncertaintyInDeg = parcel.readDouble(); gnssMeasurement.mUsedInFix = parcel.readInt() != 0; - gnssMeasurement.mPseudorangeRateCarrierInMetersPerSec = parcel.readDouble(); - gnssMeasurement.mPseudorangeRateCarrierUncertaintyInMetersPerSec = parcel.readDouble(); return gnssMeasurement; } @@ -1257,10 +1292,11 @@ public final class GnssMeasurement implements Parcelable { public void writeToParcel(Parcel parcel, int flags) { parcel.writeInt(mFlags); parcel.writeInt(mSvid); + parcel.writeByte(mConstellationType); parcel.writeDouble(mTimeOffsetInNs); parcel.writeInt(mState); - parcel.writeLong(mReceivedGpsTowInNs); - parcel.writeLong(mReceivedGpsTowUncertaintyInNs); + parcel.writeLong(mReceivedSvTimeInNs); + parcel.writeLong(mReceivedSvTimeUncertaintyInNs); parcel.writeDouble(mCn0InDbHz); parcel.writeDouble(mPseudorangeRateInMetersPerSec); parcel.writeDouble(mPseudorangeRateUncertaintyInMetersPerSec); @@ -1287,8 +1323,6 @@ public final class GnssMeasurement implements Parcelable { parcel.writeDouble(mAzimuthInDeg); parcel.writeDouble(mAzimuthUncertaintyInDeg); parcel.writeInt(mUsedInFix ? 1 : 0); - parcel.writeDouble(mPseudorangeRateCarrierInMetersPerSec); - parcel.writeDouble(mPseudorangeRateCarrierUncertaintyInMetersPerSec); } @Override @@ -1303,17 +1337,17 @@ public final class GnssMeasurement implements Parcelable { StringBuilder builder = new StringBuilder("GnssMeasurement:\n"); builder.append(String.format(format, "Svid", mSvid)); - + builder.append(String.format(format, "ConstellationType", mConstellationType)); builder.append(String.format(format, "TimeOffsetInNs", mTimeOffsetInNs)); builder.append(String.format(format, "State", getStateString())); builder.append(String.format( formatWithUncertainty, - "ReceivedGpsTowInNs", - mReceivedGpsTowInNs, - "ReceivedGpsTowUncertaintyInNs", - mReceivedGpsTowUncertaintyInNs)); + "ReceivedSvTimeInNs", + mReceivedSvTimeInNs, + "ReceivedSvTimeUncertaintyInNs", + mReceivedSvTimeUncertaintyInNs)); builder.append(String.format(format, "Cn0InDbHz", mCn0InDbHz)); @@ -1413,11 +1447,6 @@ public final class GnssMeasurement implements Parcelable { builder.append(String.format(format, "UsedInFix", mUsedInFix)); - builder.append(String.format(format, "PseudorangeRateCarrierInMetersPerSec", - mPseudorangeRateCarrierInMetersPerSec)); - builder.append(String.format(format, "PseudorangeRateCarrierUncertaintyInMetersPerSec", - mPseudorangeRateCarrierUncertaintyInMetersPerSec)); - return builder.toString(); } @@ -1426,8 +1455,8 @@ public final class GnssMeasurement implements Parcelable { setSvid((short) 0); setTimeOffsetInNs(Long.MIN_VALUE); setState(STATE_UNKNOWN); - setReceivedGpsTowInNs(Long.MIN_VALUE); - setReceivedGpsTowUncertaintyInNs(Long.MAX_VALUE); + setReceivedSvTimeInNs(Long.MIN_VALUE); + setReceivedSvTimeUncertaintyInNs(Long.MAX_VALUE); setCn0InDbHz(Double.MIN_VALUE); setPseudorangeRateInMetersPerSec(Double.MIN_VALUE); setPseudorangeRateUncertaintyInMetersPerSec(Double.MIN_VALUE); @@ -1454,8 +1483,6 @@ public final class GnssMeasurement implements Parcelable { resetAzimuthInDeg(); resetAzimuthUncertaintyInDeg(); setUsedInFix(false); - setPseudorangeRateCarrierInMetersPerSec(Double.MIN_VALUE); - setPseudorangeRateCarrierUncertaintyInMetersPerSec(Double.MIN_VALUE); } private void setFlag(int flag) { diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java index 86328eb5dcd7..faefd0bbe543 100644 --- a/location/java/android/location/GnssNavigationMessage.java +++ b/location/java/android/location/GnssNavigationMessage.java @@ -34,36 +34,33 @@ public final class GnssNavigationMessage implements Parcelable { /** The type of the GPS Clock. */ @Retention(RetentionPolicy.SOURCE) - @IntDef({MESSAGE_TYPE_UNKNOWN, MESSAGE_TYPE_L1CA, MESSAGE_TYPE_L2CNAV, MESSAGE_TYPE_L5CNAV, - MESSAGE_TYPE_CNAV2}) + @IntDef({MESSAGE_TYPE_UNKNOWN, MESSAGE_TYPE_GPS_L1CA, MESSAGE_TYPE_GPS_L2CNAV, + MESSAGE_TYPE_GPS_L5CNAV, MESSAGE_TYPE_GPS_CNAV2, MESSAGE_TYPE_GLO_L1CA, MESSAGE_TYPE_BDS_D1, + MESSAGE_TYPE_BDS_D2, MESSAGE_TYPE_GAL_I, MESSAGE_TYPE_GAL_F}) public @interface GnssNavigationMessageType {} // The following enumerations must be in sync with the values declared in gps.h - /** - * The type of the navigation message is not available or unknown. - */ - public static final byte MESSAGE_TYPE_UNKNOWN = 0; - - /** - * The Navigation Message is of type L1 C/A. - */ - public static final byte MESSAGE_TYPE_L1CA = 1; - - /** - * The Navigation Message is of type L1-CNAV. - */ - public static final byte MESSAGE_TYPE_L2CNAV = 2; - - /** - * The Navigation Message is of type L5-CNAV. - */ - public static final byte MESSAGE_TYPE_L5CNAV = 3; - - /** - * The Navigation Message is of type CNAV-2. - */ - public static final byte MESSAGE_TYPE_CNAV2 = 4; + /** Message type unknown */ + public static final short MESSAGE_TYPE_UNKNOWN = 0; + /** GPS L1 C/A message contained in the structure. */ + public static final short MESSAGE_TYPE_GPS_L1CA = 0x0101; + /** GPS L2-CNAV message contained in the structure. */ + public static final short MESSAGE_TYPE_GPS_L2CNAV = 0x0102; + /** GPS L5-CNAV message contained in the structure. */ + public static final short MESSAGE_TYPE_GPS_L5CNAV = 0x0103; + /** GPS CNAV-2 message contained in the structure. */ + public static final short MESSAGE_TYPE_GPS_CNAV2 = 0x0104; + /** Glonass L1 CA message contained in the structure. */ + public static final short MESSAGE_TYPE_GLO_L1CA = 0x0301; + /** Beidou D1 message contained in the structure. */ + public static final short MESSAGE_TYPE_BDS_D1 = 0x0501; + /** Beidou D2 message contained in the structure. */ + public static final short MESSAGE_TYPE_BDS_D2 = 0x0502; + /** Galileo I/NAV message contained in the structure. */ + public static final short MESSAGE_TYPE_GAL_I = 0x0601; + /** Galileo F/NAV message contained in the structure. */ + public static final short MESSAGE_TYPE_GAL_F = 0x0602; /** * The Navigation Message Status is 'unknown'. @@ -83,7 +80,7 @@ public final class GnssNavigationMessage implements Parcelable { // End enumerations in sync with gps.h - private byte mType; + private short mType; private short mSvid; private short mMessageId; private short mSubmessageId; @@ -117,14 +114,14 @@ public final class GnssNavigationMessage implements Parcelable { * Gets the type of the navigation message contained in the object. */ @GnssNavigationMessageType - public byte getType() { + public short getType() { return mType; } /** * Sets the type of the navigation message. */ - public void setType(@GnssNavigationMessageType byte value) { + public void setType(@GnssNavigationMessageType short value) { mType = value; } @@ -136,14 +133,24 @@ public final class GnssNavigationMessage implements Parcelable { switch (mType) { case MESSAGE_TYPE_UNKNOWN: return "Unknown"; - case MESSAGE_TYPE_L1CA: - return "L1 C/A"; - case MESSAGE_TYPE_L2CNAV: - return "L2-CNAV"; - case MESSAGE_TYPE_L5CNAV: - return "L5-CNAV"; - case MESSAGE_TYPE_CNAV2: - return "CNAV-2"; + case MESSAGE_TYPE_GPS_L1CA: + return "GPS L1 C/A"; + case MESSAGE_TYPE_GPS_L2CNAV: + return "GPS L2-CNAV"; + case MESSAGE_TYPE_GPS_L5CNAV: + return "GPS L5-CNAV"; + case MESSAGE_TYPE_GPS_CNAV2: + return "GPS CNAV2"; + case MESSAGE_TYPE_GLO_L1CA: + return "Glonass L1 C/A"; + case MESSAGE_TYPE_BDS_D1: + return "Beidou D1"; + case MESSAGE_TYPE_BDS_D2: + return "Beidou D2"; + case MESSAGE_TYPE_GAL_I: + return "Galileo I"; + case MESSAGE_TYPE_GAL_F: + return "Galileo F"; default: return "<Invalid:" + mType + ">"; } @@ -255,7 +262,7 @@ public final class GnssNavigationMessage implements Parcelable { public GnssNavigationMessage createFromParcel(Parcel parcel) { GnssNavigationMessage navigationMessage = new GnssNavigationMessage(); - navigationMessage.setType(parcel.readByte()); + navigationMessage.setType((short) parcel.readInt()); navigationMessage.setSvid((short) parcel.readInt()); navigationMessage.setMessageId((short) parcel.readInt()); navigationMessage.setSubmessageId((short) parcel.readInt()); @@ -283,7 +290,7 @@ public final class GnssNavigationMessage implements Parcelable { @Override public void writeToParcel(Parcel parcel, int flags) { - parcel.writeByte(mType); + parcel.writeInt(mType); parcel.writeInt(mSvid); parcel.writeInt(mMessageId); parcel.writeInt(mSubmessageId); diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java index 906e944f06ab..06ce30c97887 100644 --- a/location/java/android/location/GnssStatus.java +++ b/location/java/android/location/GnssStatus.java @@ -16,25 +16,36 @@ package android.location; +import android.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * This class represents the current state of the GNSS engine. * This class is used in conjunction with the {@link GnssStatusCallback}. */ public final class GnssStatus { /** Unknown constellation type. */ - public static final int CONSTELLATION_UNKNOWN = 0; + public static final byte CONSTELLATION_UNKNOWN = 0; /** Constellation type constant for GPS. */ - public static final int CONSTELLATION_GPS = 1; + public static final byte CONSTELLATION_GPS = 1; /** Constellation type constant for SBAS. */ - public static final int CONSTELLATION_SBAS = 2; + public static final byte CONSTELLATION_SBAS = 2; /** Constellation type constant for Glonass. */ - public static final int CONSTELLATION_GLONASS = 3; + public static final byte CONSTELLATION_GLONASS = 3; /** Constellation type constant for QZSS. */ - public static final int CONSTELLATION_QZSS = 4; + public static final byte CONSTELLATION_QZSS = 4; /** Constellation type constant for Beidou. */ - public static final int CONSTELLATION_BEIDOU = 5; + public static final byte CONSTELLATION_BEIDOU = 5; /** Constellation type constant for Galileo. */ - public static final int CONSTELLATION_GALILEO = 6; + public static final byte CONSTELLATION_GALILEO = 6; + + /** Constellation type. */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({CONSTELLATION_UNKNOWN, CONSTELLATION_GPS, CONSTELLATION_SBAS, CONSTELLATION_GLONASS, + CONSTELLATION_QZSS, CONSTELLATION_BEIDOU, CONSTELLATION_GALILEO}) + public @interface ConstellationType {} // these must match the definitions in gps.h /** @hide */ @@ -80,9 +91,10 @@ public final class GnssStatus { * Retrieves the constellation type of the satellite at the specified position. * @param satIndex the index of the satellite in the list. */ - public int getConstellationType(int satIndex) { - return (mSvidWithFlags[satIndex] >> CONSTELLATION_TYPE_SHIFT_WIDTH) - & CONSTELLATION_TYPE_MASK; + @ConstellationType + public byte getConstellationType(int satIndex) { + return (byte) ((mSvidWithFlags[satIndex] >> CONSTELLATION_TYPE_SHIFT_WIDTH) + & CONSTELLATION_TYPE_MASK); } /** diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java index e41e20c172f7..7b3dd7de081f 100644 --- a/location/java/android/location/GpsStatus.java +++ b/location/java/android/location/GpsStatus.java @@ -147,7 +147,6 @@ public final class GpsStatus { & GnssStatus.CONSTELLATION_TYPE_MASK; // Skip all non-GPS satellites. if (constellationType != GnssStatus.CONSTELLATION_GPS) { - // TODO: translate the defacto pre-N use of prn's >32 to new struct continue; } int prn = svidWithFlags[i] >> GnssStatus.SVID_SHIFT_WIDTH; diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index 4f1e0397abd0..bc8b026222ed 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -69,7 +69,7 @@ interface ILocationManager in String packageName); void removeGnssNavigationMessageListener(in IGnssNavigationMessageListener listener); - int getGpsYearOfHardware(); + int getGnssYearOfHardware(); // --- deprecated --- List<String> getAllProviders(); diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 23f0710a0a9d..e14e36d8c270 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -1959,11 +1959,11 @@ public class LocationManager { * @hide */ @TestApi - public int getGpsYearOfHardware() { + public int getGnssYearOfHardware() { try { - return mService.getGpsYearOfHardware(); + return mService.getGnssYearOfHardware(); } catch (RemoteException e) { - Log.e(TAG, "RemoteException in getGpsSystemInfo: ", e); + Log.e(TAG, "RemoteException in getGnssSystemInfo: ", e); return 0; } } diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java index d06da975d0f7..646ab4ef1804 100644 --- a/media/java/android/media/MediaFormat.java +++ b/media/java/android/media/MediaFormat.java @@ -65,6 +65,7 @@ import java.util.Map; * <tr><th>Name</th><th>Value Type</th><th>Description</th></tr> * <tr><td>{@link #KEY_CHANNEL_COUNT}</td><td>Integer</td><td></td></tr> * <tr><td>{@link #KEY_SAMPLE_RATE}</td><td>Integer</td><td></td></tr> + * <tr><td>{@link #KEY_PCM_ENCODING}</td><td>Integer</td><td>optional</td></tr> * <tr><td>{@link #KEY_IS_ADTS}</td><td>Integer</td><td>optional, if <em>decoding</em> AAC audio content, setting this key to 1 indicates that each audio frame is prefixed by the ADTS header.</td></tr> * <tr><td>{@link #KEY_AAC_PROFILE}</td><td>Integer</td><td><b>encoder-only</b>, optional, if content is AAC audio, specifies the desired profile.</td></tr> * <tr><td>{@link #KEY_AAC_SBR_MODE}</td><td>Integer</td><td><b>encoder-only</b>, optional, if content is AAC audio, specifies the desired SBR mode.</td></tr> @@ -197,6 +198,26 @@ public final class MediaFormat { public static final String KEY_FRAME_RATE = "frame-rate"; /** + * A key describing the raw audio sample encoding/format. + * + * <p>The associated value is an integer, using one of the + * {@link AudioFormat}.ENCODING_PCM_ values.</p> + * + * <p>This is an optional key for audio decoders and encoders specifying the + * desired raw audio sample format during {@link MediaCodec#configure + * MediaCodec.configure(…)} call. Use {@link MediaCodec#getInputFormat + * MediaCodec.getInput}/{@link MediaCodec#getOutputFormat OutputFormat(…)} + * to confirm the actual format. For the PCM decoder this key specifies both + * input and output sample encodings.</p> + * + * <p>This key is also used by {@link MediaExtractor} to specify the sample + * format of audio data, if it is specified.</p> + * + * <p>If this key is missing, the raw audio sample format is signed 16-bit short.</p> + */ + public static final String KEY_PCM_ENCODING = "pcm-encoding"; + + /** * A key describing the capture rate of a video format in frames/sec. * <p> * When capture rate is different than the frame rate, it means that the @@ -564,7 +585,7 @@ public final class MediaFormat { public static final String KEY_IS_TIMED_TEXT = "is-timed-text"; // The following color aspect values must be in sync with the ones in HardwareAPI.h. - /* + /** * An optional key describing the color primaries, white point and * luminance factors for video content. * diff --git a/media/java/android/media/session/ISessionCallback.aidl b/media/java/android/media/session/ISessionCallback.aidl index adb6b0600f97..893bd3c8cbb1 100644 --- a/media/java/android/media/session/ISessionCallback.aidl +++ b/media/java/android/media/session/ISessionCallback.aidl @@ -29,6 +29,10 @@ oneway interface ISessionCallback { void onMediaButton(in Intent mediaButtonIntent, int sequenceNumber, in ResultReceiver cb); // These callbacks are for the TransportPerformer + void onPrepare(); + void onPrepareFromMediaId(String mediaId, in Bundle extras); + void onPrepareFromSearch(String query, in Bundle extras); + void onPrepareFromUri(in Uri uri, in Bundle extras); void onPlay(); void onPlayFromMediaId(String mediaId, in Bundle extras); void onPlayFromSearch(String query, in Bundle extras); diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl index 285e5f7a0880..249bcdc802ce 100644 --- a/media/java/android/media/session/ISessionController.aidl +++ b/media/java/android/media/session/ISessionController.aidl @@ -50,6 +50,10 @@ interface ISessionController { void setVolumeTo(int value, int flags, String packageName); // These commands are for the TransportControls + void prepare(); + void prepareFromMediaId(String mediaId, in Bundle extras); + void prepareFromSearch(String string, in Bundle extras); + void prepareFromUri(in Uri uri, in Bundle extras); void play(); void playFromMediaId(String mediaId, in Bundle extras); void playFromSearch(String string, in Bundle extras); diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java index 3d9b60deed2f..13db00ef3cd1 100644 --- a/media/java/android/media/session/MediaController.java +++ b/media/java/android/media/session/MediaController.java @@ -592,6 +592,90 @@ public final class MediaController { } /** + * Request that the player prepare its playback. Once the preparation is done, the session + * will change its playback state to {@link PlaybackState#STATE_PAUSED}. Afterwards, + * {@link #play} can be called to start playback. If the preparation is not needed, + * {@link #play} can be directly called without this method. + */ + public void prepare() { + try { + mSessionBinder.prepare(); + } catch (RemoteException e) { + Log.wtf(TAG, "Error calling prepare.", e); + } + } + + /** + * Request that the player prepare playback for a specific media id. Once the preparation is + * done, the session will change its playback state to {@link PlaybackState#STATE_PAUSED}. + * Afterwards, {@link #play} can be called to start playback. If the preparation is not + * needed, {@link #playFromMediaId} can be directly called without this method. + * + * @param mediaId The id of the requested media. + * @param extras Optional extras that can include extra information about the media item + * to be prepared. + */ + public void prepareFromMediaId(String mediaId, Bundle extras) { + if (TextUtils.isEmpty(mediaId)) { + throw new IllegalArgumentException( + "You must specify a non-empty String for prepareFromMediaId."); + } + try { + mSessionBinder.prepareFromMediaId(mediaId, extras); + } catch (RemoteException e) { + Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e); + } + } + + /** + * Request that the player prepare playback for a specific search query. + * An empty or null query should be treated as a request to prepare any + * music. Once the preparation is done, the session will change its playback state to + * {@link PlaybackState#STATE_PAUSED}. Afterwards, {@link #play} can be called to start + * playback. If the preparation is not needed, {@link #playFromSearch} can be directly + * called without this method. + * + * @param query The search query. + * @param extras Optional extras that can include extra information + * about the query. + */ + public void prepareFromSearch(String query, Bundle extras) { + if (query == null) { + // This is to remain compatible with + // INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH + query = ""; + } + try { + mSessionBinder.prepareFromSearch(query, extras); + } catch (RemoteException e) { + Log.wtf(TAG, "Error calling prepare(" + query + ").", e); + } + } + + /** + * Request that the player prepare playback for a specific {@link Uri}. + * Once the preparation is done, the session will change its playback state to + * {@link PlaybackState#STATE_PAUSED}. Afterwards, {@link #play} can be called to start + * playback. If the preparation is not needed, {@link #playFromUri} can be directly + * called without this method. + * + * @param uri The URI of the requested media. + * @param extras Optional extras that can include extra information about the media item + * to be prepared. + */ + public void prepareFromUri(Uri uri, Bundle extras) { + if (uri == null || Uri.EMPTY.equals(uri)) { + throw new IllegalArgumentException( + "You must specify a non-empty Uri for prepareFromUri."); + } + try { + mSessionBinder.prepareFromUri(uri, extras); + } catch (RemoteException e) { + Log.wtf(TAG, "Error calling prepare(" + uri + ").", e); + } + } + + /** * Request that the player start its playback at its current position. */ public void play() { @@ -605,7 +689,6 @@ public final class MediaController { /** * Request that the player start playback for a specific media id. * - * @see PlaybackState#EXTRA_PREPARE_ONLY * @param mediaId The id of the requested media. * @param extras Optional extras that can include extra information about the media item * to be played. @@ -627,10 +710,9 @@ public final class MediaController { * An empty or null query should be treated as a request to play any * music. * - * @see PlaybackState#EXTRA_PREPARE_ONLY * @param query The search query. * @param extras Optional extras that can include extra information - * about the query. + * about the query. */ public void playFromSearch(String query, Bundle extras) { if (query == null) { @@ -648,8 +730,7 @@ public final class MediaController { /** * Request that the player start playback for a specific {@link Uri}. * - * @see PlaybackState#EXTRA_PREPARE_ONLY - * @param uri The URI of the requested media. + * @param uri The URI of the requested media. * @param extras Optional extras that can include extra information about the media item * to be played. */ diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java index 8c5b19c36f11..3b1b6c86ffcb 100644 --- a/media/java/android/media/session/MediaSession.java +++ b/media/java/android/media/session/MediaSession.java @@ -87,12 +87,6 @@ public final class MediaSession { public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 1 << 1; /** - * Set this flag on the session to indicate that it can handle - * the {@link PlaybackState#EXTRA_PREPARE_ONLY} field. - */ - public static final int FLAG_HANDLES_PREPARE_ONLY = 1 << 2; - - /** * System only flag for a session that needs to have priority over all other * sessions. This flag ensures this session will receive media button events * regardless of the current ordering in the system. @@ -106,7 +100,6 @@ public final class MediaSession { @IntDef(flag = true, value = { FLAG_HANDLES_MEDIA_BUTTONS, FLAG_HANDLES_TRANSPORT_CONTROLS, - FLAG_HANDLES_PREPARE_ONLY, FLAG_EXCLUSIVE_GLOBAL_PRIORITY }) public @interface SessionFlags { } @@ -519,6 +512,22 @@ public final class MediaSession { } } + private void dispatchPrepare() { + postToCallback(CallbackMessageHandler.MSG_PREPARE); + } + + private void dispatchPrepareFromMediaId(String mediaId, Bundle extras) { + postToCallback(CallbackMessageHandler.MSG_PREPARE_MEDIA_ID, mediaId, extras); + } + + private void dispatchPrepareFromSearch(String query, Bundle extras) { + postToCallback(CallbackMessageHandler.MSG_PREPARE_SEARCH, query, extras); + } + + private void dispatchPrepareFromUri(Uri uri, Bundle extras) { + postToCallback(CallbackMessageHandler.MSG_PREPARE_URI, uri, extras); + } + private void dispatchPlay() { postToCallback(CallbackMessageHandler.MSG_PLAY); } @@ -805,16 +814,49 @@ public final class MediaSession { } /** - * Override to handle requests to begin playback. + * Override to handle requests to prepare playback. The state of playback should be updated + * to {@link PlaybackState#STATE_PAUSED} after the preparation is done. Override + * {@link #onPlay} to handle requests for starting playback of prepared content. */ - public void onPlay() { + public void onPrepare() { } /** - * Override to handle requests to play a specific mediaId that was - * provided by your app's {@link MediaBrowserService}. + * Override to handle requests to prepare for playing a specific mediaId that was provided + * by your app's {@link MediaBrowserService}. The state of playback should be updated + * to {@link PlaybackState#STATE_PAUSED} after the preparation is done. The playback of + * the prepared content should start in the implementation of {@link #onPlay}. Override + * {@link #onPlayFromMediaId} to handle requests for starting playback without preparation. */ - public void onPlayFromMediaId(String mediaId, Bundle extras) { + public void onPrepareFromMediaId(String mediaId, Bundle extras) { + } + + /** + * Override to handle requests to prepare playback from a search query. An + * empty query indicates that the app may prepare any music. The + * implementation should attempt to make a smart choice about what to + * play. The state of playback should be updated to {@link PlaybackState#STATE_PAUSED} + * after the preparation is done. The playback of the prepared content should start + * in the implementation of {@link #onPlay}. Override {@link #onPlayFromSearch} + * to handle requests for starting playback without preparation. + */ + public void onPrepareFromSearch(String query, Bundle extras) { + } + + /** + * Override to handle requests to prepare a specific media item represented by a URI. + * The state of playback should be updated to {@link PlaybackState#STATE_PAUSED} + * after the preparation is done. The playback of the prepared content should start in + * the implementation of {@link #onPlay}. Override {@link #onPlayFromUri} to handle requests + * for starting playback without preparation. + */ + public void onPrepareFromUri(Uri uri, Bundle extras) { + } + + /** + * Override to handle requests to begin playback. + */ + public void onPlay() { } /** @@ -827,6 +869,13 @@ public final class MediaSession { } /** + * Override to handle requests to play a specific mediaId that was + * provided by your app's {@link MediaBrowserService}. + */ + public void onPlayFromMediaId(String mediaId, Bundle extras) { + } + + /** * Override to handle requests to play a specific media item represented by a URI. */ public void onPlayFromUri(Uri uri, Bundle extras) { @@ -937,6 +986,38 @@ public final class MediaSession { } @Override + public void onPrepare() { + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchPrepare(); + } + } + + @Override + public void onPrepareFromMediaId(String mediaId, Bundle extras) { + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchPrepareFromMediaId(mediaId, extras); + } + } + + @Override + public void onPrepareFromSearch(String query, Bundle extras) { + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchPrepareFromSearch(query, extras); + } + } + + @Override + public void onPrepareFromUri(Uri uri, Bundle extras) { + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchPrepareFromUri(uri, extras); + } + } + + @Override public void onPlay() { MediaSession session = mMediaSession.get(); if (session != null) { @@ -1162,24 +1243,28 @@ public final class MediaSession { private class CallbackMessageHandler extends Handler { - private static final int MSG_PLAY = 1; - private static final int MSG_PLAY_MEDIA_ID = 2; - private static final int MSG_PLAY_SEARCH = 3; - private static final int MSG_SKIP_TO_ITEM = 4; - private static final int MSG_PAUSE = 5; - private static final int MSG_STOP = 6; - private static final int MSG_NEXT = 7; - private static final int MSG_PREVIOUS = 8; - private static final int MSG_FAST_FORWARD = 9; - private static final int MSG_REWIND = 10; - private static final int MSG_SEEK_TO = 11; - private static final int MSG_RATE = 12; - private static final int MSG_CUSTOM_ACTION = 13; - private static final int MSG_MEDIA_BUTTON = 14; - private static final int MSG_COMMAND = 15; - private static final int MSG_ADJUST_VOLUME = 16; - private static final int MSG_SET_VOLUME = 17; - private static final int MSG_PLAY_URI = 18; + private static final int MSG_COMMAND = 1; + private static final int MSG_MEDIA_BUTTON = 2; + private static final int MSG_PREPARE = 3; + private static final int MSG_PREPARE_MEDIA_ID = 4; + private static final int MSG_PREPARE_SEARCH = 5; + private static final int MSG_PREPARE_URI = 6; + private static final int MSG_PLAY = 7; + private static final int MSG_PLAY_MEDIA_ID = 8; + private static final int MSG_PLAY_SEARCH = 9; + private static final int MSG_PLAY_URI = 10; + private static final int MSG_SKIP_TO_ITEM = 11; + private static final int MSG_PAUSE = 12; + private static final int MSG_STOP = 13; + private static final int MSG_NEXT = 14; + private static final int MSG_PREVIOUS = 15; + private static final int MSG_FAST_FORWARD = 16; + private static final int MSG_REWIND = 17; + private static final int MSG_SEEK_TO = 18; + private static final int MSG_RATE = 19; + private static final int MSG_CUSTOM_ACTION = 20; + private static final int MSG_ADJUST_VOLUME = 21; + private static final int MSG_SET_VOLUME = 22; private MediaSession.Callback mCallback; @@ -1210,6 +1295,25 @@ public final class MediaSession { public void handleMessage(Message msg) { VolumeProvider vp; switch (msg.what) { + case MSG_COMMAND: + Command cmd = (Command) msg.obj; + mCallback.onCommand(cmd.command, cmd.extras, cmd.stub); + break; + case MSG_MEDIA_BUTTON: + mCallback.onMediaButtonEvent((Intent) msg.obj); + break; + case MSG_PREPARE: + mCallback.onPrepare(); + break; + case MSG_PREPARE_MEDIA_ID: + mCallback.onPrepareFromMediaId((String) msg.obj, msg.getData()); + break; + case MSG_PREPARE_SEARCH: + mCallback.onPrepareFromSearch((String) msg.obj, msg.getData()); + break; + case MSG_PREPARE_URI: + mCallback.onPrepareFromUri((Uri) msg.obj, msg.getData()); + break; case MSG_PLAY: mCallback.onPlay(); break; @@ -1252,13 +1356,6 @@ public final class MediaSession { case MSG_CUSTOM_ACTION: mCallback.onCustomAction((String) msg.obj, msg.getData()); break; - case MSG_MEDIA_BUTTON: - mCallback.onMediaButtonEvent((Intent) msg.obj); - break; - case MSG_COMMAND: - Command cmd = (Command) msg.obj; - mCallback.onCommand(cmd.command, cmd.extras, cmd.stub); - break; case MSG_ADJUST_VOLUME: synchronized (mLock) { vp = mVolumeProvider; diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java index 1079a1f9a107..1485cd782605 100644 --- a/media/java/android/media/session/PlaybackState.java +++ b/media/java/android/media/session/PlaybackState.java @@ -133,19 +133,32 @@ public final class PlaybackState implements Parcelable { public static final long ACTION_PLAY_FROM_URI = 1 << 13; /** - * Used as an optional boolean extra field in - * {@link MediaController.TransportControls#playFromMediaId}, - * {@link MediaController.TransportControls#playFromSearch}, and - * {@link MediaController.TransportControls#playFromUri}. Value of {@code true} overrides - * the default behavior of starting the playback after preparing. Check - * {@link MediaSession#FLAG_HANDLES_PREPARE_ONLY} to see if the media session supports this. + * Indicates this session supports the prepare command. * - * @see MediaSession#FLAG_HANDLES_PREPARE_ONLY - * @see MediaController.TransportControls#playFromMediaId - * @see MediaController.TransportControls#playFromSearch - * @see MediaController.TransportControls#playFromUri + * @see Builder#setActions(long) + */ + public static final long ACTION_PREPARE = 1 << 14; + + /** + * Indicates this session supports the prepare from media id command. + * + * @see Builder#setActions(long) + */ + public static final long ACTION_PREPARE_FROM_MEDIA_ID = 1 << 15; + + /** + * Indicates this session supports the prepare from search command. + * + * @see Builder#setActions(long) + */ + public static final long ACTION_PREPARE_FROM_SEARCH = 1 << 16; + + /** + * Indicates this session supports the prepare from URI command. + * + * @see Builder#setActions(long) */ - public static final String EXTRA_PREPARE_ONLY = "android.media.session.extra.PREPARE_ONLY"; + public static final long ACTION_PREPARE_FROM_URI = 1 << 17; /** * This is the default playback state and indicates that no media has been @@ -330,6 +343,10 @@ public final class PlaybackState implements Parcelable { * <li> {@link PlaybackState#STATE_REWINDING}</li> * <li> {@link PlaybackState#STATE_BUFFERING}</li> * <li> {@link PlaybackState#STATE_ERROR}</li> + * <li> {@link PlaybackState#STATE_CONNECTING}</li> + * <li> {@link PlaybackState#STATE_SKIPPING_TO_PREVIOUS}</li> + * <li> {@link PlaybackState#STATE_SKIPPING_TO_NEXT}</li> + * <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li> * </ul> */ public int getState() { @@ -380,6 +397,10 @@ public final class PlaybackState implements Parcelable { * <li> {@link PlaybackState#ACTION_PLAY_FROM_SEARCH}</li> * <li> {@link PlaybackState#ACTION_SKIP_TO_QUEUE_ITEM}</li> * <li> {@link PlaybackState#ACTION_PLAY_FROM_URI}</li> + * <li> {@link PlaybackState#ACTION_PREPARE}</li> + * <li> {@link PlaybackState#ACTION_PREPARE_FROM_MEDIA_ID}</li> + * <li> {@link PlaybackState#ACTION_PREPARE_FROM_SEARCH}</li> + * <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li> * </ul> */ public long getActions() { @@ -831,6 +852,10 @@ public final class PlaybackState implements Parcelable { * <li> {@link PlaybackState#STATE_REWINDING}</li> * <li> {@link PlaybackState#STATE_BUFFERING}</li> * <li> {@link PlaybackState#STATE_ERROR}</li> + * <li> {@link PlaybackState#STATE_CONNECTING}</li> + * <li> {@link PlaybackState#STATE_SKIPPING_TO_PREVIOUS}</li> + * <li> {@link PlaybackState#STATE_SKIPPING_TO_NEXT}</li> + * <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li> * </ul> * * @param state The current state of playback. @@ -870,6 +895,10 @@ public final class PlaybackState implements Parcelable { * <li> {@link PlaybackState#STATE_REWINDING}</li> * <li> {@link PlaybackState#STATE_BUFFERING}</li> * <li> {@link PlaybackState#STATE_ERROR}</li> + * <li> {@link PlaybackState#STATE_CONNECTING}</li> + * <li> {@link PlaybackState#STATE_SKIPPING_TO_PREVIOUS}</li> + * <li> {@link PlaybackState#STATE_SKIPPING_TO_NEXT}</li> + * <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li> * </ul> * * @param state The current state of playback. @@ -900,6 +929,10 @@ public final class PlaybackState implements Parcelable { * <li> {@link PlaybackState#ACTION_PLAY_FROM_SEARCH}</li> * <li> {@link PlaybackState#ACTION_SKIP_TO_QUEUE_ITEM}</li> * <li> {@link PlaybackState#ACTION_PLAY_FROM_URI}</li> + * <li> {@link PlaybackState#ACTION_PREPARE}</li> + * <li> {@link PlaybackState#ACTION_PREPARE_FROM_MEDIA_ID}</li> + * <li> {@link PlaybackState#ACTION_PREPARE_FROM_SEARCH}</li> + * <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li> * </ul> * * @param actions The set of actions allowed. diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java index 7b8e4b2e2ee6..1c11842cf01c 100644 --- a/media/java/android/media/tv/TvContract.java +++ b/media/java/android/media/tv/TvContract.java @@ -1314,6 +1314,8 @@ public final class TvContract { private static final char COMMA = ','; private static final String DELIMITER = ","; + private static final String[] EMPTY_STRING_ARRAY = new String[0]; + private Genres() {} /** @@ -1359,6 +1361,12 @@ public final class TvContract { * @return genre strings. */ public static String[] decode(String genres) { + if (genres.isEmpty()) { + return EMPTY_STRING_ARRAY; + } + if (genres.indexOf(COMMA) == -1 && genres.indexOf(DOUBLE_QUOTE) == -1) { + return new String[] {genres.trim()}; + } StringBuilder sb = new StringBuilder(); List<String> results = new ArrayList<>(); int length = genres.length(); diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java index fd96391b0c5f..216509d47c20 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java @@ -18,6 +18,7 @@ package com.android.documentsui; import static com.android.documentsui.Shared.DEBUG; import static com.android.documentsui.Shared.TAG; +import static com.android.internal.util.Preconditions.checkState; import android.content.ContentProviderClient; import android.content.ContentResolver; @@ -40,6 +41,7 @@ import android.util.Log; import com.android.documentsui.model.RootInfo; import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.Preconditions; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; @@ -85,15 +87,13 @@ public class RootsCache { // Create a new anonymous "Recents" RootInfo. It's a faker. mRecentsRoot = new RootInfo() {{ - // Special root for recents - authority = null; - rootId = null; - derivedIcon = R.drawable.ic_root_recent; - derivedType = RootInfo.TYPE_RECENTS; - flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_IS_CHILD; - title = mContext.getString(R.string.root_recent); - availableBytes = -1; - }}; + // Special root for recents + derivedIcon = R.drawable.ic_root_recent; + derivedType = RootInfo.TYPE_RECENTS; + flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_IS_CHILD; + title = mContext.getString(R.string.root_recent); + availableBytes = -1; + }}; } private class RootsChangedObserver extends ContentObserver { @@ -116,6 +116,16 @@ public class RootsCache { * Gather roots from all known storage providers. */ public void updateAsync() { + // Verifying an assumption about the recents root being immutable. + if (DEBUG) { + checkState(mRecentsRoot.authority == null); + checkState(mRecentsRoot.rootId == null); + checkState(mRecentsRoot.derivedIcon == R.drawable.ic_root_recent); + checkState(mRecentsRoot.derivedType == RootInfo.TYPE_RECENTS); + checkState(mRecentsRoot.flags == (Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_IS_CHILD)); + checkState(mRecentsRoot.title == mContext.getString(R.string.root_recent)); + checkState(mRecentsRoot.availableBytes == -1); + } new UpdateTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @@ -412,9 +422,10 @@ public class RootsCache { if (!state.showAdvanced && root.isAdvanced()) continue; // Exclude non-local devices when local only if (state.localOnly && !root.isLocalOnly()) continue; - // Exclude downloads roots that don't support directory creation - // TODO: Add flag to check the root supports directory creation or not. - if (state.directoryCopy && !root.supportsChildren()) continue; + // Exclude downloads roots as it doesn't support directory creation (actually + // we just don't show them). + // TODO: Add flag to check the root supports directory creation. + if (state.directoryCopy && !root.isDownloads()) continue; // Only show empty roots when creating, or in browse mode. if (root.isEmpty() && (state.action == State.ACTION_OPEN diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java index f908eebb32a3..9f83c042b111 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java @@ -45,7 +45,6 @@ import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; -import com.android.documentsui.model.DocumentInfo; import com.android.documentsui.model.RootInfo; import java.util.ArrayList; @@ -403,17 +402,7 @@ public class RootsFragment extends Fragment { public static class RootComparator implements Comparator<RootItem> { @Override public int compare(RootItem lhs, RootItem rhs) { - // Sort by root type, then title, then summary. - int score = lhs.root.derivedType - rhs.root.derivedType; - if (score != 0) { - return score; - } - score = DocumentInfo.compareToIgnoreCaseNullable(lhs.root.title, rhs.root.title); - if (score != 0) { - return score; - } - - return DocumentInfo.compareToIgnoreCaseNullable(lhs.root.summary, rhs.root.summary); + return lhs.root.compareTo(rhs.root); } } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java index 22cb25a26a5c..b90a1194596a 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java +++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java @@ -17,14 +17,17 @@ package com.android.documentsui; import android.content.Context; +import android.text.TextUtils; import android.text.format.DateUtils; import android.text.format.Time; +import java.text.Collator; import java.util.ArrayList; import java.util.List; /** @hide */ public final class Shared { + /** Intent action name to pick a copy destination. */ public static final String ACTION_PICK_COPY_DESTINATION = "com.android.documentsui.PICK_COPY_DESTINATION"; @@ -39,6 +42,19 @@ public final class Shared { public static final String TAG = "Documents"; public static final String EXTRA_STACK = "com.android.documentsui.STACK"; + + /** + * String prefix used to indicate the document is a directory. + */ + public static final char DIR_PREFIX = '\001'; + + private static final Collator sCollator; + + static { + sCollator = Collator.getInstance(); + sCollator.setStrength(Collator.SECONDARY); + } + /** * Generates a formatted quantity string. */ @@ -76,4 +92,26 @@ public final class Shared { ? (ArrayList<T>) list : new ArrayList<T>(list); } + + /** + * Compare two strings against each other using system default collator in a + * case-insensitive mode. Clusters strings prefixed with {@link DIR_PREFIX} + * before other items. + */ + public static int compareToIgnoreCaseNullable(String lhs, String rhs) { + final boolean leftEmpty = TextUtils.isEmpty(lhs); + final boolean rightEmpty = TextUtils.isEmpty(rhs); + + if (leftEmpty && rightEmpty) return 0; + if (leftEmpty) return -1; + if (rightEmpty) return 1; + + final boolean leftDir = (lhs.charAt(0) == DIR_PREFIX); + final boolean rightDir = (rhs.charAt(0) == DIR_PREFIX); + + if (leftDir && !rightDir) return -1; + if (rightDir && !leftDir) return 1; + + return sCollator.compare(lhs, rhs); + } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java index 0a9789f54e31..4583decc14a8 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java @@ -1071,8 +1071,8 @@ public class DirectoryFragment extends Fragment implements DocumentsAdapter.Envi return false; } - // Can't copy folders to roots that don't support children. - if (!root.supportsChildren()) { + // Can't copy folders to downloads, because we don't show folders there. + if (!root.isDownloads()) { for (DocumentInfo docs : files) { if (docs.isDirectory()) { return false; diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java index b3694489aca2..9684a5a0a2c2 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java @@ -35,6 +35,7 @@ import android.util.Log; import com.android.documentsui.DirectoryResult; import com.android.documentsui.RootCursorWrapper; +import com.android.documentsui.Shared; import com.android.documentsui.dirlist.MultiSelectManager.Selection; import com.android.documentsui.model.DocumentInfo; @@ -170,7 +171,7 @@ public class Model { final String displayName = getCursorString( mCursor, Document.COLUMN_DISPLAY_NAME); if (Document.MIME_TYPE_DIR.equals(mimeType)) { - stringValues[pos] = DocumentInfo.DIR_PREFIX + displayName; + stringValues[pos] = Shared.DIR_PREFIX + displayName; } else { stringValues[pos] = displayName; } @@ -227,7 +228,7 @@ public class Model { final String lhs = pivotValue; final String rhs = sortKey[mid]; - final int compare = DocumentInfo.compareToIgnoreCaseNullable(lhs, rhs); + final int compare = Shared.compareToIgnoreCaseNullable(lhs, rhs); if (compare < 0) { right = mid; diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java index 1c696ad88ef5..e9fdab090c18 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java +++ b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java @@ -26,7 +26,6 @@ import android.provider.DocumentsContract; import android.provider.DocumentsContract.Document; import android.provider.DocumentsProvider; import android.support.annotation.VisibleForTesting; -import android.text.TextUtils; import com.android.documentsui.DocumentsApplication; import com.android.documentsui.RootCursorWrapper; @@ -38,7 +37,6 @@ import java.io.DataOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.net.ProtocolException; -import java.text.Collator; import java.util.Objects; /** @@ -48,13 +46,6 @@ public class DocumentInfo implements Durable, Parcelable { private static final int VERSION_INIT = 1; private static final int VERSION_SPLIT_URI = 2; - private static final Collator sCollator; - - static { - sCollator = Collator.getInstance(); - sCollator.setStrength(Collator.SECONDARY); - } - public String authority; public String documentId; public String mimeType; @@ -320,31 +311,4 @@ public class DocumentInfo implements Durable, Parcelable { fnfe.initCause(t); throw fnfe; } - - /** - * String prefix used to indicate the document is a directory. - */ - public static final char DIR_PREFIX = '\001'; - - /** - * Compare two strings against each other using system default collator in a - * case-insensitive mode. Clusters strings prefixed with {@link #DIR_PREFIX} - * before other items. - */ - public static int compareToIgnoreCaseNullable(String lhs, String rhs) { - final boolean leftEmpty = TextUtils.isEmpty(lhs); - final boolean rightEmpty = TextUtils.isEmpty(rhs); - - if (leftEmpty && rightEmpty) return 0; - if (leftEmpty) return -1; - if (rightEmpty) return 1; - - final boolean leftDir = (lhs.charAt(0) == DIR_PREFIX); - final boolean rightDir = (rhs.charAt(0) == DIR_PREFIX); - - if (leftDir && !rightDir) return -1; - if (rightDir && !leftDir) return 1; - - return sCollator.compare(lhs, rhs); - } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java index 3f4a1df2c5b6..38970585afc3 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java +++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java @@ -16,10 +16,12 @@ package com.android.documentsui.model; +import static com.android.documentsui.Shared.compareToIgnoreCaseNullable; import static com.android.documentsui.model.DocumentInfo.getCursorInt; import static com.android.documentsui.model.DocumentInfo.getCursorLong; import static com.android.documentsui.model.DocumentInfo.getCursorString; +import android.annotation.IntDef; import android.content.Context; import android.database.Cursor; import android.graphics.drawable.Drawable; @@ -36,17 +38,31 @@ import com.android.documentsui.R; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.net.ProtocolException; import java.util.Objects; /** * Representation of a {@link Root}. */ -public class RootInfo implements Durable, Parcelable { +public class RootInfo implements Durable, Parcelable, Comparable<RootInfo> { private static final int VERSION_INIT = 1; private static final int VERSION_DROP_TYPE = 2; // The values of these constants determine the sort order of various roots in the RootsFragment. + @IntDef(flag = true, value = { + TYPE_IMAGES, + TYPE_VIDEO, + TYPE_AUDIO, + TYPE_RECENTS, + TYPE_DOWNLOADS, + TYPE_LOCAL, + TYPE_MTP, + TYPE_OTHER + }) + @Retention(RetentionPolicy.SOURCE) + public @interface RootType {} public static final int TYPE_IMAGES = 1; public static final int TYPE_VIDEO = 2; public static final int TYPE_AUDIO = 3; @@ -69,7 +85,7 @@ public class RootInfo implements Durable, Parcelable { /** Derived fields that aren't persisted */ public String[] derivedMimeTypes; public int derivedIcon; - public int derivedType; + public @RootType int derivedType; public RootInfo() { reset(); @@ -329,6 +345,22 @@ public class RootInfo implements Durable, Parcelable { } @Override + public int compareTo(RootInfo other) { + // Sort by root type, then title, then summary. + int score = derivedType - other.derivedType; + if (score != 0) { + return score; + } + + score = compareToIgnoreCaseNullable(title, other.title); + if (score != 0) { + return score; + } + + return compareToIgnoreCaseNullable(summary, other.summary); + } + + @Override public String toString() { return "Root{authority=" + authority + ", rootId=" + rootId + ", title=" + title + "}"; } diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java index 83299f0677cf..4b0bc41f19fe 100644 --- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java @@ -28,6 +28,7 @@ import android.test.suitebuilder.annotation.SmallTest; import com.android.documentsui.DirectoryResult; import com.android.documentsui.RootCursorWrapper; +import com.android.documentsui.Shared; import com.android.documentsui.State; import com.android.documentsui.dirlist.MultiSelectManager.Selection; import com.android.documentsui.model.DocumentInfo; @@ -190,7 +191,7 @@ public class ModelTest extends AndroidTestCase { assertEquals(ITEM_COUNT, seen.cardinality()); for (int i = 0; i < names.size()-1; ++i) { - assertTrue(DocumentInfo.compareToIgnoreCaseNullable(names.get(i), names.get(i+1)) <= 0); + assertTrue(Shared.compareToIgnoreCaseNullable(names.get(i), names.get(i+1)) <= 0); } } diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java index 441b9a774ac3..ca5c79974d4d 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java @@ -581,6 +581,23 @@ class MtpDatabase { } } + void updateObject(String documentId, int deviceId, String parentId, MtpObjectInfo info) { + final ContentValues values = new ContentValues(); + getObjectDocumentValues(values, deviceId, parentId, info); + + mDatabase.beginTransaction(); + try { + mDatabase.update( + TABLE_DOCUMENTS, + values, + Document.COLUMN_DOCUMENT_ID + " = ?", + strings(documentId)); + mDatabase.setTransactionSuccessful(); + } finally { + mDatabase.endTransaction(); + } + } + private static class OpenHelper extends SQLiteOpenHelper { public OpenHelper(Context context, int flags) { super(context, diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java index db1671d6296a..d329e3cdd375 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java @@ -486,7 +486,7 @@ public class MtpDocumentsProvider extends DocumentsProvider { public final DocumentLoader mDocumentLoader; public DeviceToolkit(MtpManager manager, ContentResolver resolver, MtpDatabase database) { - mPipeManager = new PipeManager(); + mPipeManager = new PipeManager(database); mDocumentLoader = new DocumentLoader(manager, resolver, database); } } diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java index 16523bca454c..645bfcd3eeb4 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java @@ -29,12 +29,14 @@ import java.util.concurrent.Executors; class PipeManager { final ExecutorService mExecutor; + final MtpDatabase mDatabase; - PipeManager() { - this(Executors.newSingleThreadExecutor()); + PipeManager(MtpDatabase database) { + this(database, Executors.newSingleThreadExecutor()); } - PipeManager(ExecutorService executor) { + PipeManager(MtpDatabase database, ExecutorService executor) { + this.mDatabase = database; this.mExecutor = executor; } @@ -46,7 +48,7 @@ class PipeManager { ParcelFileDescriptor writeDocument(Context context, MtpManager model, Identifier identifier) throws IOException { - final Task task = new WriteDocumentTask(context, model, identifier); + final Task task = new WriteDocumentTask(context, model, identifier, mDatabase); mExecutor.execute(task); return task.getWritingFileDescriptor(); } @@ -100,11 +102,14 @@ class PipeManager { private static class WriteDocumentTask extends Task { private final Context mContext; + private final MtpDatabase mDatabase; - WriteDocumentTask(Context context, MtpManager model, Identifier identifier) + WriteDocumentTask( + Context context, MtpManager model, Identifier identifier, MtpDatabase database) throws IOException { super(model, identifier); mContext = context; + mDatabase = database; } @Override @@ -112,7 +117,7 @@ class PipeManager { File tempFile = null; try { // Obtain a temporary file and copy the data to it. - tempFile = mContext.getCacheDir().createTempFile("mtp", "tmp"); + tempFile = File.createTempFile("mtp", "tmp", mContext.getCacheDir()); try ( final FileOutputStream tempOutputStream = new ParcelFileDescriptor.AutoCloseOutputStream( @@ -140,12 +145,22 @@ class PipeManager { // Create the target object info with a correct file size and upload the file. final MtpObjectInfo targetObjectInfo = new MtpObjectInfo.Builder(placeholderObjectInfo) - .setCompressedSize((int) tempFile.length()) + .setCompressedSize(tempFile.length()) .build(); final ParcelFileDescriptor tempInputDescriptor = ParcelFileDescriptor.open( tempFile, ParcelFileDescriptor.MODE_READ_ONLY); - mManager.createDocument(mIdentifier.mDeviceId, - targetObjectInfo, tempInputDescriptor); + final int newObjectHandle = mManager.createDocument( + mIdentifier.mDeviceId, targetObjectInfo, tempInputDescriptor); + + final MtpObjectInfo newObjectInfo = mManager.getObjectInfo( + mIdentifier.mDeviceId, newObjectHandle); + final Identifier parentIdentifier = + mDatabase.getParentIdentifier(mIdentifier.mDocumentId); + mDatabase.updateObject( + mIdentifier.mDocumentId, + mIdentifier.mDeviceId, + parentIdentifier.mDocumentId, + newObjectInfo); } catch (IOException error) { Log.w(MtpDocumentsProvider.TAG, "Failed to send a file because of: " + error.getMessage()); diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java index 1df7351a8446..05c9c57e2409 100644 --- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java +++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java @@ -983,18 +983,10 @@ public class MtpDatabaseTest extends AndroidTestCase { } private void addTestDevice() throws FileNotFoundException { - mDatabase.getMapper().startAddingDocuments(null); - mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord( - 0, "Device", "device_key", /* opened is */ true, new MtpRoot[0], null, - null)); - mDatabase.getMapper().stopAddingDocuments(null); + TestUtil.addTestDevice(mDatabase); } private void addTestStorage(String parentId) throws FileNotFoundException { - mDatabase.getMapper().startAddingDocuments(parentId); - mDatabase.getMapper().putStorageDocuments(parentId, new MtpRoot[] { - new MtpRoot(0, 100, "Storage", 1024, 1024, ""), - }); - mDatabase.getMapper().stopAddingDocuments(parentId); + TestUtil.addTestStorage(mDatabase, parentId); } } diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java index 4dfc785a54ec..94f87ffe55ad 100644 --- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java +++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java @@ -16,8 +16,10 @@ package com.android.mtp; +import android.database.Cursor; import android.mtp.MtpObjectInfo; import android.os.ParcelFileDescriptor; +import android.provider.DocumentsContract.Document; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.MediumTest; @@ -33,12 +35,14 @@ public class PipeManagerTest extends AndroidTestCase { private TestMtpManager mtpManager; private ExecutorService mExecutor; private PipeManager mPipeManager; + private MtpDatabase mDatabase; @Override public void setUp() { mtpManager = new TestMtpManager(getContext()); mExecutor = Executors.newSingleThreadExecutor(); - mPipeManager = new PipeManager(mExecutor); + mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY); + mPipeManager = new PipeManager(mDatabase, mExecutor); } public void testReadDocument_basic() throws Exception { @@ -57,25 +61,32 @@ public class PipeManagerTest extends AndroidTestCase { } public void testWriteDocument_basic() throws Exception { + TestUtil.addTestDevice(mDatabase); + TestUtil.addTestStorage(mDatabase, "1"); + + final MtpObjectInfo info = + new MtpObjectInfo.Builder().setObjectHandle(1).setName("note.txt").build(); + mDatabase.getMapper().startAddingDocuments("2"); + mDatabase.getMapper().putChildDocuments(0, "2", new MtpObjectInfo[] { info }); + mDatabase.getMapper().stopAddingDocuments("2"); // Create a placeholder file which should be replaced by a real file later. - mtpManager.setObjectInfo(0, new MtpObjectInfo.Builder() - .setObjectHandle(1) - .build()); + mtpManager.setObjectInfo(0, info); // Upload testing bytes. final ParcelFileDescriptor descriptor = mPipeManager.writeDocument( getContext(), mtpManager, - new Identifier(0, 0, 1, null, MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT)); + new Identifier(0, 0, 1, "2", MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT)); final ParcelFileDescriptor.AutoCloseOutputStream outputStream = new ParcelFileDescriptor.AutoCloseOutputStream(descriptor); outputStream.write(HELLO_BYTES, 0, HELLO_BYTES.length); outputStream.close(); - mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS); + mExecutor.shutdown(); + assertTrue(mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS)); // Check if the placeholder file is removed. try { - final MtpObjectInfo placeholderDocument = mtpManager.getObjectInfo(0, 1); + mtpManager.getObjectInfo(0, 1); fail(); // The placeholder file has not been deleted. } catch (IOException e) { // Expected error, as the file is gone. @@ -86,6 +97,14 @@ public class PipeManagerTest extends AndroidTestCase { 0, TestMtpManager.CREATED_DOCUMENT_HANDLE); assertTrue(targetDocument != null); + // Confirm the object handle is updated. + try (final Cursor cursor = mDatabase.queryDocument( + "2", new String[] { MtpDatabaseConstants.COLUMN_OBJECT_HANDLE })) { + assertEquals(1, cursor.getCount()); + cursor.moveToNext(); + assertEquals(TestMtpManager.CREATED_DOCUMENT_HANDLE, cursor.getInt(0)); + } + // Verify uploaded bytes. final byte[] uploadedBytes = mtpManager.getImportFileBytes( 0, TestMtpManager.CREATED_DOCUMENT_HANDLE); @@ -112,7 +131,8 @@ public class PipeManagerTest extends AndroidTestCase { private void assertDescriptor(ParcelFileDescriptor descriptor, byte[] expectedBytes) throws IOException, InterruptedException { - mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS); + mExecutor.shutdown(); + assertTrue(mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS)); try (final ParcelFileDescriptor.AutoCloseInputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(descriptor)) { byte[] results = new byte[100]; @@ -125,7 +145,8 @@ public class PipeManagerTest extends AndroidTestCase { private void assertDescriptorError(ParcelFileDescriptor descriptor) throws InterruptedException { - mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS); + mExecutor.shutdown(); + assertTrue(mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS)); try { descriptor.checkError(); fail(); diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java index 43781520aec5..1b46f3c62aa1 100644 --- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java +++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java @@ -149,7 +149,9 @@ public class TestMtpManager extends MtpManager { if (mObjectInfos.containsKey(key)) { throw new IOException(); } - mObjectInfos.put(key, objectInfo); + final MtpObjectInfo newInfo = new MtpObjectInfo.Builder(objectInfo). + setObjectHandle(CREATED_DOCUMENT_HANDLE).build(); + mObjectInfos.put(key, newInfo); if (objectInfo.getFormat() != 0x3001) { try (final ParcelFileDescriptor.AutoCloseInputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(source)) { diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java index ffcc0882e019..34dd77bd3747 100644 --- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java +++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java @@ -21,12 +21,11 @@ import android.hardware.usb.UsbDeviceConnection; import android.hardware.usb.UsbManager; import android.os.SystemClock; +import java.io.FileNotFoundException; import java.io.IOException; import java.util.HashMap; import java.util.Objects; -import junit.framework.Assert; - /** * Static utility methods for testing. */ @@ -57,6 +56,22 @@ final class TestUtil { } } + static void addTestDevice(MtpDatabase database) throws FileNotFoundException { + database.getMapper().startAddingDocuments(null); + database.getMapper().putDeviceDocument(new MtpDeviceRecord( + 0, "Device", "device_key", /* opened is */ true, new MtpRoot[0], null, + null)); + database.getMapper().stopAddingDocuments(null); + } + + static void addTestStorage(MtpDatabase database, String parentId) throws FileNotFoundException { + database.getMapper().startAddingDocuments(parentId); + database.getMapper().putStorageDocuments(parentId, new MtpRoot[] { + new MtpRoot(0, 100, "Storage", 1024, 1024, ""), + }); + database.getMapper().stopAddingDocuments(parentId); + } + private static UsbDevice findMtpDevice( UsbManager usbManager, MtpManager manager) throws IOException { diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index 2ddb1e9703a3..99699b9f95ed 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Programme verplig ekstern toegelaat"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Laat enige program na ekstern geskryf word, ongeag manifeswaardes"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Verplig verstelbare groottes vir aktiwiteite"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Maak grootte van alle aktiwiteite verstelbaar vir veelvuldige vensters, ongeag manifeswaardes."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Maak die groottes van alle aktiwiteite verstelbaar vir veelvuldige vensters, ongeag manifeswaardes."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Aktiveer vormvrye-Windows"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Aktiveer steun vir eksperimentele vormvrye-Windows."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Aktiveer steun vir eksperimentele vormvrye-Windows."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Werkskerm-rugsteunwagwoord"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Volle rekenaarrugsteune word nie tans beskerm nie"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tik om die wagwoord vir volledige rekenaarrugsteune te verander of te verwyder"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Gedeaktiveer"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Altyd aan"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Outomaties"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Stel WebView-implementering"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Die gekose WebView-toepassing is gedeaktiveer, maar moet geaktiveer wees om gebruik te word. Wil jy dit aktiveer?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Kleurregstelling"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Hierdie kenmerk is eksperimenteel en kan werkverrigting beïnvloed."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Geneutraliseer deur <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ongeveer <xliff:g id="TIME">%1$s</xliff:g> oor"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – sowat <xliff:g id="TIME">%2$s</xliff:g> oor"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Vol"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Gedeaktiveer deur administrateur"</string> <string name="home" msgid="8263346537524314127">"Tuis"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> gelede"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> oor"</string> </resources> diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index 4276bea13a3c..0e363b51cb28 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"በውጫዊ ላይ ሃይል ይፈቀዳል"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"አንጸባራቂ እሴቶች ግምት ውስጥ ሳይገቡ ማንኛውም መተግበሪያ ወደ ውጫዊ ማከማቻ ለመጻፍ ብቁ ያደርጋል።"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"እንቅስቃሴዎች ዳግመኛ እንዲመጣጠኑ አስገድድ"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"የዝርዝር ሰነድ እሴቶች ምንም ይሁኑ ምን ለበርካታ መስኮቶች ሁሉንም እንቅስቃሴዎች ዳግም የሚመጣጠኑ እንዲሆኑ ያደርጋቸዋል።"</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"የዝርዝር ሰነድ እሴቶች ምንም ይሁኑ ምን ለበርካታ መስኮቶች ሁሉንም እንቅስቃሴዎች መጠናቸው የሚቀየሩ እንዲሆኑ ያደርጋቸዋል።"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"የነጻ ቅርጽ መስኮቶችን ያንቁ"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"የሙከራ ነጻ ቅርጽ መስኮቶች ድጋፍን ያነቃል።"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"የሙከራ ነጻ መልክ መስኮቶች ድጋፍን አንቃ"</string> <string name="local_backup_password_title" msgid="3860471654439418822">"የዴስክቶፕ መጠባበቂያ ይለፍ ቃል"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"ዴስክቶፕ ሙሉ ምትኬዎች በአሁኑ ሰዓት አልተጠበቁም"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"የዴስክቶፕ ሙሉ ምትኬዎች የይለፍ ቃሉን ለመለወጥ ወይም ለማስወገድ ነካ ያድርጉ"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"ተሰናክሏል"</string> <string name="night_mode_yes" msgid="2218157265997633432">"ሁልጊዜ ይበራል"</string> <string name="night_mode_auto" msgid="7508348175804304327">"ራስ-ሰር"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"የWebView ትግበራ"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"የWebView ትግበራን ያዘጋጁ"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"የተመረጠው WebView ትግበራ ተሰናክሏል፣ እና ጥቅም ላይ እንዲውል መንቃት አለበት፣ ሊያነቁት ይፈልጋሉ?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"የቀለም ማስተካከያ"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ይህ ባህሪ የሙከራ ነውና አፈጻጸም ላይ ተጽዕኖ ሊኖረው ይችላል።"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"በ<xliff:g id="TITLE">%1$s</xliff:g> ተሽሯል"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"<xliff:g id="TIME">%1$s</xliff:g> ገደማ ቀርቷል"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ገደማ <xliff:g id="TIME">%2$s</xliff:g> ይቀራል"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> እስከሚሞላ ድረስ"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"ሙሉነው"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"በአስተዳዳሪ የተሰናከለ"</string> <string name="home" msgid="8263346537524314127">"መነሻ"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"ከ<xliff:g id="ID_1">%1$s</xliff:g> በፊት"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> ቀርቷል"</string> </resources> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index 67fb59c84983..c757b711df9b 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"فرض السماح للتطبيقات على الخارجي"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"تأهيل أي تطبيق بحيث تتم كتابته على سعة تخزين خارجية، بغض النظر عن قيم البيان"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"فرض إمكانية تغيير على الأنشطة"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"لتمكين تغيير حجم جميع الأنشطة لتناسب تعدد النوافذ، بغض النظر عن قيم البيان."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"تمكين تغيير حجم جميع الأنشطة لتناسب تعدد النوافذ، بغض النظر عن قيم البيان."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"تمكين النوافذ الحرة"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"لتمكين إتاحة استخدام النوافذ الحرة التجريبية."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"تمكين إتاحة استخدام النوافذ الحرة التجريبية."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"كلمة مرور احتياطية للكمبيوتر"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"النسخ الاحتياطية الكاملة لسطح المكتب غير محمية في الوقت الحالي"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"انقر لتغيير كلمة مرور النسخ الاحتياطية الكاملة لسطح المكتب أو إزالتها."</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"معطَّل"</string> <string name="night_mode_yes" msgid="2218157265997633432">"التشغيل دائمًا"</string> <string name="night_mode_auto" msgid="7508348175804304327">"تلقائيًا"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"تطبيق WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"تعيين تطبيق WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"إن تنفيذ ميزة WebView التي تم اختيارها معطَّل، ويجب تمكين هذه الميزة ليتسنى استخدامها، فهل تريد تمكينها؟"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"تصحيح الألوان"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"هذه الميزة تجريبية وقد تؤثر في الأداء."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"تم الاستبدال بـ <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"يتبقى <xliff:g id="TIME">%1$s</xliff:g> تقريبًا"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - تبقى <xliff:g id="TIME">%2$s</xliff:g> تقريبًا"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> حتى الاكتمال"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"ممتلئة"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"تم التعطيل بواسطة المشرف"</string> <string name="home" msgid="8263346537524314127">"الشاشة الرئيسية"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"قبل <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"يتبقى <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml index 12b077e92d06..61008b944d84 100644 --- a/packages/SettingsLib/res/values-az-rAZ/strings.xml +++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Tətbiqlərə xaricdən məcburi icazə"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Seçilmiş hər hansı tətbiqi bəyannamə dəyərlərindən aslı olmayaraq xarici yaddaşa yazılabilən edir."</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Ölçü dəyişdirmək üçün məcburi fəaliyyətlər"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Bəyannamə dəyərlərindən aslı olmayaraq bütün fəaliyyətləri çoxsaylı pəncərə üçün dəyişkən ölçülü edir."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Bəyannamə dəyərlərindən aslı olmayaraq, bütün fəaliyyətləri çoxsaylı pəncərə üçün dəyişkən ölçülü edin."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Freeform windows aktiv edin"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Sınaq üçün freeform windows aktiv edir"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Sınaq üçün freeform windows aktiv edilir."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Masaüstü rezerv parolu"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Masaüstü tam rezervlər hazırda qorunmayıblar."</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Masaüstünün tam rezerv kopyalanması üçün parolu dəyişmək və ya silmək üçün basın"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Qeyri-aktiv"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Həmişə aktiv"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Avtomatik"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView icrası"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView icrasını ayarlayın"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Seçilmiş WebView icrası deaktiv edildi, istifadəsi üçün aktiv edilməlidir, aktivləşdirmək istəyirsiniz?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Rəng düzəlişi"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu funksiya eksperimentaldır və performansa təsir edə bilər."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> tərəfindən qəbul edilmir"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"Təxminən <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Təxminən <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - təxminən <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> dolana qədər"</string> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index ae5697867530..7021ca6226a5 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Prinudno dozvoli aplikacije u spoljnoj"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Omogućava upisivanje svih aplikacija u spoljnu memoriju, bez obzira na vrednosti manifesta"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Prinudno omogući promenu veličine aktivnosti"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Omogućava promenu veličine svih aktivnosti za režim sa više prozora, bez obzira na vrednosti manifesta."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Omogući promenu veličine svih aktivnosti za režim sa više prozora, bez obzira na vrednosti manifesta."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Omogući prozore proizvoljnog formata"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Omogućava podršku za eksperimentalne prozore proizvoljnog formata."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Omogućite podršku za eksperimentalne prozore proizvoljnog formata."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Lozinka rezervne kopije za računar"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Rezervne kopije čitavog sistema trenutno nisu zaštićene"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Dodirnite da biste promenili ili uklonili lozinku za pravljenje rezervnih kopija čitavog sistema na računaru"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Onemogućeno"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Uvek uključeno"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatski"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Primena WebView-a"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Podesite primenu WebView-a"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Izabrana primena WebView-a je onemogućena, a mora da bude omogućena radi korišćenja. Želite li da je omogućite?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korekcija boja"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova funkcija je eksperimentalna i može da utiče na performanse."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Zamenjuje ga <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Još otprilike <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo oko <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> dok se ne napuni"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Puno"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Onemogućio je administrator"</string> <string name="home" msgid="8263346537524314127">"Početni"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"Pre <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Još <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index ad0ace49864e..df47ad9b62be 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Външно хран.: Принуд. разрешаване на приложенията"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Позволява прилож. да се записват във външ. хранил. независимо от стойностите в манифеста"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Възможност за преоразмеряване на активностите"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Дава възможност за преоразмеряване на всички активности в режима за няколко прозореца независимо от стойностите в манифеста."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Дава възможност за преоразмеряване на всички активности в режима за няколко прозореца независимо от стойностите в манифеста."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Активиране на прозорците в свободна форма"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Активира поддръжката за експерименталните прозорци в свободна форма."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Активиране на поддръжката за експерименталните прозорци в свободна форма."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Наст. комп.: Парола"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Понастоящем пълните резервни копия за настолен компютър не са защитени"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Докоснете, за да промените или премахнете паролата за пълни резервни копия на настолния компютър"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Деактивирано"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Винаги включено"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Автоматично"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Внедряване на WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Задаване на внедряването на WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Избраното внедряване на WebView е деактивирано и трябва да го активирате, за да се използва. Искате ли да го направите?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Корекция на цветове"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Тази функция е експериментална и може да се отрази на ефективността."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Заменено от „<xliff:g id="TITLE">%1$s</xliff:g>“"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Прибл. оставащо време: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – приблизително оставащо време: <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Пълна"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Деактивирано от администратора"</string> <string name="home" msgid="8263346537524314127">"Начало"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"Преди <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Оставащо време: <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml index 589c52ef6018..e982a360f9df 100644 --- a/packages/SettingsLib/res/values-bn-rBD/strings.xml +++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"বহিরাগততে বলপূর্বক মঞ্জুরি"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ম্যানিফেস্ট মানগুলি নির্বিশেষে যেকোনো অ্যাপ্লিকেশানকে বাহ্যিক সঞ্চয়স্থানে লেখার উপযুক্ত বানায়"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"আকার পরিবর্তনযোগ্য করার জন্য ক্রিয়াকলাপগুলিকে জোর করুন"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"ম্যানিফেস্ট মানগুলির নির্বিশেষে মাল্টি-উইন্ডোর জন্য সমস্ত ক্রিয়াকলাপগুলিকে আকার পরিবর্তনযোগ্য করে তোলে৷"</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ম্যানিফেস্ট মানগুলির নির্বিশেষে মাল্টি-উইন্ডোর জন্য সমস্ত ক্রিয়াকলাপগুলিকে আকার পরিবর্তনযোগ্য করুন৷"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"ফ্রি-ফর্ম উইন্ডোগুলি সক্ষম করুন"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"পরীক্ষামূলক ফ্রি-ফর্ম উইন্ডোগুলির জন্য সহায়তা সক্ষম করুন৷"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"পরীক্ষামূলক ফ্রি-ফর্ম উইন্ডোগুলির জন্য সহায়তা সক্ষম করুন৷"</string> <string name="local_backup_password_title" msgid="3860471654439418822">"ডেস্কটপ ব্যাকআপ পাসওয়ার্ড"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"ডেস্কটপ পূর্ণ ব্যাকআপ বর্তমানে সুরক্ষিত নয়"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"ডেস্কটপের সম্পূর্ণ ব্যাকআপের পাসওয়ার্ডটি পরিবর্তন করতে বা মুছে ফেলতে আলতো চাপুন"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"অক্ষম করা রয়েছে"</string> <string name="night_mode_yes" msgid="2218157265997633432">"সবসময় চালু"</string> <string name="night_mode_auto" msgid="7508348175804304327">"স্বয়ংক্রিয়"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"ওয়েবভিউ প্রয়োগ"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"ওয়েবভিউ প্রয়োগ সেট করুন"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"নির্বাচিত ওয়েবভিউ প্রয়োগটি অক্ষম করা আছে এবং ব্যবহার করার জন্য অবশ্যই সক্ষম করতে হবে, আপনি কি এটিকে সক্ষম করতে চান?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"রঙ সংশোধন"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"এই বৈশিষ্ট্যটি পরীক্ষামূলক এবং এটি কার্য-সম্পাদনা প্রভাবিত করতে পারে।"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> এর দ্বারা ওভাররাইড করা হয়েছে"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"প্রায় <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"প্রায় <xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - আনুমানিক <xliff:g id="TIME">%2$s</xliff:g> বাকি আছে"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - সম্পূর্ণ হতে <xliff:g id="TIME">%2$s</xliff:g> বাকি"</string> diff --git a/packages/SettingsLib/res/values-bs-rBA/strings.xml b/packages/SettingsLib/res/values-bs-rBA/strings.xml index 8da12cb5c9fa..92c7ec841104 100644 --- a/packages/SettingsLib/res/values-bs-rBA/strings.xml +++ b/packages/SettingsLib/res/values-bs-rBA/strings.xml @@ -20,130 +20,69 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for wifi_fail_to_scan (1265540342578081461) --> - <skip /> - <!-- no translation found for wifi_security_none (7985461072596594400) --> - <skip /> - <!-- no translation found for wifi_remembered (4955746899347821096) --> - <skip /> - <!-- no translation found for wifi_disabled_generic (4259794910584943386) --> - <skip /> - <!-- no translation found for wifi_disabled_network_failure (2364951338436007124) --> - <skip /> - <!-- no translation found for wifi_disabled_wifi_failure (3081668066612876581) --> - <skip /> - <!-- no translation found for wifi_disabled_password_failure (8659805351763133575) --> - <skip /> - <!-- no translation found for wifi_not_in_range (1136191511238508967) --> - <skip /> - <!-- no translation found for wifi_no_internet (9151470775868728896) --> - <skip /> - <!-- no translation found for saved_network (4352716707126620811) --> - <skip /> - <!-- no translation found for connected_via_wfa (3805736726317410714) --> - <skip /> - <!-- no translation found for connected_via_passpoint (2826205693803088747) --> - <skip /> - <!-- no translation found for available_via_passpoint (1617440946846329613) --> - <skip /> - <!-- no translation found for wifi_connected_no_internet (3149853966840874992) --> - <skip /> - <!-- no translation found for bluetooth_disconnected (6557104142667339895) --> - <skip /> - <!-- no translation found for bluetooth_disconnecting (8913264760027764974) --> - <skip /> - <!-- no translation found for bluetooth_connecting (8555009514614320497) --> - <skip /> - <!-- no translation found for bluetooth_connected (6038755206916626419) --> - <skip /> - <!-- no translation found for bluetooth_pairing (1426882272690346242) --> - <skip /> - <!-- no translation found for bluetooth_connected_no_headset (2866994875046035609) --> - <skip /> - <!-- no translation found for bluetooth_connected_no_a2dp (4576188601581440337) --> - <skip /> - <!-- no translation found for bluetooth_connected_no_map (6504436917057479986) --> - <skip /> - <!-- no translation found for bluetooth_connected_no_headset_no_a2dp (9195757766755553810) --> - <skip /> - <!-- no translation found for bluetooth_profile_a2dp (2031475486179830674) --> - <skip /> - <!-- no translation found for bluetooth_profile_headset (8658779596261212609) --> - <skip /> - <!-- no translation found for bluetooth_profile_opp (9168139293654233697) --> - <skip /> - <!-- no translation found for bluetooth_profile_hid (3680729023366986480) --> - <skip /> - <!-- no translation found for bluetooth_profile_pan (3391606497945147673) --> - <skip /> - <!-- no translation found for bluetooth_profile_pbap (5372051906968576809) --> - <skip /> - <!-- no translation found for bluetooth_profile_pbap_summary (6605229608108852198) --> - <skip /> - <!-- no translation found for bluetooth_profile_pan_nap (8429049285027482959) --> - <skip /> - <!-- no translation found for bluetooth_profile_map (5465271250454324383) --> - <skip /> - <!-- no translation found for bluetooth_profile_sap (5764222021851283125) --> - <skip /> - <!-- no translation found for bluetooth_a2dp_profile_summary_connected (963376081347721598) --> - <skip /> - <!-- no translation found for bluetooth_headset_profile_summary_connected (7661070206715520671) --> - <skip /> - <!-- no translation found for bluetooth_opp_profile_summary_connected (2611913495968309066) --> - <skip /> - <!-- no translation found for bluetooth_map_profile_summary_connected (8191407438851351713) --> - <skip /> - <!-- no translation found for bluetooth_sap_profile_summary_connected (8561765057453083838) --> - <skip /> - <!-- no translation found for bluetooth_opp_profile_summary_not_connected (1267091356089086285) --> - <skip /> - <!-- no translation found for bluetooth_hid_profile_summary_connected (3381760054215168689) --> - <skip /> + <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ne može skenirati mreže"</string> + <string name="wifi_security_none" msgid="7985461072596594400">"Nema"</string> + <string name="wifi_remembered" msgid="4955746899347821096">"Sačuvano"</string> + <string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogućeno"</string> + <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Greška u konfiguraciji IP-a"</string> + <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Greška pri povezivanju na Wi-Fi"</string> + <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem pri provjeri vjerodostojnosti."</string> + <string name="wifi_not_in_range" msgid="1136191511238508967">"Nije u dometu"</string> + <string name="wifi_no_internet" msgid="9151470775868728896">"Pristup internetu nije pronađen. Neće se ponovo povezivati automatski."</string> + <string name="saved_network" msgid="4352716707126620811">"Sačuvao <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_wfa" msgid="3805736726317410714">"Povezani preko Wi-Fi pomoćnika"</string> + <string name="connected_via_passpoint" msgid="2826205693803088747">"Povezani preko %1$s"</string> + <string name="available_via_passpoint" msgid="1617440946846329613">"Dostupan preko %1$s"</string> + <string name="wifi_connected_no_internet" msgid="3149853966840874992">"Povezano. Nema interneta"</string> + <string name="bluetooth_disconnected" msgid="6557104142667339895">"Isključen"</string> + <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Prekidanje veze…"</string> + <string name="bluetooth_connecting" msgid="8555009514614320497">"Povezivanje…"</string> + <string name="bluetooth_connected" msgid="6038755206916626419">"Povezano"</string> + <string name="bluetooth_pairing" msgid="1426882272690346242">"Uparivanje…"</string> + <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Povezano (bez telefona)"</string> + <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Povezano (bez medija)"</string> + <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Povezano (bez pristupa porukama)"</string> + <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Povezano (bez zvuka telefona ili medija)"</string> + <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Zvuk medija"</string> + <string name="bluetooth_profile_headset" msgid="8658779596261212609">"Zvuk telefona"</string> + <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Prenošenje fajla"</string> + <string name="bluetooth_profile_hid" msgid="3680729023366986480">"Ulazni uređaj"</string> + <string name="bluetooth_profile_pan" msgid="3391606497945147673">"Pristup internetu"</string> + <string name="bluetooth_profile_pbap" msgid="5372051906968576809">"Dijeljenje kontakta"</string> + <string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"Koristi za dijeljenje kontakta"</string> + <string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"Dijeljenje internet veze"</string> + <string name="bluetooth_profile_map" msgid="5465271250454324383">"Pristup poruci"</string> + <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Pristup SIM-u"</string> + <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Povezano sa zvukom medija"</string> + <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Povezano na zvuk telefona"</string> + <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Povezan na server za prijenos podataka"</string> + <string name="bluetooth_map_profile_summary_connected" msgid="8191407438851351713">"Povezano na mapu"</string> + <string name="bluetooth_sap_profile_summary_connected" msgid="8561765057453083838">"Povezan na SAP"</string> + <string name="bluetooth_opp_profile_summary_not_connected" msgid="1267091356089086285">"Nije povezan na server za prijenos podataka"</string> + <string name="bluetooth_hid_profile_summary_connected" msgid="3381760054215168689">"Spojen na ulazni uređaj"</string> <string name="bluetooth_pan_user_profile_summary_connected" msgid="4602294638909590612">"Pov. na ur. za pris. int."</string> <string name="bluetooth_pan_nap_profile_summary_connected" msgid="1561383706411975199">"Dij. lok. int. veze s ur."</string> - <!-- no translation found for bluetooth_pan_profile_summary_use_for (5664884523822068653) --> - <skip /> - <!-- no translation found for bluetooth_map_profile_summary_use_for (5154200119919927434) --> - <skip /> - <!-- no translation found for bluetooth_sap_profile_summary_use_for (7085362712786907993) --> - <skip /> - <!-- no translation found for bluetooth_a2dp_profile_summary_use_for (4630849022250168427) --> - <skip /> - <!-- no translation found for bluetooth_headset_profile_summary_use_for (8705753622443862627) --> - <skip /> - <!-- no translation found for bluetooth_opp_profile_summary_use_for (1255674547144769756) --> - <skip /> - <!-- no translation found for bluetooth_hid_profile_summary_use_for (232727040453645139) --> - <skip /> - <!-- no translation found for bluetooth_pairing_accept (6163520056536604875) --> - <skip /> - <!-- no translation found for bluetooth_pairing_accept_all_caps (6061699265220789149) --> - <skip /> - <!-- no translation found for bluetooth_pairing_decline (4185420413578948140) --> - <skip /> - <!-- no translation found for bluetooth_pairing_will_share_phonebook (4982239145676394429) --> - <skip /> - <!-- no translation found for bluetooth_pairing_error_message (3748157733635947087) --> - <skip /> - <!-- no translation found for bluetooth_pairing_pin_error_message (8337234855188925274) --> - <skip /> - <!-- no translation found for bluetooth_pairing_device_down_error_message (7870998403045801381) --> - <skip /> - <!-- no translation found for bluetooth_pairing_rejected_error_message (1648157108520832454) --> - <skip /> - <!-- no translation found for accessibility_wifi_off (1166761729660614716) --> - <skip /> - <!-- no translation found for accessibility_no_wifi (8834610636137374508) --> - <skip /> - <!-- no translation found for accessibility_wifi_one_bar (4869376278894301820) --> - <skip /> - <!-- no translation found for accessibility_wifi_two_bars (3569851234710034416) --> - <skip /> - <!-- no translation found for accessibility_wifi_three_bars (8134185644861380311) --> - <skip /> - <!-- no translation found for accessibility_wifi_signal_full (7061045677694702) --> - <skip /> + <string name="bluetooth_pan_profile_summary_use_for" msgid="5664884523822068653">"Koristi za pristup internetu"</string> + <string name="bluetooth_map_profile_summary_use_for" msgid="5154200119919927434">"Koristi za mapu"</string> + <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"Koristi za pristup SIM-u"</string> + <string name="bluetooth_a2dp_profile_summary_use_for" msgid="4630849022250168427">"Koristi za zvuk medija"</string> + <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Koristi za zvuk telefona"</string> + <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Koristi za prijenos fajlova"</string> + <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Koristi kao ulaz"</string> + <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Upari"</string> + <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"UPARI"</string> + <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Otkaži"</string> + <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Uparivanje odobrava pristup kontaktima i istoriji poziva kada je uspostavljeno."</string> + <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"Nije se moguće upariti s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> + <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"Nije se moguće upariti s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g> zbog pogrešnog PIN-a ili pristupnog koda."</string> + <string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"Ne može komunicirati sa uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> + <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"Uređaj <xliff:g id="DEVICE_NAME">%1$s</xliff:g> je odbio uparivanje."</string> + <string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi isključen."</string> + <string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi nije povezan."</string> + <string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi jedna crtica."</string> + <string name="accessibility_wifi_two_bars" msgid="3569851234710034416">"Wi-Fi dvije crtice."</string> + <string name="accessibility_wifi_three_bars" msgid="8134185644861380311">"Wi-Fi tri crtice."</string> + <string name="accessibility_wifi_signal_full" msgid="7061045677694702">"Wi-Fi puni signal."</string> <string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string> <string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Uklonjene aplikacije"</string> <string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Uklonjene aplikacije i korisnici"</string> @@ -177,27 +116,27 @@ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> je u potpunosti podržan"</string> <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> zahtjeva mrežnu vezu"</string> <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> nije podržan"</string> - <!-- no translation found for tts_status_checking (5339150797940483592) --> - <skip /> + <string name="tts_status_checking" msgid="5339150797940483592">"Provjerava se…"</string> <string name="tts_engine_settings_title" msgid="3499112142425680334">"Postavke za <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string> <string name="tts_engine_settings_button" msgid="1030512042040722285">"Pokreni postavke programa"</string> <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Željeni program"</string> <string name="tts_general_section_title" msgid="4402572014604490502">"Opće"</string> - <!-- no translation found for tts_rate_entries:0 (6695494874362656215) --> - <!-- no translation found for tts_rate_entries:1 (4795095314303559268) --> - <!-- no translation found for tts_rate_entries:2 (8903157781070679765) --> - <!-- no translation found for tts_rate_entries:3 (164347302621392996) --> - <!-- no translation found for tts_rate_entries:4 (5794028588101562009) --> - <!-- no translation found for tts_rate_entries:5 (7163942783888652942) --> - <!-- no translation found for tts_rate_entries:6 (7831712693748700507) --> - <!-- no translation found for tts_rate_entries:7 (5194774745031751806) --> - <!-- no translation found for tts_rate_entries:8 (9085102246155045744) --> + <string-array name="tts_rate_entries"> + <item msgid="6695494874362656215">"Veoma sporo"</item> + <item msgid="4795095314303559268">"Sporo"</item> + <item msgid="8903157781070679765">"Normalno"</item> + <item msgid="164347302621392996">"Brzo"</item> + <item msgid="5794028588101562009">"Brže"</item> + <item msgid="7163942783888652942">"Veoma brzo"</item> + <item msgid="7831712693748700507">"Ubrzano"</item> + <item msgid="5194774745031751806">"Veoma ubrzano"</item> + <item msgid="9085102246155045744">"Najbrže"</item> + </string-array> <string name="choose_profile" msgid="8229363046053568878">"Odaberite profil"</string> <string name="category_personal" msgid="1299663247844969448">"Lično"</string> <string name="category_work" msgid="8699184680584175622">"Posao"</string> <string name="development_settings_title" msgid="215179176067683667">"Opcije za programere"</string> - <!-- no translation found for development_settings_enable (542530994778109538) --> - <skip /> + <string name="development_settings_enable" msgid="542530994778109538">"Omogući opcije za programere"</string> <string name="development_settings_summary" msgid="1815795401632854041">"Postavi opcije za razvoj aplikacija"</string> <string name="development_settings_not_available" msgid="4308569041701535607">"Opcije za programere nisu dostupne za ovog korisnika"</string> <string name="vpn_settings_not_available" msgid="956841430176985598">"VPN postavke nisu dostupne za ovog korisnika"</string> @@ -306,18 +245,12 @@ <string name="app_process_limit_title" msgid="4280600650253107163">"Ograničenje procesa u pozadini"</string> <string name="show_all_anrs" msgid="28462979638729082">"Prikaži sve ANR-ove"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Prik. dijalog Aplikacija ne reagira za apl. u poz."</string> - <!-- no translation found for force_allow_on_external (3215759785081916381) --> - <skip /> - <!-- no translation found for force_allow_on_external_summary (3191952505860343233) --> - <skip /> - <!-- no translation found for force_resizable_activities (8615764378147824985) --> - <skip /> - <!-- no translation found for force_resizable_activities_summary (4508217476997182216) --> - <skip /> - <!-- no translation found for enable_freeform_support (1461893351278940416) --> - <skip /> - <!-- no translation found for enable_freeform_support_summary (2252563497485436534) --> - <skip /> + <string name="force_allow_on_external" msgid="3215759785081916381">"Nametni aplikacije na vanjskoj pohrani"</string> + <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Dozvoljava da bilo koja aplikacija bude upisana na vanjsku pohranu, bez obzira na vrijednosti manifesta."</string> + <string name="force_resizable_activities" msgid="8615764378147824985">"Nametni aktivnostima mijenjanje veličina"</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Neka sve aktivnosti budu takve da mogu mijenjati veličinu za prikaz sa više prozora, bez obzira na prikazane vrijednosti."</string> + <string name="enable_freeform_support" msgid="1461893351278940416">"Omogući prozore nepravilnih oblika"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Omogućiti podršku za eksperimentalne prozore nepravilnih oblika."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Lozinka za rezervnu kopiju radne površine"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Potpune sigurnosne kopije za računare trenutno nisu zaštićene"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Dodirnite da promijenite ili uklonite lozinku za potpune rezervne kopije sa radne površine"</string> @@ -339,32 +272,24 @@ <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktivno. Dodirnite za promjenu opcije."</string> <string name="runningservices_settings_title" msgid="8097287939865165213">"Pokrenute usluge"</string> <string name="runningservices_settings_summary" msgid="854608995821032748">"Prikažite trenutno pokrenute usluge i upravljajte njima"</string> - <!-- no translation found for night_mode_title (2594133148531256513) --> - <skip /> + <string name="night_mode_title" msgid="2594133148531256513">"Noćni način rada"</string> <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string> - <!-- no translation found for night_mode_no (9171772244775838901) --> - <skip /> - <!-- no translation found for night_mode_yes (2218157265997633432) --> - <skip /> + <string name="night_mode_no" msgid="9171772244775838901">"Onemogućeno"</string> + <string name="night_mode_yes" msgid="2218157265997633432">"Uvijek uključeno"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatski"</string> - <!-- no translation found for select_webview_provider_title (4628592979751918907) --> - <skip /> - <!-- no translation found for select_webview_provider_dialog_title (4370551378720004872) --> - <skip /> - <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) --> - <skip /> - <!-- no translation found for convert_to_file_encryption (3060156730651061223) --> - <skip /> - <!-- no translation found for convert_to_file_encryption_enabled (2861258671151428346) --> - <skip /> - <!-- no translation found for convert_to_file_encryption_done (7859766358000523953) --> - <skip /> - <!-- no translation found for title_convert_fbe (1263622876196444453) --> - <skip /> - <!-- no translation found for convert_to_fbe_warning (6139067817148865527) --> - <skip /> - <!-- no translation found for button_convert_fbe (5152671181309826405) --> - <skip /> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> + <string name="select_webview_provider_title" msgid="4628592979751918907">"Postavljanje WebViewa"</string> + <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Podesi WebView"</string> + <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Postavljanje izabranog WebViewa je onemogućeno. Da bi se mogao koristiti, mora biti omogućen. Želite li ga omogućiti?"</string> + <string name="convert_to_file_encryption" msgid="3060156730651061223">"Pretvori u šifrirani fajl"</string> + <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Pretvaranje…"</string> + <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Fajl je već šifriran"</string> + <string name="title_convert_fbe" msgid="1263622876196444453">"Pretvaranje u šifrirane fajlove"</string> + <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Pretvori particiju sa podacima u particiju šifriranu sistemom fajlova.\n !! Upozorenje!! Ovo će izbrisati sve vaše podatke.\n Ova funkcija je u alfa fazi razvoja i možda neće ispravno raditi.\n Pritisnite \'Obriši i pretvori…\" da nastavite."</string> + <string name="button_convert_fbe" msgid="5152671181309826405">"Obriši i pretvori…"</string> <string name="picture_color_mode" msgid="4560755008730283695">"Režim boja Slika"</string> <string name="picture_color_mode_desc" msgid="1141891467675548590">"Koristi sRGB"</string> <string name="daltonizer_mode_disabled" msgid="7482661936053801862">"Onemogućeno"</string> @@ -375,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Ispravka boje"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova funkcija je eksperimentalna te može utjecati na performanse."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Zamjenjuje <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Još otprilike <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo vreme je otprilike <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pune baterije"</string> @@ -393,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Puna"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Onemogućio administrator"</string> <string name="home" msgid="8263346537524314127">"Početna stranica"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"prije <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Još otprilike <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index 333868b704a0..beb909e1a502 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Força permís d\'aplicacions a l\'emmagatzem. extern"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Permet que les aplicacions es puguin escriure en un dispositiu d’emmagatzematge extern, independentment dels valors definits"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Força l\'ajust de la mida de les activitats"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Permet ajustar la mida de totes les activitats per al mode multifinestra, independentment dels valors definits."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permet ajustar la mida de totes les activitats per al mode multifinestra, independentment dels valors definits."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Activa les finestres de format lliure"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Activa la compatibilitat amb les finestres de format lliure experimentals."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Activa la compatibilitat amb finestres de format lliure experimentals."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Contrasenya per a còpies d\'ordinador"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Les còpies de seguretat d\'ordinador completes no estan protegides"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Toca per canviar o suprimir la contrasenya per a les còpies de seguretat completes de l\'ordinador"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Desactivat"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Sempre activat"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automàtic"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementació de WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configura la implementació de WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"La implementació de WebView que has triat està desactivada i s\'ha d\'activar per utilitzar-la. Vols activar-la?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correcció del color"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Aquesta funció és experimental i pot afectar el rendiment."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"S\'ha substituït per <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Temps restant aproximat: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g>: falten aproximadament <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Plena"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Opció desactivada per l\'administrador"</string> <string name="home" msgid="8263346537524314127">"Inici"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"Fa <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Temps restant: <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index e21995958567..ad01febb56d4 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Vynutit povolení aplikací na externím úložišti"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Každou aplikaci bude možné zapsat do externího úložiště, bez ohledu na hodnoty manifestu"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Vynutit možnost změny velikosti aktivit"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Velikost všech aktivit bude možné změnit na několik oken (bez ohledu na hodnoty manifestu)."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Umožnit změnu velikosti všech aktivit na několik oken (bez ohledu na hodnoty manifestu)"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Aktivovat okna s volným tvarem"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Aktivuje podporu experimentálních oken s volným tvarem."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Aktivovat podporu experimentálních oken s volným tvarem"</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Heslo pro zálohy v počítači"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Úplné zálohy v počítači nejsou v současné době chráněny"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tuto možnost vyberte, chcete-li změnit nebo odebrat heslo pro úplné zálohy do počítače"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Vypnuto"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Vždy zapnuto"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatický"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementace WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Nastavte implementaci WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Vybraná implementace WebView je zakázána a nelze ji použít. Chcete ji povolit a použít?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korekce barev"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Funkce je experimentální a může mít vliv na výkon."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Přepsáno nastavením <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Zbývající čas: <xliff:g id="TIME">%1$s</xliff:g> (přibližně)"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – zbývá přibližně <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Nabitá"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Zakázáno administrátorem"</string> <string name="home" msgid="8263346537524314127">"Plocha"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"před <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Zbývající čas: <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index 6acdcc7cbf79..e86904453afa 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Gennemtving tilladelse til eksternt lager"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Gør det muligt at overføre enhver app til et eksternt lager uafhængigt af manifestværdier"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Tving aktiviteter til at kunne tilpasses"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Sørger for, at alle aktiviteter kan tilpasses flere vinduer uafhængigt af manifestværdier."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Tillad, at alle aktiviteter kan tilpasses flere vinduer uafhængigt af manifestværdier."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Aktivér vinduer i frit format"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Aktiverer understøttelse af eksperimentelle vinduer i frit format."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Aktivér understøttelse af eksperimentelle vinduer i frit format."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Kode til lokal sikkerhedskopi"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Lokale fuldstændige sikkerhedskopieringer er i øjeblikket ikke beskyttet"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tryk for at skifte eller fjerne adgangskoden til fuld lokal sikkerhedskopiering"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Deaktiveret"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Altid slået til"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatisk"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Konfigurer WebView-implementering"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Den valgte WebView-implementering er deaktiveret og skal aktiveres, før den kan bruges. Vil du aktivere den?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korriger farver"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Denne funktion er eksperimentel og kan påvirke ydeevnen."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Tilsidesat af <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca. <xliff:g id="TIME">%2$s</xliff:g> tilbage"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca. <xliff:g id="TIME">%1$s</xliff:g> tilbage"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – ca. <xliff:g id="TIME">%2$s</xliff:g> tilbage"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til fuldt opladet"</string> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index 5f4f60b1f5a8..56d2543b1b20 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Externe Speichernutzung von Apps erlauben"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Ermöglicht es jeder qualifizierten App, Daten auf externen Speicher zu schreiben, unabhängig von den Manifestwerten"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Anpassen der Größe von Aktivitäten erzwingen"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Ermöglicht es, die Größe aller Aktivitäten an den Mehrfenstermodus anzupassen, unabhängig von den Manifestwerten."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Größe aller Aktivitäten an den Mehrfenstermodus anpassen, unabhängig von den Manifestwerten."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Freiform-Fenster zulassen"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Unterstützt experimentelle Freiform-Fenster."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Experimentelle Freiform-Fenster unterstützen."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Desktop-Sicherungspasswort"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Vollständige Desktop-Sicherungen sind momentan nicht passwortgeschützt."</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Zum Ändern oder Entfernen des Passworts für vollständige Desktop-Sicherungen tippen"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Deaktiviert"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Immer an"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatisch"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-Implementierung"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView-Implementierung festlegen"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Die ausgewählte WebView-Implementierung ist deaktiviert. Um sie nutzen zu können, muss sie aktiviert sein. Möchtest du sie aktivieren?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Farbkorrektur"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Hierbei handelt es sich um eine experimentelle Funktion. Dies kann sich auf die Leistung auswirken."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Außer Kraft gesetzt von \"<xliff:g id="TITLE">%1$s</xliff:g>\""</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Noch ca. <xliff:g id="TIME">%1$s</xliff:g> verbleibend"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – noch etwa <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – voll in <xliff:g id="TIME">%2$s</xliff:g>"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Voll"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Vom Administrator deaktiviert"</string> <string name="home" msgid="8263346537524314127">"Startseite"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"Vor <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Noch <xliff:g id="ID_1">%1$s</xliff:g> verbleibend"</string> </resources> diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index 826e8233e7dc..e9f86615a2f5 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Να επιτρέπονται υποχρεωτικά εφαρμογές σε εξωτ.συσ."</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Κάνει κάθε εφαρμογή κατάλληλη για εγγραφή σε εξωτερικό χώρο αποθήκευσης, ανεξάρτητα από τις τιμές του μανιφέστου"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Αναγκαστική δυνατότητα αλλαγής μεγέθους δραστηριοτήτων"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Να έχουν όλες οι δραστηριότητες δυνατότητα αλλαγής μεγέθους για την προβολή πολλαπλών παραθύρων, ανεξάρτητα από τις τιμές του μανιφέστου."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Να έχουν όλες οι δραστηριότητες δυνατότητα αλλαγής μεγέθους για την προβολή πολλαπλών παραθύρων, ανεξάρτητα από τις τιμές του μανιφέστου."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Ενεργοποίηση παραθύρων ελεύθερης μορφής"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Ενεργοποιεί την υποστήριξη για πειραματικά παράθυρα ελεύθερης μορφής."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Ενεργοποίηση υποστήριξης για πειραματικά παράθυρα ελεύθερης μορφής."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Εφ/κός κωδικός desktop"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Τα πλήρη αντίγραφα ασφαλείας επιφάνειας εργασίας δεν προστατεύονται αυτήν τη στιγμή"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Πατήστε για αλλαγή ή κατάργηση του κωδικού πρόσβασης για τα πλήρη αντίγραφα ασφαλείας επιφάνειας εργασίας"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Ανενεργό"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Πάντα ενεργό"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Αυτόματο"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Υλοποίηση WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Ορισμός υλοποίησης WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Η επιλεγμένη ενσωμάτωση WebView είναι απενεργοποιημένη και θα πρέπει να ενεργοποιηθεί για να χρησιμοποιηθεί. Θέλετε να την ενεργοποιήσετε;"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Διόρθωση χρωμάτων"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Αυτή η λειτουργία είναι πειραματική και ενδεχομένως να επηρεάσει τις επιδόσεις."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Αντικαταστάθηκε από <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Απομένουν περίπου <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - απομένουν περίπου <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Πλήρης"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Απενεργοποιήθηκε από το διαχειριστή"</string> <string name="home" msgid="8263346537524314127">"Αρχική οθόνη"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"Πριν από <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Απομένουν <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml index 481cc47e0ae9..668e0b2fcbad 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Makes any app eligible to be written to external storage, regardless of manifest values"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Makes all activities re-sizable for multi-window, regardless of manifest values."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Make all activities resizable for multi-window, regardless of manifest values."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Enable freeform windows"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Enables support for experimental freeform windows."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Enable support for experimental freeform windows."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Desktop backup password"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Desktop full backups aren\'t currently protected"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tap to change or remove the password for desktop full backups"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Disabled"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Always on"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatic"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Set WebView implementation"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"The chosen WebView implementation is disabled and must be enabled to be used, do you wish to enable it?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Colour correction"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%2$s</xliff:g> left"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%1$s</xliff:g> left"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – approx. <xliff:g id="TIME">%2$s</xliff:g> left"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full"</string> diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml index 481cc47e0ae9..668e0b2fcbad 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Makes any app eligible to be written to external storage, regardless of manifest values"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Makes all activities re-sizable for multi-window, regardless of manifest values."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Make all activities resizable for multi-window, regardless of manifest values."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Enable freeform windows"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Enables support for experimental freeform windows."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Enable support for experimental freeform windows."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Desktop backup password"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Desktop full backups aren\'t currently protected"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tap to change or remove the password for desktop full backups"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Disabled"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Always on"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatic"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Set WebView implementation"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"The chosen WebView implementation is disabled and must be enabled to be used, do you wish to enable it?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Colour correction"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%2$s</xliff:g> left"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%1$s</xliff:g> left"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – approx. <xliff:g id="TIME">%2$s</xliff:g> left"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full"</string> diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index 481cc47e0ae9..668e0b2fcbad 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Makes any app eligible to be written to external storage, regardless of manifest values"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Makes all activities re-sizable for multi-window, regardless of manifest values."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Make all activities resizable for multi-window, regardless of manifest values."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Enable freeform windows"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Enables support for experimental freeform windows."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Enable support for experimental freeform windows."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Desktop backup password"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Desktop full backups aren\'t currently protected"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tap to change or remove the password for desktop full backups"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Disabled"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Always on"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatic"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Set WebView implementation"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"The chosen WebView implementation is disabled and must be enabled to be used, do you wish to enable it?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Colour correction"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%2$s</xliff:g> left"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%1$s</xliff:g> left"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – approx. <xliff:g id="TIME">%2$s</xliff:g> left"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full"</string> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index 738024014cf1..05ab073ad699 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permisos en almacenamiento externo"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Cualquier aplicación puede escribirse en una memoria externa, independientemente de los valores del manifiesto."</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Forzar actividades para que cambien de tamaño"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Permite que todas las actividades puedan cambiar de tamaño para el modo multiventana, sin importar los valores del manifiesto."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permitir que todas las actividades puedan cambiar de tamaño para el modo multiventana, sin importar los valores del manifiesto."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Habilitar ventanas de forma libre"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Habilita la admisión de ventanas de forma libre experimentales."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Habilitar la admisión de ventanas de forma libre experimentales."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Contraseñas"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Tus copias de seguridad de escritorio no están protegidas por contraseña."</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Presiona para cambiar o quitar la contraseña de las copias de seguridad completas de tu escritorio."</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Inhabilitado"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Siempre activado"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automático"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configurar la implementación de WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"La implementación de WebView que elegiste está inhabilitada. Debes habilitarla para poder usarla. ¿Quieres hacerlo?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Corrección de color"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función es experimental y puede afectar el rendimiento."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Reemplazado por <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Falta <xliff:g id="TIME">%1$s</xliff:g> aproximadamente"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g>: alrededor de <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Cargado"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Inhabilitada por el administrador"</string> <string name="home" msgid="8263346537524314127">"Página principal"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"Hace <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Falta <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index 1cf51fe7112b..5fea7554c5cb 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permiso de aplicaciones de forma externa"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Hace que cualquier aplicación se pueda escribir en un dispositivo de almacenamiento externo, independientemente de los valores definidos"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Forzar el ajuste de tamaño de las actividades"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Permite que se pueda ajustar el tamaño de todas las actividades para el modo multiventana, independientemente de los valores establecidos."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permite que se pueda ajustar el tamaño de todas las actividades para el modo multiventana, independientemente de los valores establecidos."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Habilitar ventanas de forma libre"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Permite utilizar ventanas de forma libre experimentales."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Habilita la opción para utilizar ventanas de forma libre experimentales."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Contraseña para copias de ordenador"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Las copias de seguridad completas de ordenador no están protegidas"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Toca para cambiar o quitar la contraseña de las copias de seguridad completas del escritorio"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Inhabilitado"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Siempre activado"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automático"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Establecer implementación de WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"La implementación de WebView seleccionada está inhabilitada y debes habilitarla para utilizarla. ¿Quieres hacerlo?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Corrección del color"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función es experimental y puede afectar al rendimiento."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Tiempo restante (aproximado): <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - Quedan <xliff:g id="TIME">%2$s</xliff:g> aproximadamente"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la batería"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Completa"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Inhabilitada por el administrador"</string> <string name="home" msgid="8263346537524314127">"Inicio"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"Hace <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Tiempo restante: <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml index c5153ff7e541..b9d011bee9d4 100644 --- a/packages/SettingsLib/res/values-et-rEE/strings.xml +++ b/packages/SettingsLib/res/values-et-rEE/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Luba rakendused välises salvestusruumis"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Lubab rakendusi kirjutada välisesse salvestusruumi olenemata manifesti väärtustest"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Muuda tegevuste suurused muudetavaks"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Muudab kõigi tegevuste suurused mitme aknaga vaates olenemata manifesti väärtustest muudetavaks."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Muudetakse kõigi tegevuste suurused mitme aknaga vaates muudetavaks (manifesti väärtustest olenemata)."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Luba vabas vormis aknad"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Lubatakse katseliste vabas vormis akende tugi."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Lubatakse katseliste vabavormis akende tugi."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Arvutivarunduse parool"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Täielikud arvutivarundused pole praegu kaitstud"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Puudutage täielike arvutivarunduste parooli muutmiseks või eemaldamiseks"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Keelatud"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Alati sees"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automaatne"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView\' rakendamine"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView\' rakendamise seadistamine"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Valitud WebView\' rakendamisviis on keelatud ja see tuleb kasutamiseks lubada. Kas soovite selle lubada?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Värviparandus"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"See funktsioon on katseline ja võib mõjutada toimivust."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Alistas <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"Umbes <xliff:g id="TIME">%2$s</xliff:g> on jäänud"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Umbes <xliff:g id="TIME">%1$s</xliff:g> on jäänud"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – jäänud on umbes <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, kuni aku on täis"</string> diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml index 1e06c6ad6ac4..c1be37fc3e81 100644 --- a/packages/SettingsLib/res/values-eu-rES/strings.xml +++ b/packages/SettingsLib/res/values-eu-rES/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Behartu aplikazioak onartzea kanpoko biltegian"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Aplikazioek kanpoko memorian idatz dezakete, manifestuaren balioak kontuan izan gabe"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Behartu jardueren tamaina doitu ahal izatea"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Manifestuan jartzen duena jartzen duela ere, jarduera guztien tamaina doitzeko aukera ematen du, hainbat leihotan erabili ahal izan daitezen."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Eman aukera jarduera guztien tamaina doitzeko, hainbat leihotan erabili ahal izan daitezen, manifestuan jartzen duena jartzen duela ere."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Gaitu estilo libreko leihoak"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Estilo libreko leiho esperimentalak onartzen ditu."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Onartu estilo libreko leiho esperimentalak."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Tokiko babeskop. pasahitza"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Une honetan, ordenagailuko babeskopia osoak ez daude babestuta."</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Ordenagailuko eduki guztiaren babeskopia egiteko erabiltzen den pasahitza aldatzeko edo kentzeko, sakatu hau"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Desgaituta"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Beti aktibatuta"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatikoa"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Set WebView implementation"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Desgaituta dago aukeratu den WebView inplementazioa. Erabili nahi izanez gero, gaitu egin behar duzu. Gaitu nahi al duzu?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Kolore-zuzenketa"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Eginbidea esperimentala da eta eragina izan dezake funtzionamenduan."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> hobespena gainjarri zaio"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"<xliff:g id="TIME">%1$s</xliff:g> inguru guztiz kargatu arte"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> inguru. <xliff:g id="TIME">%2$s</xliff:g> geratzen d(ir)a"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Beteta"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Administratzaileak desgaitu du"</string> <string name="home" msgid="8263346537524314127">"Hasierako pantaila"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"Duela <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> guztiz kargatu arte"</string> </resources> diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index e023f247c7d2..fc4cd7d1dd51 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"اجازه اجباری به برنامههای دستگاه ذخیره خارجی"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"بدون توجه به مقادیر مانیفست، هر برنامهای را برای نوشتن در حافظه خارجی واجد شرایط میکند"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"اجبار فعالیتها به قابل تغییر اندازه بودن"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"بدون درنظر گرفتن مقادیر مانیفست، همه فعالیتها را برای چندپنجره قابل تغییر اندازه میکند."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"بدون توجه به مقادیر مانیفست، اندازه همه فعالیتها برای حالت چند پنجرهای میتواند تغییر کند."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"فعال کردن پنجرههای آزاد"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"پشتیبانی برای پنجرههای آزاد آزمایشی را امکانپذیر میکند"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"فعال کردن پشتیبانی برای پنجرههای آزاد آزمایشی."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"گذرواژه پشتیبانگیری محلی"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"پشتیبانگیری کامل رایانه درحال حاضر محافظت نمیشود"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"برای تغییر یا حذف گذرواژه برای نسخههای پشتیبان کامل رایانهای ضربه بزنید"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"غیرفعال است"</string> <string name="night_mode_yes" msgid="2218157265997633432">"همیشه روشن"</string> <string name="night_mode_auto" msgid="7508348175804304327">"خودکار"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"اجرای WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"تنظیم اجرای WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"پیادهسازی WebView انتخابشده غیرفعال شده است و برای استفاده شدن باید فعال شود؛ میخواهید آن را فعال کنید؟"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"تصحیح رنگ"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"این قابلیت آزمایشی است و ممکن است عملکرد را تحت تأثیر قرار دهد."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"توسط <xliff:g id="TITLE">%1$s</xliff:g> لغو شد"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"تقریباً <xliff:g id="TIME">%1$s</xliff:g> باقی مانده است"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - تقریباً <xliff:g id="TIME">%2$s</xliff:g> باقی مانده است"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"پر"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"سرپرست آن را غیرفعال کرده است"</string> <string name="home" msgid="8263346537524314127">"صفحه اصلی"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> قبل"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> باقی مانده است"</string> </resources> diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index c4f572cfab0c..34309c193a7f 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Salli aina ulkoinen tallennus"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Mahdollistaa sovellusten tallentamisen ulkoiseen tall.tilaan luettelosta riippumatta"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Pakota kaikki toiminnot hyväksymään koon muutos"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Pakottaa kaikki toiminnot hyväksymään koon muuttamisen rinnakkaisnäkymään luettelon arvoista riippumatta."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Pakota kaikki toiminnot hyväksymään koon muuttaminen usean ikkunan tilassa luettelon arvoista riippumatta."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Ota käyttöön vapaamuotoiset ikkunat"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Ottaa käyttöön kokeellisten vapaamuotoisten ikkunoiden tuen."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Ota kokeellisten vapaamuotoisten ikkunoiden tuki käyttöön."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Varmuuskop. salasana"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Tietokoneen kaikkien tietojen varmuuskopiointia ei ole tällä hetkellä suojattu"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Vaihda tai poista tietokoneen kaikkien tietojen varmuuskopioinnin salasana koskettamalla."</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Ei käytössä"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Aina käytössä"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automaattinen"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-käyttöönotto"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Määritä WebView-käyttöönotto"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Valittu WebView-käyttöönotto on poistettu käytöstä. Haluatko ottaa sen käyttöön?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Värikorjaus"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Tämä ominaisuus on kokeellinen ja voi vaikuttaa suorituskykyyn."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Tämän ohittaa <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Noin <xliff:g id="TIME">%1$s</xliff:g> jäljellä"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – noin <xliff:g id="TIME">%2$s</xliff:g> jäljellä"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Täynnä"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Järjestelmänvalvojan käytöstä poistama"</string> <string name="home" msgid="8263346537524314127">"Aloitusnäyttö"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> sitten"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> jäljellä"</string> </resources> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index f888ec813000..1181c2a3f0c2 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Forcer l\'autor. d\'applis sur stockage externe"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Permet enreg. d\'applis sur espace stockage externe"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Forcer les activités à être redimensionnables"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Permet de redimensionner toutes les activités pour le mode multifenêtre, indépendamment des valeurs du fichier manifeste."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permet de redimensionner toutes les activités pour le mode multifenêtre, indépendamment des valeurs du fichier manifeste."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Activer les fenêtres de forme libre"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Active la compatibilité avec les fenêtres de forme libre expérimentales."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Activer la compatibilité avec les fenêtres de forme libre expérimentales."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Mot de passe sauvegarde PC"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Les sauvegardes complètes sur PC ne sont pas protégées actuellement."</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Touchez pour modifier ou supprimer le mot de passe utilisé pour les sauvegardes complètes sur ordinateur."</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Désactivé"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Toujours actif"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatique"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Mise en œuvre WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Définir la mise en œuvre WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"La mise en œuvre WebView sélectionnée est désactivée. Vous devez l\'activer pour l\'utiliser. Souhaitez-vous l\'activer?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correction des couleurs"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Cette fonctionnalité est expérimentale et peut toucher les performances."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Il reste environ <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> %% – Temps restant : environ <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> %% (chargée à 100 %% dans <xliff:g id="TIME">%2$s</xliff:g>)"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Pleine"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Désactivé par l\'administrateur"</string> <string name="home" msgid="8263346537524314127">"Accueil"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"Il y a <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Durée restante :<xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index dfc71f1f7e37..0639f1fa5f57 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Forcer disponibilité stockage externe pour applis"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Rend possible enregistrement de toute appli sur espace stockage externe, indépendamment valeurs fichier manifeste."</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Forcer possibilité de redimensionner les activités"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Permet de redimensionner toutes les activités pour le mode multifenêtre, indépendamment des valeurs du fichier manifeste."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permettre de redimensionner toutes les activités pour le mode multifenêtre, indépendamment des valeurs du fichier manifeste."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Activer les fenêtres de forme libre"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Active la compatibilité avec les fenêtres de forme libre expérimentales."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Activer la compatibilité avec les fenêtres de forme libre expérimentales."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Mot de passe sauvegarde PC"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Les sauvegardes complètes sur PC ne sont pas protégées actuellement."</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Appuyez pour modifier ou supprimer le mot de passe utilisé pour les sauvegardes complètes sur PC."</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Désactivé"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Toujours activé"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatique"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Mise en œuvre WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Définir la mise en œuvre WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"La mise en œuvre WebView sélectionnée est désactivée. Vous devez l\'activer pour l\'utiliser. Souhaitez-vous l\'activer ?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correction couleur"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Cette fonctionnalité est expérimentale et peut affecter les performances."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Il reste environ <xliff:g id="TIME">%1$s</xliff:g>."</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – Temps restant : <xliff:g id="TIME">%2$s</xliff:g> environ"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> (chargée à 100 %% dans <xliff:g id="TIME">%2$s</xliff:g>)"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"pleine"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Désactivé par l\'administrateur"</string> <string name="home" msgid="8263346537524314127">"Accueil"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"Il y a <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Il reste <xliff:g id="ID_1">%1$s</xliff:g>."</string> </resources> diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml index 20985bd43eb7..5622d634a5d4 100644 --- a/packages/SettingsLib/res/values-gl-rES/strings.xml +++ b/packages/SettingsLib/res/values-gl-rES/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permiso de aplicacións de forma externa"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Fai que calquera aplicación se poida escribir nun almacenamento externo, independentemente dos valores expresados"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Forzar o axuste do tamaño das actividades"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Permite axustar o tamaño de todas as actividades para o modo de varias ventás, independentemente dos valores definidos."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permite axustar o tamaño de todas as actividades para o modo de varias ventás, independentemente dos valores definidos."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Activar ventás de forma libre"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Activa a compatibilidade con ventás de forma libre experimentais."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Activa a compatibilidade con ventás de forma libre experimentais."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Contrasinal para copias"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"As copias de seguridade de ordenador completas non están protexidas"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Toca para cambiar ou eliminar o contrasinal para as copias de seguranza completas do escritorio"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Desactivado"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Sempre activada"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automático"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Definir implementación de WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"A implementación de WebView escollida está desactivada e, para poder usala, debe estar activada. Queres activala?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Corrección da cor"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función é experimental e pode afectar ao rendemento."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Duración aproximada de <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - faltan aproximadamente <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar a carga"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Completa"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Desactivado polo administrador"</string> <string name="home" msgid="8263346537524314127">"Inicio"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"Hai <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Tempo restante: <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-gu-rIN/strings.xml b/packages/SettingsLib/res/values-gu-rIN/strings.xml index 18917e0a4c85..2c1990fea83a 100644 --- a/packages/SettingsLib/res/values-gu-rIN/strings.xml +++ b/packages/SettingsLib/res/values-gu-rIN/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"બાહ્ય પર એપ્લિકેશનોને મંજૂરી આપવાની ફરજ પાડો"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"મેનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, કોઈપણ એપ્લિકેશનને બાહ્ય સ્ટોરેજ પર લખાવા માટે લાયક બનાવે છે"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"પ્રવૃત્તિઓને ફરીથી કદ યોગ્ય થવા માટે ફરજ પાડો"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"તમામ પ્રવૃત્તિઓને મલ્ટી-વિંડો માટે ફરીથી કદ બદલી શકે તેવી બનાવે છે, મેનીફેસ્ટ મુલ્યોને ધ્યાનમાં લીધા સિવાય."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"મૅનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, તમામ પ્રવૃત્તિઓને મલ્ટી-વિંડો માટે ફરીથી કદ બદલી શકે તેવી બનાવો."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"ફ્રિફોર્મ વિંડોઝ સક્ષમ કરો"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"પ્રાયોગિક ફ્રિફોર્મ વિંડોઝ માટે સમર્થનને સક્ષમ કરે છે."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"પ્રાયોગિક ફ્રિફોર્મ વિંડોઝ માટે સમર્થનને સક્ષમ કરો."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"ડેસ્કટૉપ બેકઅપ પાસવર્ડ"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"ડેસ્કટૉપ સંપૂર્ણ બેકઅપ હાલમાં સુરક્ષિત નથી"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"ડેસ્કટૉપ સંપૂર્ણ બેકઅપ્સ માટેનો પાસવર્ડ બદલવા અથવા દૂર કરવા માટે ટૅચ કરો"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"અક્ષમ કરેલ"</string> <string name="night_mode_yes" msgid="2218157265997633432">"હંમેશાં ચાલુ"</string> <string name="night_mode_auto" msgid="7508348175804304327">"સ્વચલિત"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView અમલીકરણ"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView અમલીકરણ સેટ કરો"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"પસંદ કરેલ WebView અમલીકરણ અક્ષમ કરેલ છે અને ઉપયોગ કરવા માટે સક્ષમ કરવું આવશ્યક છે, શું તમે તેને સક્ષમ કરવા માગો છો?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"રંગ સુધારણા"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"આ સુવિધા પ્રાયોગિક છે અને કામગીરી પર અસર કરી શકે છે."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> દ્વારા ઓવરરાઇડ થયું"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"અંદાજે. <xliff:g id="TIME">%1$s</xliff:g> બાકી"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - આશરે <xliff:g id="TIME">%2$s</xliff:g> બાકી"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"સંપૂર્ણ થવામાં <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"પૂર્ણ"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"વ્યવસ્થાપક દ્વારા અક્ષમ"</string> <string name="home" msgid="8263346537524314127">"હોમ"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> પહેલાં"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> બાકી"</string> </resources> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index 32b281409433..7deb05c530cb 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"ऐप्स को बाहरी मेमोरी पर बाध्य करें"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"इससे कोई भी ऐप मेनिफेस्ट मान अनदेखा करके, बाहरी मेमोरी पर लिखने योग्य बन जाता है"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"आकार बदले जाने के लिए गतिविधियों को बाध्य करें"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"एकाधिक-विंडो के लिए सभी गतिविधियों के आकार को बदले जाने योग्य बनाता है, चाहे मेनिफेस्ट मान कुछ भी हों."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"सभी गतिविधियों को एकाधिक विंडो के लिए आकार बदलने योग्य बनाएं, चाहे मेनिफेस्ट मान कुछ भी हों."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"फ़्रीफ़ॉर्म विंडो सक्षम करें"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"प्रयोगात्मक फ़्रीफ़ॉर्म विंडो का समर्थन सक्षम करती है."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"प्रयोगात्मक फ़्रीफ़ॉर्म विंडो का समर्थन सक्षम करें."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"डेस्कटॉप बैकअप पासवर्ड"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"डेस्कटॉप पूर्ण बैकअप वर्तमान में सुरक्षित नहीं हैं"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"डेस्कटॉप के पूर्ण बैकअप का पासवर्ड बदलने या निकालने के लिए टैप करें"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"अक्षम"</string> <string name="night_mode_yes" msgid="2218157265997633432">"हमेशा चालू"</string> <string name="night_mode_auto" msgid="7508348175804304327">"स्वचालित"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView कार्यान्वयन"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView कार्यान्वयन सेट करें"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"चुना गया WebView कार्यान्वयन अक्षम है और उसे उपयोग करने के लिए सक्षम किया जाना आवश्यक है, क्या आप उसे सक्षम करना चाहते हैं?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"रंग सुधार"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"यह सुविधा प्रायोगिक है और निष्पादन को प्रभावित कर सकती है."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> के द्वारा ओवरराइड किया गया"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"लगभग <xliff:g id="TIME">%2$s</xliff:g> शेष"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"लगभग <xliff:g id="TIME">%1$s</xliff:g> शेष"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - लगभग <xliff:g id="TIME">%2$s</xliff:g> शेष"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पूरी होने तक"</string> diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index 37b5363dd0f1..ca58584d4dac 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Prisilno dopusti aplikacije u vanjskoj pohrani"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Aplikacije se mogu zapisivati u vanjsku pohranu neovisno o manifestu"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Nametni mogućnost promjene veličine za aktivnosti"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Veličina svih aktivnosti može se mijenjati za više prozora, neovisno o vrijednostima manifesta."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Omogući mijenjanje veličine svih aktivnosti za više prozora, neovisno o vrijednostima manifesta."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Omogući prozore slobodnog oblika"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Omogućuje podršku za eksperimentalne prozore slobodnog oblika."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Omogući podršku za eksperimentalne prozore slobodnog oblika."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Zaporka sigurnosne kopije"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Potpune sigurnosne kopije na stolnom računalu trenutačno nisu zaštićene"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Dodirnite da biste promijenili ili uklonili zaporku za potpune sigurnosne kopije na računalu"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Onemogućeno"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Uvijek uključeno"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatska"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementacija WebViewa"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Postavi implementaciju WebViewa"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Odabrana implementacija WebViewa onemogućena je i morate je omogućiti da biste je mogli upotrebljavati. Želite li je omogućiti?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korekcija boje"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova je značajka eksperimentalna i može utjecati na performanse."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Premošćeno postavkom <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"Još približno <xliff:g id="TIME">%2$s</xliff:g>"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Još približno <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – još približno <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti"</string> diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index 9113ab336654..365c409b5232 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Külső tárhely alkalmazásainak engedélyezése"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Lehetővé teszi, hogy külső tárhelyre lehessen írni"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Tevékenységek átméretezésének kényszerítése"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Lehetővé teszi, hogy az összes tevékenység átméretezhető legyen a többablakos megjelenítés érdekében a jegyzékértékektől függetlenül."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Legyen az összes tevékenység átméretezhető a többablakos megjelenítés érdekében a jegyzékértékektől függetlenül."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Szabad formájú ablakok engedélyezése"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Engedélyezi a kísérleti jellegű, szabad formájú ablakok támogatását."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Kísérleti, szabad formájú ablakok támogatásának engedélyezése."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Asztali mentés jelszava"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Az asztali teljes biztonsági mentések jelenleg nem védettek."</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Koppintson ide az asztali teljes mentések jelszavának módosításához vagy eltávolításához"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Kikapcsolva"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Mindig bekapcsolva"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatikus"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-megvalósítás"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView-megvalósítás beállítása"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"A kiválasztott WebView-megvalósítás le van tiltva, a használathoz viszont engedélyezni kell. Szeretné engedélyezni?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Színkorrekció"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ez egy kísérleti funkció, és hatással lehet a teljesítményre."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Felülírva erre: <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"Kb. <xliff:g id="TIME">%2$s</xliff:g> van hátra"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Kb. <xliff:g id="TIME">%1$s</xliff:g> van hátra"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – kb. <xliff:g id="TIME">%2$s</xliff:g> van hátra"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a teljes töltöttség eléréséig"</string> diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml index 2baa160cf655..b210698c33e7 100644 --- a/packages/SettingsLib/res/values-hy-rAM/strings.xml +++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Միշտ թույլատրել ծրագրեր արտաքին պահեստում"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Թույլ է տալիս պահել հավելվածը արտաքին սարքում՝ մանիֆեստի արժեքներից անկախ"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Ստիպել, որ ակտիվությունների չափերը լինեն փոփոխելի"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Բոլոր ակտիվությունների չափերը բազմապատուհան ռեժիմի համար դարձնել փոփոխելի՝ մանիֆեստի արժեքներից անկախ:"</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Բոլոր ակտիվությունների չափերը բազմապատուհան ռեժիմի համար դարձնել փոփոխելի՝ մանիֆեստի արժեքներից անկախ:"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Ակտիվացնել կամայական ձևի պատուհանները"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Ակտիվացնում է կամայական ձևի փորձնական պատուհանների աջակցումը:"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Միացնել ազատ ձևի փորձնական պատուհանների աջակցումը:"</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Աշխատասեղանի պահուստավորման գաղտնաբառ"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Աշխատասեղանի ամբողջական պահուստավորումները այժմ պաշտպանված չեն"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Հպեք՝ աշխատասեղանի ամբողջական պահուստավորման գաղտնաբառը փոխելու կամ հեռացնելու համար"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Անջատված"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Միշտ միացված"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Ավտոմատ"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-ի իրականացում"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Ընտրեք WebView-ի իրականացումը"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"WebView-ի իրականացման ընտրված եղանակն անջատված է և օգտագործելու համար պետք է նախ միացվի: Միացնե՞լ:"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Գունային կարգաբերում"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Սա փորձնական գործառույթ է և կարող է ազդել աշխատանքի վրա:"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Գերազանցված է <xliff:g id="TITLE">%1$s</xliff:g>-ից"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Մնացել է մոտ <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - մնաց մոտավորապես <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Լիցքավորված"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Կասեցված է ադմինիստրատորի կողմից"</string> <string name="home" msgid="8263346537524314127">"Գլխավոր էջ"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> առաջ"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Մնացել է <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index 1a4757646269..33e869cf04a6 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Paksa izinkan aplikasi di eksternal"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Membuat semua aplikasi dapat ditulis ke penyimpanan eksterna"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Paksa aktivitas agar ukurannya dapat diubah"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Membuat semua aktivitas dapat diubah ukurannya untuk banyak jendela, terlepas dari nilai manifes."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Buat semua aktivitas dapat diubah ukurannya untuk banyak jendela, terlepas dari nilai manifes."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Aktifkan jendela berformat bebas"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Mengaktifkan dukungan untuk jendela eksperimental berformat bebas."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Aktifkan dukungan untuk jendela eksperimental berformat bebas."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Sandi cadangan desktop"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Saat ini cadangan desktop penuh tidak dilindungi"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Ketuk guna mengubah atau menghapus sandi untuk cadangan lengkap desktop"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Dinonaktifkan"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Selalu aktif"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Otomatis"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Penerapan WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Setel penerapan WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Implementasi WebView yang dipilih telah dinonaktifkan, dan harus diaktifkan agar dapat digunakan. Ingin mengaktifkannya?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Koreksi warna"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Fitur ini bersifat eksperimental dan dapat memengaruhi kinerja."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Digantikan oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Kira-kira tersisa <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - kira-kira tersisa. <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sampai penuh"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Penuh"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Dinonaktifkan oleh administrator"</string> <string name="home" msgid="8263346537524314127">"Layar Utama"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> lalu"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Tersisa <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml index 558f7bc74f3d..b79dcf8fa180 100644 --- a/packages/SettingsLib/res/values-is-rIS/strings.xml +++ b/packages/SettingsLib/res/values-is-rIS/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Þvinga fram leyfi forrita í ytri geymslu"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Gerir hvaða forriti sem er kleift að skrifa í ytri geymslu, burtséð frá gildum í upplýsingaskrá"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Þvinga breytanlega stærð virkni"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Gerir stærð allrar virkni breytanlega svo að hún henti fyrir marga glugga, óháð gildum í upplýsingaskrá."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Gera stærð allrar virkni breytanlega svo að hún henti fyrir marga glugga, óháð gildum í upplýsingaskrá."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Virkja glugga með frjálsu sniði"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Kveikir á stuðningi við glugga með frjálsu sniði á tilraunastigi."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Virkja stuðning við glugga með frjálsu sniði á tilraunastigi."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Aðgangsorð tölvuafritunar"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Heildarafritun á tölvu er ekki varin sem stendur."</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Ýttu til að breyta eða fjarlægja aðgangsorðið fyrir heildarafritun á tölvu"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Óvirkt"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Alltaf kveikt"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Sjálfvirkt"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Innleiðing WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Stilla innleiðingu WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Slökkt er á valinni innleiðingu WebView. Kveikja þarf á henni til að hægt sé að nota hana. Viltu gera það?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Litaleiðrétting"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Þessi eiginleiki er á tilraunastigi og getur haft áhrif á frammistöðu."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Hnekkt af <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Um það bil <xliff:g id="TIME">%1$s</xliff:g> eftir"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – u.þ.b. <xliff:g id="TIME">%2$s</xliff:g> eftir"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> í fulla hleðslu"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Fullhlaðin"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Stjórnandi gerði óvirkt"</string> <string name="home" msgid="8263346537524314127">"Heim"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"Fyrir <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> eftir"</string> </resources> diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index 24564c164f38..d5753c489bac 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Forza autorizzazione app su memoria esterna"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Rende l\'app idonea all\'installaz. su mem. esterna, senza considerare i valori manifest"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Imponi formato modificabile alle attività"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Rende il formato di tutte le attività modificabile per la modalità multi-finestra, indipendentemente dai valori manifest."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Rendi il formato di tutte le attività modificabile per la modalità multi-finestra, indipendentemente dai valori manifest."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Attiva finestre a forma libera"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Attiva il supporto per le finestre a forma libera sperimentali."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Attiva il supporto delle finestre a forma libera sperimentali."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Password di backup desktop"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"I backup desktop completi non sono attualmente protetti."</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tocca per modificare o rimuovere la password per i backup desktop completi"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Disattivato"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Sempre attivo"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatico"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementazione di WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Imposta l\'implementazione di WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"L\'implementazione di WebView selezionata non è attiva e deve essere attivata per poterla utilizzare. Vuoi attivarla?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correzione del colore"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Questa funzione è sperimentale e potrebbe influire sulle prestazioni."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Valore sostituito da <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Circa <xliff:g id="TIME">%1$s</xliff:g> rimanenti"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – Tempo rimanente: <xliff:g id="TIME">%2$s</xliff:g> circa"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Carica"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Disattivata dall\'amministratore"</string> <string name="home" msgid="8263346537524314127">"Home page"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> fa"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> rimanenti"</string> </resources> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index 5dea0a2a7955..ee2588fda6e3 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"אילוץ הרשאה של אפליקציות באחסון חיצוני"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"מאפשר כתיבה של כל אפליקציה באחסון חיצוני, ללא התחשבות בערכי המניפסט"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"אלץ יכולת קביעת גודל של הפעילויות"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"מאפשר יכולת קביעת גודל של כל הפעילויות לריבוי חלונות, ללא קשר לערך המניפסט."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"אפשר יכולת קביעת גודל של כל הפעילויות לריבוי חלונות, ללא קשר לערך המניפסט."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"הפעל את האפשרות לשנות את הגודל והמיקום של החלונות"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"מפעיל תמיכה בתכונה הניסיונית של שינוי הגודל והמיקום של החלונות."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"הפעל תמיכה בתכונה הניסיונית של שינוי הגודל והמיקום של החלונות."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"סיסמת גיבוי מקומי"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"גיבויים מלאים בשולחן העבודה אינם מוגנים כעת"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"הקש כדי לשנות או להסיר את הסיסמה לגיבויים מלאים בשולחן העבודה"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"מושבת"</string> <string name="night_mode_yes" msgid="2218157265997633432">"פועל תמיד"</string> <string name="night_mode_auto" msgid="7508348175804304327">"באופן אוטומטי"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"יישום WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"הגדרת יישום WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"יישום ה-WebView שנבחר מושבת, ויש להפעיל אותו כדי להשתמש בו. האם ברצונך להפעיל אותו?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"תיקון צבע"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"תכונה זו היא ניסיונית ועשויה להשפיע על הביצועים."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"נעקף על ידי <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"נשארו <xliff:g id="TIME">%1$s</xliff:g> בערך"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> בקירוב עד לסיום"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> עד למילוי"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"מלא"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"הושבת על ידי מנהל המערכת"</string> <string name="home" msgid="8263346537524314127">"דף הבית"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"לפני <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"נשארו <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index eb7f8af8f46a..67bf4b08e498 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"外部ストレージへのアプリの書き込みを許可"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"マニフェストの値に関係なく、すべてのアプリを外部ストレージに書き込めるようになります"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"アクティビティをサイズ変更可能にする"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"マニフェストの値に関係なく、マルチウィンドウですべてのアクティビティのサイズを変更できるようになります。"</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"マニフェストの値に関係なく、マルチウィンドウですべてのアクティビティのサイズを変更できるようにします。"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"フリーフォーム ウィンドウの有効化"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"テスト段階のフリーフォーム ウィンドウのサポートを有効にします。"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"外部のフリーフォーム ウィンドウのサポートを有効にします。"</string> <string name="local_backup_password_title" msgid="3860471654439418822">"PCバックアップパスワード"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"デスクトップのフルバックアップは現在保護されていません"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"デスクトップのフルバックアップ用のパスワードを変更または削除する場合にタップします"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"無効"</string> <string name="night_mode_yes" msgid="2218157265997633432">"常にON"</string> <string name="night_mode_auto" msgid="7508348175804304327">"自動"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView の実装"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView の実装の設定"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"選択した WebView の実装は無効になっていますが、使用するには有効にする必要があります。有効にしますか?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"色補正"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"この機能は試験運用機能であり、パフォーマンスに影響することがあります。"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g>によって上書き済み"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"あと約 <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 残り約<xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで<xliff:g id="TIME">%2$s</xliff:g>"</string> @@ -316,8 +319,6 @@ <skip /> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"管理者によって無効にされています"</string> <string name="home" msgid="8263346537524314127">"ホーム"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>前"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"あと <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-ka-rGE/strings.xml b/packages/SettingsLib/res/values-ka-rGE/strings.xml index 540dc816065f..f441fa09fea0 100644 --- a/packages/SettingsLib/res/values-ka-rGE/strings.xml +++ b/packages/SettingsLib/res/values-ka-rGE/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"აპების დაშვება გარე მეხსიერებაში"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"აპები ჩაიწერ. გარე მეხს.-ზე აღწ. ფაილის მნიშვნ. მიუხედ."</string> <string name="force_resizable_activities" msgid="8615764378147824985">"ზომაცვლადი აქტივობების იძულება"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"მანიფესტის მნიშვნელობების მიუხედავად, ყველა აქტივობას მრავალი ფანჯრის რეჟიმისთვის ზომაცვლადად აქცევს."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"მანიფესტის მნიშვნელობების მიუხედავად, მრავალი ფანჯრის რეჟიმისთვის ყველა აქტივობის ზომაცვლადად გადაქცევა."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"თავისუფალი ფორმის მქონე ფანჯრების ჩართვა"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"ჩართავს თავისუფალი ფორმის მქონე ფანჯრების მხარდაჭერის ექსპერიმენტულ ფუნქციას"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"თავისუფალი ფორმის მქონე ფანჯრების მხარდაჭერის ექსპერიმენტული ფუნქციის ჩართვა."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"დესკტოპის სარეზერვო ასლის პაროლი"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"დესკტოპის სრული სარეზერვო ასლები ამჟამად დაცული არ არის"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"შეეხეთ დესკტოპის სრული სარეზერვო ასლების პაროლის შესაცვლელად ან წასაშლელად"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"გამორთულია"</string> <string name="night_mode_yes" msgid="2218157265997633432">"ყოველთვის ჩართული"</string> <string name="night_mode_auto" msgid="7508348175804304327">"ავტომატური"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView რეალიზაცია"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView რეალიზაციის დაყენება"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"არჩეული WebView რეალიზაცია გათიშულია და გამოყენებამდე უნდა ჩაირთოს. გსურთ მისი ჩართვა?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"ფერის კორექცია"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ეს ფუნქცია საცდელია და შეიძლება გავლენა იქონიოს შესრულებაზე."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"უკუგებულია <xliff:g id="TITLE">%1$s</xliff:g>-ის მიერ"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"დარჩენილია დაახლოებით <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"დაახლ. <xliff:g id="LEVEL">%1$s</xliff:g> დარჩენილია <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> სრულ დატენვამდე"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"ბატარეა დატენილია"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"გათიშულია ადმინისტრატორის მიერ"</string> <string name="home" msgid="8263346537524314127">"მთავარი"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"გავიდა <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"დარჩენილია <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml index 7f59d976001f..fb5ab126ff8e 100644 --- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml +++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Сыртқыда қолданбаларға мәжбүрлеп рұқсат ету"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Манифест мәндеріне қарамастан кез келген қолданбаны сыртқы жадқа жазуға жарамды етеді"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Әрекеттерді өлшемін өзгертуге болатын етуге мәжбүрлеу"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Манифест мәндеріне қарамастан барлық әрекеттерді бірнеше терезе үшін өлшемін өзгертуге болатын етеді."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Манифест мәндеріне қарамастан барлық әрекеттерді бірнеше терезе үшін өлшемін өзгертуге болатын етеді."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Еркін пішіндегі терезелерді қосу"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Эксперименттік еркін пішіндегі терезелерді қолдауды қосады."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Эксперименттік еркін терезелерді қолдауды қосу."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Компьютер үстелінің сақтық көшірмесі"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Жұмыс үстелінің сақтық көшірмелері қазір қорғалмаған"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Үстелдік компьютердің толық сақтық көшірмелерінің кілтсөзін өзгерту немесе жою үшін түртіңіз"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Өшірілген"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Әрқашан қосулы"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Aвтоматты"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ендіру"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ендіруін орнату"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Таңдалған веб-көріністі енгізу өшірілген және пайдалану үшін оны қосу керек. Оны қосу керек пе?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Түсті түзету"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Бұл мүмкіндік эксперименттік болып табылады және өнімділікке әсер етуі мүмкін."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> үстінен басқан"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Шамамен <xliff:g id="TIME">%1$s</xliff:g> қалды"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - шамамен <xliff:g id="TIME">%2$s</xliff:g> қалды"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - толғанша <xliff:g id="TIME">%2$s</xliff:g>"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Толық"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Әкімші өшірген"</string> <string name="home" msgid="8263346537524314127">"Негізгі бет"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> бұрын"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> қалды"</string> </resources> diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml index a949538de534..c1946c4fd6ca 100644 --- a/packages/SettingsLib/res/values-km-rKH/strings.xml +++ b/packages/SettingsLib/res/values-km-rKH/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"បង្ខំឲ្យអនុញ្ញាតកម្មវិធីលើឧបករណ៍ផ្ទុកខាងក្រៅ"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ធ្វើឲ្យកម្មវិធីទាំងឡាយមានសិទ្ធិសរសេរទៅកាន់ឧបករណ៍ផ្ទុកខាងក្រៅ ដោយមិនគិតពីតម្លៃជាក់លាក់"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"បង្ខំឲ្យសកម្មភាពអាចប្តូរទំហំបាន"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"កំណត់ឲ្យសកម្មភាពទាំងអស់អាចប្តូរទំហំបានសម្រាប់ពហុផ្ទាំងវិនដូ ដោយមិនគិតពីតម្លៃមេនីហ្វេសឡើយ។"</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"កំណត់ឲ្យសកម្មភាពទាំងអស់អាចប្តូរទំហំបានសម្រាប់ពហុផ្ទាំងវិនដូ ដោយមិនគិតពីតម្លៃមេនីហ្វេស។"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"បើកដំណើរការផ្ទាំងវិនដូទម្រង់សេរី"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"បើកដំណើរការគាំទ្រផ្ទាំងវិនដូទម្រង់សេរីសាកល្បង"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"បើកដំណើរការគាំទ្រផ្ទាំងវិនដូទម្រង់សេរីសាកល្បង"</string> <string name="local_backup_password_title" msgid="3860471654439418822">"ពាក្យសម្ងាត់បម្រុងទុកលើផ្ទៃតុ"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"ការបម្រុងទុកពេញលេញលើផ្ទៃតុបច្ចុប្បន្នមិនត្រូវបានការពារទេ។"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"ប៉ះដើម្បីប្ដូរ ឬយកពាក្យសម្ងាត់ចេញសម្រាប់ការបម្រុងទុកពេញលេញលើកុំព្យូទ័រ"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"បានបិទ"</string> <string name="night_mode_yes" msgid="2218157265997633432">"បើកជានិច្ច"</string> <string name="night_mode_auto" msgid="7508348175804304327">"ស្វ័យប្រវត្តិ"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"ការប្រតិបត្តិ WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"កំណត់ការប្រតិបត្តិ WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ការប្រតិបត្តិការ WebView ដែលបានជ្រើសត្រូវបានបិទដំណើរការ ប៉ុន្តែអ្នកត្រូវបើកដំណើរការវាដើម្បីប្រើ តើអ្នកចង់បើកដំណើរការវាដែរឬទេ?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"ការកែពណ៌"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"លក្ខណៈនេះគឺជាការពិសោធន៍ ហើយអាចប៉ះពាល់ការអនុវត្ត។"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"បដិសេធដោយ <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"នៅសល់ប្រហែល <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - នៅសល់ប្រហែល <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> រហូតដល់ពេញ"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"ពេញ"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"បានបិទដំណើរការដោយអ្នកគ្រប់គ្រង"</string> <string name="home" msgid="8263346537524314127">"ដើម"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> មុន"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"នៅសល់ <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml index bfe0c1e8a1c8..a6acd1772684 100644 --- a/packages/SettingsLib/res/values-kn-rIN/strings.xml +++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"ಬಾಹ್ಯವಾಗಿ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಒತ್ತಾಯವಾಗಿ ಅನುಮತಿಸಿ"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳನ್ನು ಪರಿಗಣಿಸದೇ, ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್ಗೆ ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆಗೆ ಬರೆಯಲು ಅರ್ಹಗೊಳಿಸುತ್ತದೆ"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"ಚಟುವಟಿಕೆಗಳನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸುವಂತೆ ಒತ್ತಾಯ ಮಾಡಿ"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳನ್ನು ಪರಿಗಣಿಸದೇ, ಬಹು-ವಿಂಡೊಗೆ ಎಲ್ಲಾ ಚಟುವಟಿಕೆಗಳನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸುವಂತೆ ಮಾಡುತ್ತದೆ."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳನ್ನು ಪರಿಗಣಿಸದೇ, ಬಹು-ವಿಂಡೊಗೆ ಎಲ್ಲಾ ಚಟುವಟಿಕೆಗಳನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸುವಂತೆ ಮಾಡಿ."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"ಮುಕ್ತಸ್ವರೂಪದ ವಿಂಡೊಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"ಪ್ರಾಯೋಗಿಕ ಮುಕ್ತಸ್ವರೂಪದ ವಿಂಡೊಗಳಿಗೆ ಬೆಂಬಲವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"ಪ್ರಾಯೋಗಿಕ ಫ್ರೀಫಾರ್ಮ್ ವಿಂಡೊಗಳಿಗೆ ಬೆಂಬಲವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"ಡೆಸ್ಕ್ಟಾಪ್ ಬ್ಯಾಕಪ್ ಪಾಸ್ವರ್ಡ್"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"ಡೆಸ್ಕ್ಟಾಪ್ನ ಪೂರ್ಣ ಬ್ಯಾಕಪ್ಗಳನ್ನು ಪ್ರಸ್ತುತ ರಕ್ಷಿಸಲಾಗಿಲ್ಲ"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"ಡೆಸ್ಕ್ಟಾಪ್ನ ಪೂರ್ಣ ಬ್ಯಾಕಪ್ಗಳಿಗೆ ಪಾಸ್ವರ್ಡ್ ಬದಲಾಯಿಸಲು ಅಥವಾ ತೆಗೆದುಹಾಕಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string> <string name="night_mode_yes" msgid="2218157265997633432">"ಯಾವಾಗಲೂ ಆನ್"</string> <string name="night_mode_auto" msgid="7508348175804304327">"ಸ್ವಯಂಚಾಲಿತ"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ಅನುಷ್ಠಾನಗೊಳಿಸುವಿಕೆ"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ಅನುಷ್ಠಾನಗೊಳಿಸುವಿಕೆಯನ್ನು ಹೊಂದಿಸಿ"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ಆಯ್ಕೆಮಾಡಲಾದ WebView ಅನುಷ್ಠಾನಗೊಳಿಸುವಿಕೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ ಮತ್ತು ಬಳಸಲು ಸಕ್ರಿಯಗೊಳಿಸಬೇಕಾಗಿದೆ, ಇದನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ನೀವು ಬಯಸುತ್ತೀರಾ?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"ಬಣ್ಣದ ತಿದ್ದುಪಡಿ"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ಇದು ಪ್ರಾಯೋಗಿಕ ವೈಶಿಷ್ಟ್ಯವಾಗಿದೆ. ಕಾರ್ಯಕ್ಷಮತೆ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರಬಹುದು."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ಮೂಲಕ ಅತಿಕ್ರಮಿಸುತ್ತದೆ"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"ಸುಮಾರು <xliff:g id="TIME">%2$s</xliff:g> ಉಳಿದಿದೆ"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"ಸುಮಾರು <xliff:g id="TIME">%1$s</xliff:g> ಉಳಿದಿದೆ"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"ಸುಮಾರು <xliff:g id="LEVEL">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g> ಉಳಿದಿದೆ"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ಪೂರ್ಣವಾಗುವವರೆಗೆ"</string> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index 5d1176aaa83c..c8bb2e6c5d1f 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"외부에서 앱 강제 허용"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"매니페스트 값에 관계없이 앱을 외부 저장소에 작성"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"활동의 크기가 조정 가능하도록 설정"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"모든 활동을 매니페스트 값에 관계없이 멀티 윈도우용으로 크기 조정 가능하도록 설정"</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"모든 활동을 매니페스트 값에 관계없이 멀티 윈도우용으로 크기 조정 가능하도록 설정"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"자유 형식 창 사용"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"자유 형식 창(베타) 지원 사용"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"자유 형식 창 지원 사용"</string> <string name="local_backup_password_title" msgid="3860471654439418822">"데스크톱 백업 비밀번호"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"데스크톱 전체 백업에 비밀번호가 설정되어 있지 않음"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"데스크톱 전체 백업에 대한 비밀번호를 변경하거나 삭제하려면 탭하세요."</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"사용 안함"</string> <string name="night_mode_yes" msgid="2218157265997633432">"항상 사용"</string> <string name="night_mode_auto" msgid="7508348175804304327">"자동"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView 구현"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView 구현 설정"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"선택한 WebView 구현이 사용 중지되어 있습니다. 사용하려면 사용 설정해야 합니다. 사용 설정하시겠습니까?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"색보정"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"실험실 기능이며 성능에 영향을 줄 수 있습니다."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> 우선 적용됨"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"약 <xliff:g id="TIME">%1$s</xliff:g> 남음"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 대략 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"충전 완료"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"관리자가 사용 중지함"</string> <string name="home" msgid="8263346537524314127">"홈"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> 전"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> 남음"</string> </resources> diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml index f0867f54eb0f..6f158c00be33 100644 --- a/packages/SettingsLib/res/values-ky-rKG/strings.xml +++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Тышкы сактагычка сактоого уруксат берүү"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Манифест маанилерине карабастан бардык колдонмолорду тышкы сактагычка сактоого уруксат берет"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Аракеттердин өлчөмүн өзгөртүүнү мажбурлоо"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Манифест маанилерине карабастан бардык аракеттерди мульти-терезеге өлчөмү өзгөртүлгүдөй кылат."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Манифест маанилерине карабастан бардык аракеттерди мульти-терезеге өлчөмү өзгөртүлгүдөй кылуу."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Эркин формадагы терезелерди түзүүнү иштетүү"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Эркин формадагы терезелерди түзүү боюнча сынамык функцияны иштетүү"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Эркин формадагы терезелерди түзүү боюнча сынамык функцияны иштетүү."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Компүтердеги бэкаптын сырсөзү"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Компүтердеги толук бэкап учурда корголгон эмес"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Иш тактасынын камдалган сырсөзүн өзгөртүү же алып салуу үчүн таптап коюңуз"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Өчүрүлгөн"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Ар дайым күйгүзүлгөн"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Автоматтык"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView аткарылышы"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView аткарылышын коюу"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"WebView кызматын пайдалануу үчүн аны иштетүү керек. Иштетесизби?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Түсүн тууралоо"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Бул сынамык мүмкүнчүлүк болгондуктан, иштин майнаптуулугуна таасир этиши мүмкүн."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> менен алмаштырылган"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"<xliff:g id="TIME">%1$s</xliff:g>-чакты калды"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - болжол менен <xliff:g id="TIME">%2$s</xliff:g> саат калды"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> толгончо"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Толук"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Администратор өчүрүп койгон"</string> <string name="home" msgid="8263346537524314127">"Башкы бет"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> мурун"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> калды"</string> </resources> diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml index 14194662e4be..766421233ede 100644 --- a/packages/SettingsLib/res/values-lo-rLA/strings.xml +++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"ບັງຄັບອະນຸຍາດແອັບຢູ່ພາຍນອກ"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ເຮັດໃຫ້ທຸກແອັບມີສິດໄດ້ຮັບການຂຽນໃສ່ບ່ອນຈັດເກັບພາຍນອກ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າທີ່ຈະແຈ້ງ"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"ບັງຄັງໃຫ້ກິດຈະກຳປ່ຽນຂະໜາດໄດ້"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"ເຮັດໃຫ້ທຸກກິດຈະກຳປ່ຽນຂະໜາດໄດ້ສຳລັບຫຼາຍໜ້າຕ່າງ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າທີ່ຈະແຈ້ງ."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ເຮັດໃຫ້ທຸກກິດຈະກຳສາມາດປັບຂະໜາດໄດ້ສຳລັບຫຼາຍໜ້າຈໍ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າທີ່ຈະແຈ້ງ."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"ເປີດໃຊ້ໜ້າຕ່າງຮູບແບບອິດສະຫຼະ"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"ເປີດໃຊ້ການຮອງຮັບໜ້າຕ່າງຮູບແບບອິດສະຫຼະທີ່ທົດລອງໃຊ້."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"ເປີດໃຊ້ການຮອງຮັບໜ້າຈໍຮູບແບບອິດສະຫຼະແບບທົດລອງ."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"ລະຫັດຜ່ານການສຳຮອງຂໍ້ມູນເດັກສະທັອບ"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"ການສຳຮອງຂໍ້ມູນເຕັມຮູບແບບໃນເດັກສະທັອບຍັງບໍ່ໄດ້ຮັບການປ້ອງກັນໃນເວລານີ້"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"ແຕະເພື່ອປ່ຽນ ຫຼືລຶບລະຫັດຂອງການສຳຮອງຂໍ້ມູນເຕັມຮູບແບບໃນເດັກສະທັອບ"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"ປິດໃຊ້ງານແລ້ວ"</string> <string name="night_mode_yes" msgid="2218157265997633432">"ເປີດຕະຫຼອດ"</string> <string name="night_mode_auto" msgid="7508348175804304327">"ອັດຕະໂນມັດ"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"ການຈັດຕັ້ງປະຕິບັດ WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"ຕັ້ງການຈັດຕັ້ງປະຕິບັດ WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ການຈັດຕັ້ງປະຕິບັດ WebView ທີ່ເລືອກຖືກປິດນຳໃຊ້, ແລະຕ້ອງຖືກເປີດນຳໃຊ້, ທ່ານຕ້ອງການເປີດນຳໃຊ້ມັນບໍ?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"ການປັບແຕ່ງສີ"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ຄຸນສົມບັດນີ້ກຳລັງຢູ່ໃນການທົດລອງແລະອາດມີຜົນຕໍ່ປະສິດທິພາບ."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"ຖືກແທນໂດຍ <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"ຍັງເຫຼືອປະມານ <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ເຫຼືອປະມານ <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງຈະເຕັມ"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"ເຕັມ"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"ຖືກປິດໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບ"</string> <string name="home" msgid="8263346537524314127">"ໜ້າຫຼັກ"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ກ່ອນນີ້"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"ຍັງເຫຼືອ <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index 3f5493d9f4af..c730dc07ae37 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Priverstinai leisti programas išorinėje atmintin."</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Vis. pr. gal. įr. į vid. saug. nepais. apr. vert."</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Priv. nust., kad veiksm. b. g. atl. kelių d. lang."</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Nustatoma, kad visus veiksmus būtų galima atlikti kelių dydžių languose, nepaisant aprašo verčių."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Nustatyti, kad visus veiksmus būtų galima atlikti kelių dydžių languose, nepaisant aprašo verčių."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Įgalinti laisvos formos langus"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Įgalinamas eksperimentinių laisvos formos langų palaikymas."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Įgalinti eksperimentinių laisvos formos langų palaikymą."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Viet. atsrg. kop. slapt."</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Šiuo metu visos vietinės atsarginės kopijos neapsaugotos"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Jei norite pakeisti ar pašalinti visų stalinio kompiuterio atsarginių kopijų slaptažodį, palieskite"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Išjungta"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Visada įjungta"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatinė"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"„WebView“ diegimas"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"„WebView“ diegimo nustatymas"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Pasirinktas „WebView“ diegimas išjungtas ir jį būtina įgalinti, kad būtų galima naudoti. Ar norite jį įgalinti?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Spalvų taisymas"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ši funkcija yra eksperimentinė ir ji gali turėti įtakos našumui."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Nepaisyta naudojant nuostatą „<xliff:g id="TITLE">%1$s</xliff:g>“"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Liko maždaug <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko maždaug <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Visiškai įkrautas"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Išjungė administratorius"</string> <string name="home" msgid="8263346537524314127">"Pagrindinis ekranas"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"Prieš <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Liko <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index dd7070306608..65e4cff6aca1 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Lietotņu piespiedu atļaušana ārējā krātuvē"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Ļauj jebkuru lietotni ierakstīt ārējā krātuvē neatkarīgi no manifesta vērtības."</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Pielāgot darbības"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Pielāgo visas darbības vairāku logu režīmam neatkarīgi no vērtībām manifestā."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Pielāgot visas darbības vairāku logu režīmam neatkarīgi no vērtībām manifestā."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Iespējot brīvās formas logus"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Iespējo eksperimentālo brīvās formas logu atbalstu."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Iespējot eksperimentālo brīvās formas logu atbalstu."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Datora dublējuma parole"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Darbvirsmas pilnie dublējumi pašlaik nav aizsargāti."</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Pieskarieties, lai mainītu vai noņemtu paroli pilniem datora dublējumiem."</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Atspējots"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Vienmēr ieslēgts"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automātiski"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ieviešana"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Iestatīt WebView ieviešanu"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Izvēlētā WebView ieviešana ir atspējota, un tā ir jāiespējo, lai to varētu izmantot. Vai vēlaties to iespējot?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Krāsu korekcija"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Šī funkcija ir eksperimentāla un var ietekmēt veiktspēju."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Jaunā preference: <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Atlikušais laiks: aptuveni <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> — aptuvenais atlikušais laiks: <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai uzlādei"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Pilns"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Atspējojis administrators"</string> <string name="home" msgid="8263346537524314127">"Sākums"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"Pirms šāda laika: <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Atlikušais laiks: <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-mk-rMK/strings.xml b/packages/SettingsLib/res/values-mk-rMK/strings.xml index 5bdfd01aa53d..4576f3a3afc4 100644 --- a/packages/SettingsLib/res/values-mk-rMK/strings.xml +++ b/packages/SettingsLib/res/values-mk-rMK/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Принуд. дозволете апликации на надворешна меморија"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Запишува апл. во надв.меморија, незав. од манифест"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Принуди ги активностите да ја менуваат големината"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Ги прави сите активности да бидат со променлива големина за мултипрозорец, без разлика на вредностите на манифестот."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Направете сите активности да бидат со променлива големина за повеќе прозорци, без разлика на вредностите на манифестот."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Овозможи прозорци со слободна форма"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Овозможува поддршка за експериментални прозорци со слободна форма."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Овозможи поддршка за експериментални прозорци со слободна форма."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Резервна лозинка за работна површина"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Целосни резервни копии на работната површина кои во моментов не се заштитени"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Допрете за да се промени или отстрани лозинката за целосни резервни копии на работната површина"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Оневозможено"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Секогаш вклучено"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Автоматски"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Воведување WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Поставете воведување WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Избраната примена на WebView е оневозможена, а за да се користи, мора да се овозможи. Дали сакате да ја овозможите?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Корекција на боја"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Функцијата е експериментална и може да влијае на изведбата."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Прескокнато според <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"Преостанаа прибл. <xliff:g id="TIME">%2$s</xliff:g>"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Преостанаа прибл. <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – преостанува приближно <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до целосно полна"</string> diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml index 38b4771d3957..180d615cfe3f 100644 --- a/packages/SettingsLib/res/values-ml-rIN/strings.xml +++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"ബാഹ്യമായതിൽ നിർബന്ധിച്ച് അനുവദിക്കുക"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"മാനിഫെസ്റ്റ് മൂല്യങ്ങൾ പരിഗണിക്കാതെ, ബാഹ്യ സ്റ്റോറേജിലേക്ക് എഴുതപ്പെടുന്നതിന് ഏതൊരു ആപ്പിനെയും യോഗ്യമാക്കുന്നു"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"വലിപ്പം മാറ്റാൻ പ്രവർത്തനങ്ങളെ നിർബന്ധിക്കുക"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"മാനിഫെസ്റ്റ് മൂല്യങ്ങൾ പരിഗണിക്കാതെ, എല്ലാ പ്രവർത്തനങ്ങളെയും മൾട്ടി-വിൻഡോയ്ക്കായി വലിപ്പം മാറ്റുന്നു."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"മാനിഫെസ്റ്റ് മൂല്യങ്ങൾ പരിഗണിക്കാതെ, എല്ലാ ആക്ടിവിറ്റികളെയും മൾട്ടി-വിൻഡോയ്ക്കായി വലിപ്പം മാറ്റുക."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"ഫ്രീഫോം വിൻഡോകൾ പ്രവർത്തനക്ഷമമാക്കുക"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"പരീക്ഷണാത്മക ഫ്രീഫോം വിൻഡോകൾക്കുള്ള പിന്തുണ പ്രവർത്തനക്ഷമമാക്കുന്നു."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"പരീക്ഷണാത്മക ഫ്രീഫോം വിൻഡോകൾക്കുള്ള പിന്തുണ പ്രവർത്തനക്ഷമമാക്കുക."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"ഡെസ്ക്ടോപ്പ് ബാക്കപ്പ് പാസ്വേഡ്"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"ഡെസ്ക്ടോപ്പ് പൂർണ്ണ ബാക്കപ്പുകൾ നിലവിൽ പരിരക്ഷിച്ചിട്ടില്ല"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"ഡെസ്ക്ടോപ്പ് പൂർണ്ണ ബാക്കപ്പുകൾക്കായി പാസ്വേഡുകൾ മാറ്റാനോ നീക്കംചെയ്യാനോ ടാപ്പുചെയ്യുക"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"പ്രവർത്തനരഹിതമാക്കി"</string> <string name="night_mode_yes" msgid="2218157265997633432">"എല്ലായ്പ്പോഴും ഓണാണ്"</string> <string name="night_mode_auto" msgid="7508348175804304327">"ഓട്ടോമാറ്റിക്"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView നടപ്പാക്കൽ"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView നടപ്പാക്കൽ സജ്ജമാക്കുക"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"തിരഞ്ഞെടുത്ത WebView നടപ്പാക്കൽ പ്രവർത്തനരഹിതമാക്കി, ഉപയോഗിക്കുന്നതിന് ഇത് പ്രവർത്തനക്ഷമമാക്കണം, പ്രവർത്തനക്ഷമമാക്കാൻ ആഗ്രഹിക്കുന്നുണ്ടോ?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"വർണ്ണം ക്രമീകരിക്കൽ"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ഈ ഫീച്ചർ പരീക്ഷണാത്മകമായതിനാൽ പ്രകടനത്തെ ബാധിച്ചേക്കാം."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ഉപയോഗിച്ച് അസാധുവാക്കി"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"ഏകദേശം <xliff:g id="TIME">%2$s</xliff:g> ശേഷിക്കുന്നു"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"ഏകദേശം <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ഏകദേശം <xliff:g id="TIME">%2$s</xliff:g> ശേഷിക്കുന്നു"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml index 3b5d5f196941..8bdd8801af0d 100644 --- a/packages/SettingsLib/res/values-mn-rMN/strings.xml +++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Апп-ыг гадаад санах ойд хадгалахыг зөвшөөрөх"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Манифест утгыг нь үл хамааран дурын апп-ыг гадаад санах ойд бичих боломжтой болгодог"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Үйл ажиллагааны хэмжээг өөрчилж болохуйц болгох"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Тодорхойлогч файлын утгыг үл хамааран, бүх үйл ажиллагааг олон цонхонд хэмжээг нь өөрчилж болохуйц болгох."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Тодорхойлогч файлын утгыг үл хамааран, бүх үйл ажиллагааны хэмжээг олон цонхонд өөрчилж болохуйц болгоно уу."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Чөлөөт хэлбэрийн цонхыг идэвхжүүлэх"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Туршилтын чөлөөт хэлбэрийн цонхны дэмжлэгийг идэвхжүүлдэг."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Туршилтын чөлөөт хэлбэрийн цонхны дэмжлэгийг идэвхжүүлнэ үү."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Десктоп нөөшлөлтийн нууц үг"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Десктоп бүрэн нөөцлөлт одоогоор хамгаалалтгүй байна"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Компьютерийн бүтэн нөөцлөлтийн нууц үгийг өөрчлөх, устгах бол дарна уу"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Идэвхгүй"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Байнга асаалттай"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Автоматаар"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView хэрэгжилт"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView хэрэгжилтийг тохируулах"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Сонгосон WebView хэрэгжүүлэлтийг идэвхгүй болгосон бөгөөд хэрэглэхийн тулд заавал идэвхжүүлэх шаардлагатай. Үүнийг идэвхжүүлэх үү?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Өнгө тохируулах"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Энэ функц туршилтынх бөгөөд ажиллагаанд нөлөөлж болзошгүй."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Давхарласан <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ойролцоогоор <xliff:g id="TIME">%1$s</xliff:g> үлдсэн"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ойролцоогоор <xliff:g id="TIME">%2$s</xliff:g> үлдсэн"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"дүүртэл <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Дүүрэн"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Админ идэвхгүй болгосон"</string> <string name="home" msgid="8263346537524314127">"Нүүр"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> өмнө"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> үлдсэн"</string> </resources> diff --git a/packages/SettingsLib/res/values-mr-rIN/strings.xml b/packages/SettingsLib/res/values-mr-rIN/strings.xml index 493f579a5ca2..92247f5fe1fb 100644 --- a/packages/SettingsLib/res/values-mr-rIN/strings.xml +++ b/packages/SettingsLib/res/values-mr-rIN/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"बाह्यवर अॅप्सना अनुमती देण्याची सक्ती करा"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"मॅनिफेस्ट मूल्यांकडे दुर्लक्ष करून, कोणत्याही अॅपला बाह्य संचयनावर लेखन केले जाण्यासाठी पात्र बनविते"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"क्रियाकलापाचा आकार बदलण्यायोग्य होण्याची सक्ती करा"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"मॅनिफेस्ट मूल्यांकडे दुर्लक्ष करून, एकाधिक-विंडोसाठी सर्व क्रियाकलापांचा आकार बदलण्यायोग्य करा"</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"मॅनिफेस्ट मूल्यांकडे दुर्लक्ष करून, एकाधिक-विंडोसाठी सर्व क्रियाकलापांचा आकार बदलण्यायोग्य करा."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"freeform विंडो सक्षम करा"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"प्रायोगिक मुक्तस्वरूपाच्या विंडोसाठी समर्थन सक्षम करते."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"प्रायोगिक मुक्तस्वरूपाच्या विंडोसाठी समर्थन सक्षम करा."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"डेस्कटॉप बॅकअप संकेतशब्द"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"डेस्कटॉप पूर्ण बॅक अप सध्या संरक्षित नाहीत"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"डेस्कटॉपच्या पूर्ण बॅकअपसाठी असलेला संकेतशब्द बदलण्यासाठी किंवा काढण्यासाठी टॅप करा"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"अक्षम केले"</string> <string name="night_mode_yes" msgid="2218157265997633432">"नेहमी चालू"</string> <string name="night_mode_auto" msgid="7508348175804304327">"स्वयंचलित"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"वेबदृश्य अंमलबजावणी"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"वेबदृश्य अंमलबजावणी सेट करा"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"निवडलेली WebView अंमलबजावणी अक्षम आहे आणि वापरण्यास सक्षम असणे आवश्यक आहे, आपण ती सक्षम करू इच्छिता?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"रंग सुधारणा"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"हे वैशिष्ट्य प्रायोगिक आहे आणि कदाचित कार्यप्रदर्शन प्रभावित करू शकते."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारे अधिलिखित"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"अंदाजे. <xliff:g id="TIME">%2$s</xliff:g> शिल्लक"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"अंदाजे. <xliff:g id="TIME">%1$s</xliff:g> शिल्लक"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - अंदाजे. <xliff:g id="TIME">%2$s</xliff:g> शिल्लक"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पूर्ण होण्यात"</string> diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml index 050915991b67..45f5c6f20682 100644 --- a/packages/SettingsLib/res/values-ms-rMY/strings.xml +++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Benarkan apl secara paksa pada storan luaran"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Menjadikan sebarang apl layak ditulis ke storan luaran, walau apa juga nilai manifesnya"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Paksa aktiviti supaya boleh diubah saiz"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Menjadikan semua aktiviti boleh diubah saiz untuk berbilang tetingkap, tanpa mengambil kira nilai manifes."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Bolehkan semua saiz aktiviti diubah untuk berbilang tetingkap, tanpa mengambil kira nilai manifes."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Dayakan tetingkap bentuk bebas"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Mendayakan sokongan untuk tetingkap bentuk bebas percubaan."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Dayakan sokongan untuk tetingkap bentuk bebas percubaan."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Kata laluan sandaran komputer meja"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Sandaran penuh komputer meja tidak dilindungi pada masa ini"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Ketik untuk menukar atau mengalih keluar kata laluan untuk sandaran penuh desktop"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Dilumpuhkan"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Sentiasa hidup"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatik"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Pelaksanaan WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Tetapkan pelaksanaan WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Pelaksanaan WebView pilihan telah dilumpuhkan dan mesti didayakan untuk digunakan, adakah anda mahu mendayakannya?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Pembetulan warna"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ciri ini adalah percubaan dan boleh menjejaskan prestasi."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Diatasi oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Kira-kira <xliff:g id="TIME">%1$s</xliff:g> lagi"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - kira-kira. <xliff:g id="TIME">%2$s</xliff:g> yang tinggal"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga penuh"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Penuh"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Dilumpuhkan oleh pentadbir"</string> <string name="home" msgid="8263346537524314127">"Skrin Utama"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> yang lalu"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> lagi"</string> </resources> diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml index 9f56479b5040..9d722dbcae23 100644 --- a/packages/SettingsLib/res/values-my-rMM/strings.xml +++ b/packages/SettingsLib/res/values-my-rMM/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"အပြင်မှာ အတင်း ခွင့်ပြုရန်"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ပြနေတဲ့ တန်ဖိုး ဘယ်လိုပဲရှိနေနေ၊ ဘယ် appကို မဆို အပြင် သိုလှောင်ခန်းသို့ ရေးသားခွင့် ပေးတယ်"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"လုပ်ဆောင်ချက်များ ဆိုက်ညှိရနိုင်ရန် လုပ်ခိုင်းပါ"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"မန်နီးဖက်စ် တန်ဖိုးမရွေး၊ လုပ်ဆောင်ချက် အားလုံး ဆိုက်ညှိရနိုင်အောင် လုပ်ပေးပါ။"</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"မန်နီးဖက်စ်တန်ဖိုးများ မည်မျှပင်ရှိစေကာမူ၊ ဝင်းဒိုးများအတွက် လှုပ်ရှားမှုများအားလုံးကို အရွယ်အစားချိန်ခြင်း ပြုလုပ်ပါ။"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"အခမဲ့ပုံစံ ဝင်းဒိုးကို ဖွင့်ပါ"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"စမ်းသပ်မှု အခမဲ့ပုံစံ ဝင်းဒိုးများအတွက် ပံ့ပိုးမှုကို ဖွင့်ပါ။"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"ပုံစံမျိုးစုံဝင်းဒိုးများစမ်းသပ်မှုအတွက် အထောက်အပံ့ကိုဖွင့်ပါ"</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Desktop အရန်စကားဝှက်"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"အလုပ်ခုံတွင် အရန်သိမ်းဆည်းခြင်းများကို လောလောဆယ် မကာကွယ်နိုင်ပါ။"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"စားပွဲတင်ကွန်ပျူတာကို အပြည့်အဝအရံကူးထားရန်အတွက် စကားဝှက်ကို ပြောင်းရန် သို့မဟုတ် ဖယ်ရှားရန် တို့ပါ။"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"ပိတ်ထား"</string> <string name="night_mode_yes" msgid="2218157265997633432">"အမြဲတမ်း ဖွင့်ထားရန်"</string> <string name="night_mode_auto" msgid="7508348175804304327">"အလိုအလျောက်"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView အကောင်အထည်ဖော်မှု"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView အကောင်အထည်ဖော်မှု သတ်မှတ်ပါ"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ရွေးချယ်ထားသည့် WebView လုပ်ဆောင်ခြင်းကို ပိတ်ထားသည်ပြီး အသုံးပြုရန်အတွက် ဖွင့်ရမည်၊ ဖွင့်လိုပါသလား။"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"အရောင်ပြင်ဆင်မှု"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ဒီအင်္ဂါရပ်မှာ စမ်းသပ်မှု ဖြစ်၍ လုပ်ကိုင်မှုကို အကျိုးသက်ရောက်နိုင်သည်။"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> မှ ကျော်၍ လုပ်ထားသည်။"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"ခန့်မှန်းခြေ <xliff:g id="TIME">%1$s</xliff:g> ကျန်ပါသည်"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ခန့်မှန်းခြေ။ <xliff:g id="TIME">%2$s</xliff:g> ကျန်ရှိနေ"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> အပြည့်အထိ"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"အပြည့်"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"စီမံခန့်ခွဲသူမှ ပိတ်ထားသည်"</string> <string name="home" msgid="8263346537524314127">"ပင်မ"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"ပြီးခဲ့သည့် <xliff:g id="ID_1">%1$s</xliff:g> က"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> ကျန်ပါသည်"</string> </resources> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index 013fe26ab257..ff15482b7ee2 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Tving frem tillatelse for ekstern lagring av apper"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Gjør at apper kan skrives til ekstern lagring, uavhengig av manifestverdier"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Tving aktiviteter til å kunne endre størrelse"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Dette gjør at alle aktivitene kan endre størrelse for flervindusmodus, uavhengig av manifestverdier."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Gjør at alle aktivitetene kan endre størrelse for flervindusmodus, uavhengig av manifestverdier."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Slå på vinduer i fritt format"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Slår på støtte for vinduer i eksperimentelt fritt format."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Slå på støtte for vinduer i eksperimentelt fritt format."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Passord for sikkerhetskopiering på datamaskin"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Fullstendig sikkerhetskopiering på datamaskin beskyttes ikke for øyeblikket."</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Trykk for å endre eller fjerne passordet for fullstendige sikkerhetskopier på datamaskinen"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Slått av"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Alltid på"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatisk"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Angi WebView-implementering"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Den valgte implementeringen av nettvisningen er slått av – den må slås på for å brukes. Vil du slå den på?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Fargekorrigering"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Denne funksjonen er eksperimentell og kan påvirke ytelsen."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overstyres av <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca. <xliff:g id="TIME">%1$s</xliff:g> gjenstår"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – ca. <xliff:g id="TIME">%2$s</xliff:g> igjen"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – fulladet om <xliff:g id="TIME">%2$s</xliff:g>"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Fullt"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Avslått av administratoren"</string> <string name="home" msgid="8263346537524314127">"Startside"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> siden"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> gjenstår"</string> </resources> diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml index 715f055f696d..f0cfdab27ada 100644 --- a/packages/SettingsLib/res/values-ne-rNP/strings.xml +++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"बाह्यमा बल प्रयोगको अनुमति प्राप्त अनुप्रयोगहरू"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"म्यानिफेेस्टको उपेक्षा गरी, कुनै पनि अनुप्रयोगलाई बाह्य भण्डारणमा लेख्न योग्य बनाउँछ"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"गतिविधिहरू रिसाइज गर्नको लागि बाध्य गर्नुहोस्"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"म्यानिफेेस्ट मानहरूको ख्याल नगरी, बहु-विन्डोको लागि सबै रिसाइज गर्न सकिने गतिविधिहरू बनाउँछ।"</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"म्यानिफेेस्ट मानहरूको ख्याल नगरी, बहु-विन्डोको लागि सबै रिसाइज गर्न सकिने गतिविधिहरू बनाउँछ।"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"फ्रिफर्म विन्डोहरू सक्रिय गर्नुहोस्"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"प्रयोगात्मक फ्रिफर्म विन्डोहरूका लागि समर्थनलाई सक्रिय गर्छ।"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"प्रयोगात्मक फ्रिफर्म विन्डोहरूका लागि समर्थन सक्रिय गर्नुहोस्।"</string> <string name="local_backup_password_title" msgid="3860471654439418822">"डेस्कटप ब्याकअप पासवर्ड"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"डेस्कटप पूर्ण जगेडाहरू हाललाई सुरक्षित छैनन्"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"डेस्कटप पूर्ण ब्याकअपको लागि पासवर्ड बदल्न वा हटाउन ट्याप गर्नुहोस्"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"असक्षम गरियो"</string> <string name="night_mode_yes" msgid="2218157265997633432">"सधैं खुल्ला"</string> <string name="night_mode_auto" msgid="7508348175804304327">"स्वचालित"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView कार्यान्वयन"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView कार्यान्वयन सेट गर्नुहोस्"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"छनौट गरिएको WebView को कार्यान्वयन असक्षम गरिएको छ र प्रयोग गर्नका लागि सक्रिय गर्नुपर्छ, तपाईँ यसलाई सक्रिय गर्न चाहनुहुन्छ?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"रङ्ग सुधार"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"यो सुविधा प्रयोगात्मक छ र प्रदर्शनमा असर गर्न सक्छ।"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारा अधिरोहित"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"लगभग <xliff:g id="TIME">%2$s</xliff:g> बाँकी छ"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"लगभग <xliff:g id="TIME">%1$s</xliff:g> बाँकी छ"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - लगभग। <xliff:g id="TIME">%2$s</xliff:g> बायाँ"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पूर्ण नभए सम्म"</string> diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index bd2420131c07..0dbf5b9e0783 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Toestaan van apps op externe opslag afdwingen"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Hierdoor komt een app in aanmerking om te worden geschreven naar externe opslag, ongeacht de manifestwaarden"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Formaat activiteiten geforceerd aanpasbaar maken"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Hiermee wordt het formaat van alle activiteiten aanpasbaar gemaakt, ongeacht de manifestwaarden."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Het formaat van alle activiteiten aanpasbaar maken, ongeacht de manifestwaarden."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Vensters met vrije vorm inschakelen"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Schakelt ondersteuning in voor vensters met experimentele vrije vorm."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Ondersteuning voor vensters met experimentele vrije vorm inschakelen."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Wachtwoord desktopback-up"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Volledige back-ups naar desktops zijn momenteel niet beveiligd"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tik om het wachtwoord voor volledige back-ups naar desktops te wijzigen of te verwijderen"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Uitgeschakeld"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Altijd aan"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatisch"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementatie"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView-implementatie instellen"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"De gekozen WebView-implementatie is uitgeschakeld en moet worden ingeschakeld voor gebruik. Wil je deze inschakelen?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Kleurcorrectie"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Deze functie is experimenteel en kan invloed hebben op de prestaties."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overschreven door <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca. <xliff:g id="TIME">%1$s</xliff:g> resterend"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ca. <xliff:g id="TIME">%2$s</xliff:g> resterend"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot vol"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Volledig"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Uitgeschakeld door beheerder"</string> <string name="home" msgid="8263346537524314127">"Startpagina"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> geleden"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> resterend"</string> </resources> diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml index f9c0c11b6c7e..2f44757b087f 100644 --- a/packages/SettingsLib/res/values-pa-rIN/strings.xml +++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"ਐਪਸ ਨੂੰ ਬਾਹਰਲੇ ਤੇ ਜ਼ਬਰਦਸਤੀ ਆਗਿਆ ਦਿਓ"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ਇੱਕ ਐਪ ਨੂੰ ਬਾਹਰਲੀ ਸਟੋਰੇਜ ਤੇ ਲਿਖਣ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ, ਮੈਨੀਫੈਸਟ ਵੈਲਯੂਜ ਤੇ ਵਿਚਾਰ ਕੀਤੇ ਬਿਨਾਂ"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"ਮੁੜ-ਆਕਾਰ ਬਦਲਣ ਲਈ ਸਰਗਰਮੀਆਂ \'ਤੇ ਜ਼ੋਰ ਦਿਓ"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"ਮਲਟੀ-ਵਿੰਡੋ ਲਈ ਸਾਰੀਆਂ ਸਰਗਰਮੀਆਂ ਨੂੰ ਮੁੜ-ਆਕਾਰ ਵਿੱਚ ਲਿਆਉਂਦੀ ਹੈ, ਚਾਹੇ ਮੈਨੀਫੈਸਟ ਵੈਲਯੂਜ਼ ਕੁਝ ਵੀ ਹੋਣ।"</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ਮੈਨੀਫੈਸਟ ਮੁੱਲਾਂ ਦੀ ਪਰਵਾਹ ਕੀਤੇ ਬਿਨਾਂ, ਮਲਟੀ-ਵਿੰਡੋ ਲਈ ਸਾਰੀਆਂ ਸਰਗਰਮੀਆਂ ਨੂੰ ਆਕਾਰ ਬਦਲਣਯੋਗ ਬਣਾਓ।"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"freeform windows ਨੂੰ ਯੋਗ ਬਣਾਓ"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"ਪ੍ਰਯੋਗਾਤਮਕ freeform windows ਲਈ ਸਮਰਥਨ ਨੂੰ ਯੋਗ ਬਣਾਉਂਦੀ ਹੈ।"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"ਪ੍ਰਯੋਗਮਈ ਫ੍ਰੀਫਾਰਮ ਵਿੰਡੋਜ਼ ਲਈ ਸਮਰਥਨ ਨੂੰ ਯੋਗ ਬਣਾਓ।"</string> <string name="local_backup_password_title" msgid="3860471654439418822">"ਡੈਸਕਟੌਪ ਬੈਕਅਪ ਪਾਸਵਰਡ"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"ਡੈਸਕਟੌਪ ਪੂਰੇ ਬੈਕਅਪਸ ਇਸ ਵੇਲੇ ਸੁਰੱਖਿਅਤ ਨਹੀਂ ਹਨ"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"ਡੈਸਕਟਾਪ ਦੇ ਮੁਕੰਮਲ ਬੈਕਅੱਪਾਂ ਲਈ ਪਾਸਵਰਡ ਨੂੰ ਬਦਲਣ ਜਾਂ ਹਟਾਉਣ ਲਈ ਟੈਪ ਕਰੋ"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"ਅਸਮਰੱਥ ਬਣਾਇਆ"</string> <string name="night_mode_yes" msgid="2218157265997633432">"ਹਮੇਸ਼ਾ ਚਾਲੂ"</string> <string name="night_mode_auto" msgid="7508348175804304327">"ਆਟੋਮੈਟਿਕ"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ਅਮਲ"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ਅਮਲ ਸੈੱਟ ਕਰੋ"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ਚੁਣਿਆ ਗਿਆ WebView ਅਮਲ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ, ਅਤੇ ਵਰਤੋਂ ਕਰਨ ਲਈ ਇਸ ਨੂੰ ਯੋਗ ਬਣਾਇਆ ਜਾਣਾ ਜ਼ਰੂਰੀ ਹੈ, ਕੀ ਤੁਸੀਂ ਇਸ ਨੂੰ ਯੋਗ ਬਣਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"ਰੰਗ ਸੰਸ਼ੋਧਨ"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਪ੍ਰਯੋਗਾਤਮਿਕ ਹੈ ਅਤੇ ਪ੍ਰਦਰਸ਼ਨ ਤੇ ਅਸਰ ਪਾ ਸਕਦੀ ਹੈ।"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ਦੁਆਰਾ ਓਵਰਰਾਈਡ ਕੀਤਾ"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"ਲਗਭਗ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"ਲਗਭਗ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਲਗਭਗ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ਪੂਰੀ ਹੋਣ ਤੱਕ"</string> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index 4ff0d03cc903..e30925c9695d 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Wymuś zezwalanie na aplikacje w pamięci zewn."</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Pozwala na zapis aplikacji w pamięci zewn. niezależnie od wartości w pliku manifestu"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Wymuś zmianę rozmiaru okien aktywności"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Umożliwia zmianę rozmiaru wszystkich okien aktywności w trybie wielu okien niezależnie od ustawień w pliku manifestu."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Zezwól na zmianę rozmiaru wszystkich okien aktywności w trybie wielu okien niezależnie od ustawień w pliku manifestu."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Włącz dowolny rozmiar okien"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Włącza obsługę eksperymentalnej funkcji dowolnego rozmiaru okien."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Włącz obsługę eksperymentalnej funkcji dowolnego rozmiaru okien."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Hasło kopii zapasowej"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Pełne kopie zapasowe na komputerze nie są obecnie chronione"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Dotknij, by zmienić lub usunąć hasło pełnych kopii zapasowych na komputerze."</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Wyłączone"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Zawsze włączone"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatycznie"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementacja WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Ustaw implementację WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Wybrana implementacja WebView jest wyłączona. Aby jej używać, musisz ją włączyć. Chcesz to zrobić?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korekcja kolorów"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"To jest funkcja eksperymentalna i może wpływać na działanie urządzenia."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Nadpisana przez <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Pozostało około <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – zostało ok. <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Naładowana"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Wyłączone przez administratora"</string> <string name="home" msgid="8263346537524314127">"Ekran główny"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> temu"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Pozostało: <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml index b4251a5387ab..ec54e4fc5043 100644 --- a/packages/SettingsLib/res/values-pt-rBR/strings.xml +++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Forçar permissão de apps em armazenamento externo"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Qualifica apps p/ gravação em armazenamento externo, independentemente de valores de manifestos"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Forçar atividades a serem redimensionáveis"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Torna todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Ativar janelas de forma livre"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Ativa a compatibilidade com janelas de forma livre experimentais."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Ativar a compatibilidade com janelas de forma livre experimentais."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Senha do backup local"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Os backups completos do computador não estão protegidos no momento"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Toque para alterar ou remover a senha de backups completos do desktop"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Desativada"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Sempre ativada"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automático"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementação do WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configurar implementação do WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"A implementação do WebView escolhida está desativada e deve ser ativada para ser usada. Deseja ativá-la?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correção de cor"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Este recurso é experimental e pode afetar o desempenho."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Aproximadamente <xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - cerca de <xliff:g id="TIME">%2$s</xliff:g> restantes"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Cheio"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Desativada pelo administrador"</string> <string name="home" msgid="8263346537524314127">"Início"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> atrás"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> restante(s)"</string> </resources> diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index 3dd9561c50d0..ab2a5aeac4ab 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Forçar perm. de aplicações no armazenamento ext."</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Qualquer aplic. pode ser gravada no arm. ext., independ. dos valores do manif."</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Forçar as atividades a serem redimensionáveis"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Torna todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Ativar janelas de forma livre"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Ativa a compatibilidade com janelas de forma livre experimentais."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Ativar a compatibilidade com janelas de forma livre experimentais."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Palavra-passe cópia do comp."</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"As cópias de segurança completas no ambiente de trabalho não estão atualmente protegidas"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tocar para alterar ou remover a palavra-passe para cópias de segurança completas no ambiente de trabalho"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Desativado"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Sempre ativado"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automático"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementação WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Definir implementação WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"A implementação WebView escolhida foi desativada e tem de ser ativada para poder ser utilizada. Pretende ativá-la?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correção da cor"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta funcionalidade é experimental e pode afetar o desempenho."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"Resta(m) aproximadamente <xliff:g id="TIME">%2$s</xliff:g>"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Resta(m) aproximadamente <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – resta(m) aprox. <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar completa"</string> diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml index b4251a5387ab..ec54e4fc5043 100644 --- a/packages/SettingsLib/res/values-pt/strings.xml +++ b/packages/SettingsLib/res/values-pt/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Forçar permissão de apps em armazenamento externo"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Qualifica apps p/ gravação em armazenamento externo, independentemente de valores de manifestos"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Forçar atividades a serem redimensionáveis"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Torna todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Ativar janelas de forma livre"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Ativa a compatibilidade com janelas de forma livre experimentais."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Ativar a compatibilidade com janelas de forma livre experimentais."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Senha do backup local"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Os backups completos do computador não estão protegidos no momento"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Toque para alterar ou remover a senha de backups completos do desktop"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Desativada"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Sempre ativada"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automático"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementação do WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configurar implementação do WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"A implementação do WebView escolhida está desativada e deve ser ativada para ser usada. Deseja ativá-la?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correção de cor"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Este recurso é experimental e pode afetar o desempenho."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Aproximadamente <xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - cerca de <xliff:g id="TIME">%2$s</xliff:g> restantes"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Cheio"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Desativada pelo administrador"</string> <string name="home" msgid="8263346537524314127">"Início"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> atrás"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> restante(s)"</string> </resources> diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index e883d0afc37d..0cfacd7f3c5d 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -85,7 +85,7 @@ <string name="accessibility_wifi_signal_full" msgid="7061045677694702">"Semnal Wi-Fi: complet."</string> <string name="process_kernel_label" msgid="3916858646836739323">"Sistem de operare Android"</string> <string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplicații eliminate"</string> - <string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplicaţii și utilizatori eliminaţi"</string> + <string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplicații și utilizatori eliminați"</string> <string name="tether_settings_title_usb" msgid="6688416425801386511">"Tethering prin USB"</string> <string name="tether_settings_title_wifi" msgid="3277144155960302049">"Hotspot portabil"</string> <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Tethering prin Bluetooth"</string> @@ -102,7 +102,7 @@ <string name="tts_default_rate_title" msgid="6030550998379310088">"Ritmul vorbirii"</string> <string name="tts_default_rate_summary" msgid="4061815292287182801">"Viteza cu care este vorbit textul"</string> <string name="tts_default_lang_title" msgid="8018087612299820556">"Limbă"</string> - <string name="tts_lang_use_system" msgid="2679252467416513208">"Utilizaţi limba sistemului"</string> + <string name="tts_lang_use_system" msgid="2679252467416513208">"Utilizați limba sistemului"</string> <string name="tts_lang_not_selected" msgid="7395787019276734765">"Nu ați selectat limba"</string> <string name="tts_default_lang_summary" msgid="5219362163902707785">"Setează vocea caracteristică limbii pentru textul vorbit"</string> <string name="tts_play_example_title" msgid="7094780383253097230">"Ascultați un exemplu"</string> @@ -110,7 +110,7 @@ <string name="tts_install_data_title" msgid="4264378440508149986">"Instalați date vocale"</string> <string name="tts_install_data_summary" msgid="5742135732511822589">"Instalați datele vocale necesare pentru sintetizarea vorbirii"</string> <string name="tts_engine_security_warning" msgid="8786238102020223650">"Acest motor de sintetizare a vorbirii poate culege în întregime textul vorbit, inclusiv datele personale cum ar fi parolele și numerele cărților de credit. Metoda provine de la motorul <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Permiteți utilizarea acestui motor de sintetizare a vorbirii?"</string> - <string name="tts_engine_network_required" msgid="1190837151485314743">"Pentru rezultatul transformării textului în vorbire pentru această limbă este necesară o conexiune de rețea care să funcţioneze."</string> + <string name="tts_engine_network_required" msgid="1190837151485314743">"Pentru rezultatul transformării textului în vorbire pentru această limbă este necesară o conexiune de rețea care să funcționeze."</string> <string name="tts_default_sample_string" msgid="4040835213373086322">"Acesta este un exemplu de sintetizare a vorbirii"</string> <string name="tts_status_title" msgid="7268566550242584413">"Starea limbii prestabilite"</string> <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> este acceptată integral"</string> @@ -175,7 +175,7 @@ <string name="select_usb_configuration_title" msgid="2649938511506971843">"Selectați configurația USB"</string> <string name="select_usb_configuration_dialog_title" msgid="6385564442851599963">"Selectați configurația USB"</string> <string name="allow_mock_location" msgid="2787962564578664888">"Permiteți locațiile fictive"</string> - <string name="allow_mock_location_summary" msgid="317615105156345626">"Permiteți locaţiile fictive"</string> + <string name="allow_mock_location_summary" msgid="317615105156345626">"Permiteți locațiile fictive"</string> <string name="debug_view_attributes" msgid="6485448367803310384">"Activați inspectarea atributelor de vizualizare"</string> <string name="legacy_dhcp_client_summary" msgid="163383566317652040">"Folosiți clientul DHCP din Lollipop în locul noului client Android DHCP."</string> <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Păstrați întotdeauna conexiunea de date mobile activată, chiar și atunci când funcția Wi‑Fi este activată (pentru comutarea rapidă între rețele)."</string> @@ -183,7 +183,7 @@ <string name="adb_warning_message" msgid="7316799925425402244">"Depanarea USB are exclusiv scopuri de dezvoltare. Utilizați-o pentru a copia date de pe computer pe dispozitiv, pentru a instala aplicații pe dispozitiv fără notificare și pentru a citi datele din jurnale."</string> <string name="adb_keys_warning_message" msgid="5659849457135841625">"Revocați accesul la remedierea erorilor prin USB de pe toate computerele pe care le-ați autorizat anterior?"</string> <string name="dev_settings_warning_title" msgid="7244607768088540165">"Permiteți setările pentru dezvoltare?"</string> - <string name="dev_settings_warning_message" msgid="2298337781139097964">"Aceste setări sunt destinate exclusiv utilizării pentru dezvoltare. Din cauza lor, este posibil ca dispozitivul dvs. și aplicațiile de pe acesta să nu mai funcţioneze sau să funcţioneze necorespunzător."</string> + <string name="dev_settings_warning_message" msgid="2298337781139097964">"Aceste setări sunt destinate exclusiv utilizării pentru dezvoltare. Din cauza lor, este posibil ca dispozitivul dvs. și aplicațiile de pe acesta să nu mai funcționeze sau să funcționeze necorespunzător."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificați aplicațiile prin USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Verificați aplicațiile instalate utilizând ADB/ADT, pentru a detecta un comportament dăunător."</string> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Dezactivează funcția Bluetooth de volum absolut în cazul problemelor de volum apărute la dispozitivele la distanță, cum ar fi volumul mult prea ridicat sau lipsa de control asupra acestuia."</string> @@ -194,11 +194,11 @@ <string name="debug_debugging_category" msgid="6781250159513471316">"Depanare"</string> <string name="debug_app" msgid="8349591734751384446">"Selectați aplicația de depanare"</string> <string name="debug_app_not_set" msgid="718752499586403499">"Nu ați setat o aplicație de depanare"</string> - <string name="debug_app_set" msgid="2063077997870280017">"Aplicaţie de depanare: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> - <string name="select_application" msgid="5156029161289091703">"Selectaţi o aplicație"</string> + <string name="debug_app_set" msgid="2063077997870280017">"Aplicație de depanare: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="select_application" msgid="5156029161289091703">"Selectați o aplicație"</string> <string name="no_application" msgid="2813387563129153880">"Niciuna"</string> - <string name="wait_for_debugger" msgid="1202370874528893091">"Aşteptaţi depanatorul"</string> - <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Înaintea executării, aplicația aşteaptă atașarea depanatorului"</string> + <string name="wait_for_debugger" msgid="1202370874528893091">"Așteptați depanatorul"</string> + <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Înaintea executării, aplicația așteaptă atașarea depanatorului"</string> <string name="debug_input_category" msgid="1811069939601180246">"Intrare"</string> <string name="debug_drawing_category" msgid="6755716469267367852">"Desen"</string> <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Redare accelerată hardware"</string> @@ -218,7 +218,7 @@ <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Straturile hardware clipesc verde la actualizare"</string> <string name="debug_hw_overdraw" msgid="2968692419951565417">"Depanați suprapunerea"</string> <string name="disable_overlays" msgid="2074488440505934665">"Dezactivați suprapun. HW"</string> - <string name="disable_overlays_summary" msgid="3578941133710758592">"Utilizaţi mereu GPU pentru compunerea ecranului"</string> + <string name="disable_overlays_summary" msgid="3578941133710758592">"Utilizați mereu GPU pentru compunerea ecranului"</string> <string name="simulate_color_space" msgid="6745847141353345872">"Simulați spațiu culoare"</string> <string name="enable_opengl_traces_title" msgid="6790444011053219871">"Monitorizări OpenGL"</string> <string name="usb_audio_disable_routing" msgid="8114498436003102671">"Dezactivați rutarea audio USB"</string> @@ -239,7 +239,7 @@ <string name="transition_animation_scale_title" msgid="387527540523595875">"Scară tranziție animații"</string> <string name="animator_duration_scale_title" msgid="3406722410819934083">"Scară durată Animator"</string> <string name="overlay_display_devices_title" msgid="5364176287998398539">"Simulați afișaje secundare"</string> - <string name="debug_applications_category" msgid="4206913653849771549">"Aplicaţii"</string> + <string name="debug_applications_category" msgid="4206913653849771549">"Aplicații"</string> <string name="immediately_destroy_activities" msgid="1579659389568133959">"Nu păstrați activitățile"</string> <string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"Elimină activitățile imediat ce utilizatorul le închide"</string> <string name="app_process_limit_title" msgid="4280600650253107163">"Limită procese fundal"</string> @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Forțați accesul aplicațiilor la stocarea externă"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Face orice aplicație eligibilă să fie scrisă în stocarea externă, indiferent de valorile manifestului"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Forțați redimensionarea activităților"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Permite redimensionarea tuturor activităților pentru modul cu ferestre multiple, indiferent de valorile manifestului."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permiteți redimensionarea tuturor activităților pentru modul cu ferestre multiple, indiferent de valorile manifestului."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Activați ferestrele cu formă liberă"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Activează compatibilitatea pentru ferestrele experimentale cu formă liberă."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Activați compatibilitatea pentru ferestrele experimentale cu formă liberă."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Parolă copie rez. desktop"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"În prezent, copiile de rezervă complete pe desktop nu sunt protejate"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Atingeți ca să modificați sau să eliminați parola pentru backupurile complete pe desktop"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Dezactivată"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Activată permanent"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automat"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementare WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Setați implementarea WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Implementarea WebView aleasă este dezactivată. Pentru a fi folosită, trebuie să fie activată. Doriți să o activați?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Corecția culorii"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Această funcție este experimentală și poate afecta performanțele."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Valoare înlocuită de <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Timp rămas: aproximativ <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – timp rămas: aproximativ <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcare completă"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Complet"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Dezactivată de administrator"</string> <string name="home" msgid="8263346537524314127">"Ecranul principal"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"Acum <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Timp rămas: <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index 0f4eaa1366c7..4b3214abfb32 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Разрешить сохранение на внешние накопители"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Разрешает сохранение приложений на внешние накопители независимо от значения манифеста"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Изменение размера в многооконном режиме"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Позволяет менять размер в многооконном режиме (независимо от значений манифеста)"</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Разрешить изменение размера в многооконном режиме (независимо от значений манифеста)"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Разрешить создание окон произвольной формы"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Включить экспериментальную функцию создания окон произвольной формы"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Включить экспериментальную функцию создания окон произвольной формы"</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Пароль для резервного копирования"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Полные резервные копии в настоящее время не защищены"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Нажмите, чтобы изменить или удалить пароль для резервного копирования"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Отключено"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Всегда включено"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Автоматическое переключение"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Сервис WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Настройки сервиса WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Чтобы использовать сервис WebView, включите его. Сделать это?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Коррекция цвета"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Это экспериментальная функция, она может снизить производительность устройства."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Новая настройка: <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Осталось примерно <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – осталось около <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Батарея заряжена"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Отключено администратором"</string> <string name="home" msgid="8263346537524314127">"Главная"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> назад"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Осталось <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml index 6483b189efd0..390e218cc61d 100644 --- a/packages/SettingsLib/res/values-si-rLK/strings.xml +++ b/packages/SettingsLib/res/values-si-rLK/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"බාහිර මත යෙදුම් ඉඩ දීම බල කරන්න"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"මැනිෆෙස්ට් අගයන් නොසලකා, ඕනෑම යෙදුමක් අභ්යන්තර ගබඩාවට ලිවීමට සුදුසුකම් ලබා දෙයි"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"ක්රියාකාරකම් ප්රතිප්රමාණ කළ හැකි බවට බල කරන්න"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"මැනිෆෙස්ට් අගයන් නොසලකා, සියලු ක්රියාකාරකම් බහු-කවුළු සඳහා ප්රතිප්රමාණ කළ හැකි බවට පත් කරයි."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"මැනිෆෙස්ට් අගයන් නොසලකා, සියලු ක්රියාකාරකම් බහු-කවුළුව සඳහා ප්රතිප්රමාණ කළ හැකි බවට පත් කරන්න."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"අනියම් හැඩැති කවුළු සබල කරන්න"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"පරීක්ෂණාත්මක අනියම් හැඩැති කවුළු සඳහා සහාය සබල කරයි."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"පරීක්ෂණාත්මක අනියම් හැඩැති කවුළු සඳහා සහාය සබල කරන්න."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"ඩෙස්ක්ටොප් උපස්ථ මුරපදය"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"ඩෙස්ක්ටොප් සම්පූර්ණ උපස්ථ දැනට ආරක්ෂා කර නොමැත"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"ඩෙස්ක්ටොප් සම්පූර්ණ උපස්ථ සඳහා මුරපදය වෙනස් කිරීමට හෝ ඉවත් කිරීමට තට්ටු කරන්න"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"අබලයි"</string> <string name="night_mode_yes" msgid="2218157265997633432">"සැමවිට ක්රියාත්මක"</string> <string name="night_mode_auto" msgid="7508348175804304327">"ස්වයංක්රීය"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ක්රියාත්මක කිරීම"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ක්රියාත්මක කිරීම සකසන්න"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"තෝරන ලද WebView ක්රියාත්මක කිරීම අබල අතර, භාවිත කිරීමට සබල කළ යුතුය, ඔබ එය සබල කිරීමට අදහස් කරන්නේද?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"වර්ණ නිවැරදි කිරීම"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"මෙම විශේෂාංගය පරීක්ෂණාත්මක සහ ඇතැම් විට ක්රියාකාරිත්වයට බලපෑ හැක."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> මගින් ඉක්මවන ලදී"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"දළ වශයෙන් <xliff:g id="TIME">%1$s</xliff:g>ක් ඉතිරිය"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආසන්න <xliff:g id="TIME">%2$s</xliff:g> වම"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> සම්පුර්ණ වන තෙක්"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"පූර්ණ"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"පරිපාලක විසින් අබල කරන ලදී"</string> <string name="home" msgid="8263346537524314127">"මුල් පිටුව"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>කට පෙර"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g>ක් ඉතිරිය"</string> </resources> diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index d8e2389eb43e..8bf64fa78cf2 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Vynútiť povolenie aplikácií na externom úložisku"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Umožňuje zapísať akúkoľvek aplikáciu do externého úložiska bez ohľadu na hodnoty v manifeste"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Vynútiť možnosť zmeny veľkosti aktivít"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Veľkosti všetkých aktivít bude možné zmeniť na niekoľko okien (bez ohľadu na hodnoty manifestu)."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Veľkosti všetkých aktivít bude možné zmeniť na niekoľko okien (bez ohľadu na hodnoty manifestu)."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Povoliť okná s voľným tvarom"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Povolenie podpory pre experimentálne okná s voľným tvarom."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Povolenie podpory pre experimentálne okná s voľným tvarom."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Heslo pre zálohy v počítači"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Úplné zálohy na počítači nie sú momentálne chránené"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Klepnutím zmeníte alebo odstránite heslo pre úplné zálohy do počítača"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Vypnuté"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Vždy zapnuté"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatický"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementácia komponenta WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Nastavenie implementácie komponenta WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Zvolená implementácia technológie WebView je zakázaná. Ak ju chcete použiť, musíte ju najprv povoliť. Chcete ju povoliť?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Úprava farieb"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Funkcia je experimentálna a môže mať vplyv na výkonnosť."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Prekonané predvoľbou <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Zostáva cca. <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – zostáva približne <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Nabitá"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Zakázané správcom"</string> <string name="home" msgid="8263346537524314127">"Domov"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"pred <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Zostáva <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index fa0e784bc2ca..42e589b6057a 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Vsili omogočanje aplikacij v zunanji shrambi"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsako aplikacijo zapisati v zunanjo shrambo"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Vsili povečanje velikosti za aktivnosti"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsem aktivnostim povečati velikost za način z več okni."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsem aktivnostim povečati velikost za način z več okni."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Omogočanje oken svobodne oblike"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Omogočanje podpore za poskusna okna svobodne oblike"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Omogočanje podpore za poskusna okna svobodne oblike"</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Geslo za varn. kop. rač."</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Popolne varnostne kopije namizja trenutno niso zaščitene"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Dotaknite se, če želite spremeniti ali odstraniti geslo za popolno varnostno kopiranje namizja"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Onemogočeno"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Vedno vklopljeno"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Samodejno"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Izvedba spletnega pogleda"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Nastavitev izvedbe spletnega pogleda"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Izbrana izvedba spletnega pogleda je onemogočena in jo morate omogočiti, če jo želite uporabljati. Ali jo želite omogočiti?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Popravljanje barv"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"To je preskusna funkcija in lahko vpliva na učinkovitost delovanja."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Preglasila nastavitev: <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"Še približno <xliff:g id="TIME">%2$s</xliff:g>"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Še približno <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – še približno <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti"</string> diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml index f9b62fbdcfdf..4c77a12497b7 100644 --- a/packages/SettingsLib/res/values-sq-rAL/strings.xml +++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Detyro lejimin në hapësirën e jashtme"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Bën që çdo aplikacion të jetë i përshtatshëm për t\'u shkruar në hapësirën ruajtëse të jashtme, pavarësisht nga vlerat e manifestit"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Detyro madhësinë e ndryshueshme për aktivitetet"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Bën që të gjitha aktivitetet të kenë madhësi të ndryshueshme për përdorimin me shumë dritare, pavarësisht vlerave të manifestit."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Bëj që të gjitha aktivitetet të kenë madhësi të ndryshueshme për përdorimin me shumë dritare, pavarësisht vlerave të manifestit."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Aktivizo dritaret me formë të lirë"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Aktivizon mbështetjen për dritaret eksperimentale me formë të lirë."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Aktivizo mbështetjen për dritaret eksperimentale me formë të lirë."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Fjalëkalimi rezervë i kompjuterit"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Rezervimet e plota në kompjuter nuk janë të mbrojtura aktualisht"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Trokit për të ndryshuar ose hequr fjalëkalimin për rezervime të plota të desktopit"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Çaktivizuar"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Gjithmonë aktive"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatike"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Zbatimi i WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Cakto zbatimin e WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Është çaktivizuar zbatimi i zgjedhur i WebView dhe duhet të aktivizohet për t\'u përdorur, dëshiron ta aktivizosh?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korrigjimi i ngjyrës"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ky funksion është eksperimental dhe mund të ndikojë në veprimtari."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Mbivendosur nga <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"Afërsisht <xliff:g id="TIME">%2$s</xliff:g> të mbetura"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Afërsisht <xliff:g id="TIME">%1$s</xliff:g> të mbetura"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - afërsisht <xliff:g id="TIME">%2$s</xliff:g> të mbetura"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të jetë e plotë"</string> diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index 002e963fe4fc..8c4702563f9c 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Принудно дозволи апликације у спољној"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Омогућава уписивање свих апликација у спољну меморију, без обзира на вредности манифеста"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Принудно омогући промену величине активности"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Омогућава промену величине свих активности за режим са више прозора, без обзира на вредности манифеста."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Омогући промену величине свих активности за режим са више прозора, без обзира на вредности манифеста."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Омогући прозоре произвољног формата"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Омогућава подршку за експерименталне прозоре произвољног формата."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Омогућите подршку за експерименталне прозоре произвољног формата."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Лозинка резервне копије за рачунар"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Резервне копије читавог система тренутно нису заштићене"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Додирните да бисте променили или уклонили лозинку за прављење резервних копија читавог система на рачунару"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Онемогућено"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Увек укључено"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Аутоматски"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Примена WebView-а"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Подесите примену WebView-а"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Изабрана примена WebView-а је онемогућена, а мора да буде омогућена ради коришћења. Желите ли да је омогућите?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Корекција боја"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ова функција је експериментална и може да утиче на перформансе."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Замењује га <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Још отприлике <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – преостало око <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> док се не напуни"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Пуно"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Онемогућио је администратор"</string> <string name="home" msgid="8263346537524314127">"Почетни"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"Пре <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Још <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index 9b6f3028d9f2..d25f9f55acb2 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Tillåt appar i externt lagringsutrymme"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Appen kan skrivas till extern lagring, oavsett manifestvärden"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Framtvinga storleksanpassning för aktiviteter"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Detta gör det möjligt att ändra storleken på alla aktiviteter i flerfönsterläge, oavsett manifestvärden."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Gör det möjligt att ändra storleken på alla aktiviteter i flerfönsterläge, oavsett manifestvärden."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Aktivera frihandsfönster"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Aktiverar stöd för experimentella frihandsfönster."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Aktivera stöd för experimentella frihandsfönster."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Lösenord för säkerhetskopia av datorn"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"De fullständiga säkerhetskopiorna av datorn är för närvarande inte skyddade"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tryck om du vill ändra eller ta bort lösenordet för fullständig säkerhetskopiering av datorn"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Inaktiverad"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Alltid på"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Automatiskt"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Ange WebView-implementering"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Den valda WebView-implementeringen har inaktiverats och måste aktiveras om du ska kunna använda den. Vill du aktivera den?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Färgkorrigering"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Den här funktionen är experimentell och kan påverka prestandan."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Har åsidosatts av <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca <xliff:g id="TIME">%1$s</xliff:g> kvar"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – ca <xliff:g id="TIME">%2$s</xliff:g> kvar"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till fulladdat"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Fullt"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Har inaktiverats av administratören"</string> <string name="home" msgid="8263346537524314127">"Startsida"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"för <xliff:g id="ID_1">%1$s</xliff:g> sedan"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> kvar"</string> </resources> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index f9171ce1d8bb..3f1d26af6f51 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Lazima uruhusu programu kwenye hifadhi ya nje"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Huweka programu kwenye hifadhi ya nje, bila kujali maelezo"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Lazimisha shughuli ziweze kubadilishwa ukubwa"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Fanya shughuli zote ziweze kubadilishwa ukubwa kwa ajili ya dirisha nyingi, bila kujali thamani za faili ya maelezo."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Fanya shughuli zote ziweze kubadilishwa ukubwa kwenye madirisha mengi, bila kuzingatia thamani za faili ya maelezo."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Washa madirisha yenye muundo huru"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Huwasha uwezo wa kutumia madirisha ya majaribio yenye muundo huru."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Ruhusu uwezo wa kutumia madirisha ya majaribio yenye muundo huru."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Nenosiri la hifadhi rudufu ya eneo kazi"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Hifadhi rudufu kamili za eneo kazi hazijalindwa kwa sasa"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Gonga ili ubadilishe au uondoe nenosiri la hifadhi rudufu kamili za eneo kazi"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Imezimwa"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Imewashwa kila wakati"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Otomatiki"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Utekelezaji wa WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Weka utekelezaji wa WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Kipengee ulichochagua cha utekelezaji wa WebView kimezimwa. Ni lazima ukiwashe ili kitumike. Ungependa kukiwasha?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Usahihishaji wa rangi"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Kipengele hiki ni cha majaribio na huenda kikaathiri utendaji."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Imetanguliwa na <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Zimesalia takribani <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia takriban <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia <xliff:g id="TIME">%2$s</xliff:g> hadi ijae"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Imejaa"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Msimamizi amezima mapendeleo ya mipangilio"</string> <string name="home" msgid="8263346537524314127">"Mwanzo"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"Zimepita <xliff:g id="ID_1">%1$s</xliff:g>"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Zimesalia <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml index 56970a7e50bd..f06b0f9a24b0 100644 --- a/packages/SettingsLib/res/values-ta-rIN/strings.xml +++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"பயன்பாடுகளை வெளிப்புறச் சேமிப்பிடத்தில் அனுமதி"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"மேனிஃபெஸ்ட் மதிப்புகளை பொருட்படுத்தாமல், எந்தப் பயன்பாட்டையும் வெளிப்புற சேமிப்பிடத்தில் எழுத அனுமதிக்கும்"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"செயல்பாடுகளை அளவுமாறக்கூடியதாக அமை"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"மேனிஃபெஸ்ட் மதிப்புகளைப் பொருட்படுத்தாமல், பல சாளரத்திற்கு எல்லா செயல்பாடுகளையும் அளவுமாறக்கூடியதாக அமைக்கும்."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"மேனிஃபெஸ்ட் மதிப்புகளைப் பொருட்படுத்தாமல், பல சாளரத்திற்கு எல்லா செயல்பாடுகளையும் அளவுமாறக்கூடியதாக அமை."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"குறிப்பிட்ட வடிவமில்லாத சாளரங்களை இயக்கு"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"பரிசோதனைக்குரிய குறிப்பிட்ட வடிவமில்லாத சாளரங்களுக்கான ஆதரவை இயக்கும்."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"சாளரங்களை அளவுமாற்ற மற்றும் எங்கும் நகர்த்த அனுமதிக்கும் பரிசோதனைக்குரிய அம்சத்திற்கான ஆதரவை இயக்கு."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"டெஸ்க்டாப் காப்புப்பிரதி கடவுச்சொல்"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"டெஸ்க்டாப்பின் முழு காப்புப்பிரதிகள் தற்போது பாதுகாக்கப்படவில்லை"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"டெஸ்க்டாப்பின் முழுக் காப்புப் பிரதிகளுக்கான கடவுச்சொல்லை மாற்ற அல்லது அகற்ற, தட்டவும்"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"முடக்கப்பட்டது"</string> <string name="night_mode_yes" msgid="2218157265997633432">"எப்போதும் இயக்கத்தில் வை"</string> <string name="night_mode_auto" msgid="7508348175804304327">"தானியங்கு"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView செயல்படுத்தல்"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView செயல்படுத்தலை அமை"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"தேர்வுசெய்த WebView செயல்படுத்தல் முடக்கப்பட்டுள்ளது, பயன்படுத்த வேண்டுமெனில் அதைக் கண்டிப்பாக இயக்க வேண்டும். இயக்க விரும்புகிறீர்களா?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"வண்ணத்திருத்தம்"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"இது சோதனை முறையிலான அம்சம், இது செயல்திறனைப் பாதிக்கலாம்."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> மூலம் மேலெழுதப்பட்டது"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"தோராயமாக <xliff:g id="TIME">%1$s</xliff:g> உள்ளது"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"தோராயம்: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> உள்ளது"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"முழு சார்ஜிற்கு: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"முழுமை"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"நிர்வாகி முடக்கியுள்ளார்"</string> <string name="home" msgid="8263346537524314127">"முகப்பு"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> முன்"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> உள்ளது"</string> </resources> diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml index 5a8c824a776e..e6d594b489c9 100644 --- a/packages/SettingsLib/res/values-te-rIN/strings.xml +++ b/packages/SettingsLib/res/values-te-rIN/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"అనువర్తనాలను బాహ్య నిల్వలో నిర్బంధంగా అనుమతించు"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ఏ అనువర్తనాన్ని అయినా మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా బాహ్య నిల్వలో వ్రాయగలిగేలా అనుమతిస్తుంది"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"కార్యాచరణలను పరిమాణం మార్చగలిగేలా నిర్బంధించు"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా అన్ని కార్యాచరణలను బహుళ విండోల్లో సరిపోయేటట్లు పరిమాణం మార్చగలిగేలా చేస్తుంది."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా అన్ని కార్యాచరణలను పలు రకాల విండోల్లో సరిపోయేట్లు పరిమాణం మార్చగలిగేలా చేస్తుంది."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"స్వతంత్ర రూప విండోలను ప్రారంభించండి"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"ప్రయోగాత్మక స్వతంత్ర రూప విండోలకు మద్దతును ప్రారంభిస్తుంది."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"ప్రయోగాత్మక స్వతంత్ర రూప విండోల కోసం మద్దతును ప్రారంభిస్తుంది."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"డెస్క్టాప్ బ్యాకప్ పాస్వర్డ్"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"డెస్క్టాప్ పూర్తి బ్యాకప్లు ప్రస్తుతం రక్షించబడలేదు"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"డెస్క్టాప్ పూర్తి బ్యాకప్ల కోసం పాస్వర్డ్ను మార్చడానికి లేదా తీసివేయడానికి నొక్కండి"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"నిలిపివేయబడింది"</string> <string name="night_mode_yes" msgid="2218157265997633432">"ఎల్లప్పుడూ ఆన్లో ఉంచు"</string> <string name="night_mode_auto" msgid="7508348175804304327">"స్వయంచాలకం"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"వెబ్ వీక్షణ అమలు"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"వెబ్ వీక్షణ అమలుని సెట్ చేయండి"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ఎంచుకున్న వెబ్ వీక్షణ అమలు నిలిపివేయబడింది, కానీ ఉపయోగించడానికి తప్పనిసరిగా ప్రారంభించాల్సి ఉంటుంది, మీరు దీన్ని ప్రారంభించాలనుకుంటున్నారా?"</string> @@ -296,7 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"రంగు సవరణ"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ఈ లక్షణం ప్రయోగాత్మకమైనది మరియు పనితీరుపై ప్రభావం చూపవచ్చు."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ద్వారా భర్తీ చేయబడింది"</string> - <string name="power_remaining_duration_only" msgid="4400068916452346544">"సుమారు <xliff:g id="TIME">%2$s</xliff:g> మిగిలి ఉంది"</string> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"సుమారు <xliff:g id="TIME">%1$s</xliff:g> మిగిలి ఉంది"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - సుమారు <xliff:g id="TIME">%2$s</xliff:g> మిగిలి ఉంది"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - పూర్తిగా నిండటానికి <xliff:g id="TIME">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index 5ef31682ce23..ab428a96242c 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"บังคับให้แอปสามารถใช้ที่เก็บภายนอก"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ให้สามารถเขียนแอปต่างๆ ไปยังที่เก็บภายนอกได้ โดยไม่คำนึงถึงค่าในไฟล์ Manifest"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"บังคับให้กิจกรรมปรับขนาดได้"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"ทำให้กิจกรรมทั้งหมดปรับขนาดได้สำหรับหน้าต่างหลายบาน โดยไม่คำนึงถึงค่าในไฟล์ Manifest"</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ทำให้กิจกรรมทั้งหมดปรับขนาดได้สำหรับหน้าต่างหลายบาน โดยไม่คำนึงถึงค่าในไฟล์ Manifest"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"เปิดใช้หน้าต่างรูปแบบอิสระ"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"เปิดการสนับสนุนหน้าต่างรูปแบบอิสระแบบทดลอง"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"เปิดการสนับสนุนหน้าต่างรูปแบบอิสระแบบทดลอง"</string> <string name="local_backup_password_title" msgid="3860471654439418822">"รหัสผ่านการสำรองข้อมูลในเดสก์ท็อป"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"การสำรองข้อมูลเต็มรูปแบบในเดสก์ท็อป ไม่ได้รับการป้องกันในขณะนี้"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"แตะเพื่อเปลี่ยนแปลงหรือลบรหัสผ่านสำหรับการสำรองข้อมูลเต็มรูปแบบในเดสก์ท็อป"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"ปิดใช้แล้ว"</string> <string name="night_mode_yes" msgid="2218157265997633432">"เปิดใช้เสมอ"</string> <string name="night_mode_auto" msgid="7508348175804304327">"อัตโนมัติ"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"การใช้งาน WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"ตั้งค่าการใช้งาน WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"การใช้งาน WebView ที่เลือกไว้ถูกปิดใช้อยู่ คุณต้องการเปิดใช้เพื่อที่จะใช้งานไหม"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"การแก้สี"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"คุณลักษณะนี้เป็นแบบทดลองและอาจส่งผลต่อประสิทธิภาพการทำงาน"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"แทนที่โดย <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"เหลืออีกประมาณ <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - เหลือประมาณ <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะเต็ม"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"เต็ม"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"ปิดใช้โดยผู้ดูแลระบบ"</string> <string name="home" msgid="8263346537524314127">"หน้าแรก"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>ที่ผ่านมา"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"เหลือ <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index 8a7d6aa3adf8..b21acdafb2f6 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Pwersahang payagan ang mga app sa external"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Mara-write na sa external storage ang anumang app, anuman ang manifest value"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Sapilitang gawing resizable ang mga aktibidad"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Gawing resizable para sa multi-window ang lahat ng aktibidad, anuman ang mga manifest value."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Gawing nare-resize ang lahat ng aktibidad para sa multi-window, anuman ang mga value ng manifest."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"I-enable ang mga freeform window"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Ine-enable ang suporta para sa mga pang-eksperimentong freeform window."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"I-enable ang suporta para sa mga pang-eksperimentong freeform window."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Password ng pag-backup ng desktop"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Kasalukuyang hindi pinoprotektahan ang mga buong pag-backup ng desktop"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"I-tap upang baguhin o alisin ang password para sa mga kumpletong pag-back up sa desktop"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Naka-disable"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Palaging naka-on"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Awtomatiko"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Pagpapatupad sa WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Itakda ang pagpapatupad sa WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Naka-disable ang napiling pagpapatupad sa WebView, at dapat itong i-enable upang magamit, gusto mo ba itong i-enable?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Pagtatama ng kulay"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ang feature na ito ay pinag-eeksperimentuhan at maaaring makaapekto sa pagganap."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Na-override ng <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> na lang ang natitira"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - humigit kumulang <xliff:g id="TIME">%2$s</xliff:g> ang natitira"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> bago mapuno"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Puno"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Na-disable ng administrator"</string> <string name="home" msgid="8263346537524314127">"Home"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> na ang nakalipas"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> na lang"</string> </resources> diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index 11b975ed1cf1..beca481f3f58 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Harici birimdeki uygulamalara izin vermeye zorla"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Bildirilen değerlerden bağımsız olarak uygulamaları harici depolamaya yazmak için uygun hale getirir"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Etkinlikleri yeniden boyutlandırılabilmeye zorla"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Manifest değerlerinden bağımsız olarak, tüm etkinlikleri birden fazla pencerede yeniden boyutlandırılabilir hale getirir."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Manifest değerlerinden bağımsız olarak, tüm etkinlikleri birden fazla pencerede yeniden boyutlandırılabilir yap."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Serbest biçimli pencereleri etkinleştir"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Deneysel serbest biçimli pencereleri etkinleştirir."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Deneysel serbest biçimli pencere desteğini etkinleştir."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Masaüstü yedekleme şifresi"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Masaüstü tam yedeklemeleri şu an korunmuyor"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Masaüstü tam yedeklemelerinin şifresini değiştirmek veya kaldırmak için hafifçe dokunun"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Devre dışı"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Her zaman açık"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Otomatik"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView kullanımı"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView kullanımını ayarla"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Seçilen WebView uygulama şekli devre dışı. Bu uygulama şeklinin kullanılabilmesi için etkinleştirilmesi gerekir. Etkinleştirmek istiyor musunuz?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Renk düzeltme"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu özellik deneyseldir ve performansı etkileyebilir."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> tarafından geçersiz kılındı"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Yaklaşık <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - yaklaşık <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - tam şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> var"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Dolu"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Yönetici tarafından devre dışı bırakıldı"</string> <string name="home" msgid="8263346537524314127">"Ana Ekran"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> önce"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> kaldı"</string> </resources> diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index ad18d7f39f9e..9250dfd2f379 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Примусово записувати додатки в зовнішню пам’ять"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Додатки можна записувати на зовнішню пам’ять незалежно від значень маніфесту"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Примусово масштабувати активність"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Активність масштабуватиметься на кілька вікон, незалежно від значень у файлі маніфесту."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Масштабувати активність на кілька вікон, незалежно від значень у файлі маніфесту."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Увімкнути вікна довільного формату"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Увімкнуться експериментальні вікна довільного формату."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Увімкнути експериментальні вікна довільного формату."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Пароль резерв.копії на ПК"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Повні резервні копії на комп’ютері наразі не захищені"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Торкніться, щоб змінити або видалити пароль для повного резервного копіювання на комп’ютер"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Вимкнено"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Завжди ввімкнено"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Автоматично"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Застосування WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Налаштувати застосування WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Вибране застосування WebView вимкнено. Увімкнути його?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Корекція кольору"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Це експериментальна функція. Вона може вплинути на продуктивність."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Замінено на <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Залишилося приблизно <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – залишилось близько <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного зарядження"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Акумулятор заряджено"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Вимкнено адміністратором"</string> <string name="home" msgid="8263346537524314127">"Головний екран"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> тому"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Залишилося <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml index 670f2e66a8cb..3173b33360c9 100644 --- a/packages/SettingsLib/res/values-ur-rPK/strings.xml +++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"بیرونی پر ایپس کو زبردستی اجازت دیں"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"manifest اقدار سے قطع نظر، کسی بھی ایپ کو بیرونی اسٹوریج پر لکھے جانے کا اہل بناتا ہے"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"سرگرمیوں کو ری سائز ایبل بنائیں"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"manifest اقدار سے قطع نظر، ملٹی ونڈو کیلئے تمام سرگرمیوں کو ری سائز ایبل بناتا ہے۔"</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"manifest اقدار سے قطع نظر، ملٹی ونڈو کیلئے تمام سرگرمیوں کو ری سائز ایبل بنائیں۔"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"freeform ونڈوز فعال کریں"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"تجرباتی freeform ونڈوز کے لئے سپورٹ فعال کرتا ہے۔"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"تجرباتی freeform ونڈوز کیلئے سپورٹ فعال کریں۔"</string> <string name="local_backup_password_title" msgid="3860471654439418822">"ڈیسک ٹاپ کا بیک اپ پاس ورڈ"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"ڈیسک ٹاپ کے مکمل بیک اپس فی الحال محفوظ کیے ہوئے نہیں ہیں"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"ڈیسک ٹاپ کے مکمل بیک اپس کیلئے پاس ورڈ کو تبدیل کرنے یا ہٹانے کیلئے تھپتھپائیں"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"غیر فعال"</string> <string name="night_mode_yes" msgid="2218157265997633432">"ہمیشہ آن"</string> <string name="night_mode_auto" msgid="7508348175804304327">"خودکار"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView کا نفاذ"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView کا نفاذ سیٹ کریں"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"منتخب کردہ WebView کا نفاذ غیر فعال ہے اور استعمال کرنے کیلئے اسے فعال ہونا چاہئیے، کیا آپ اسے فعال کرنا چاہتے ہیں؟"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"رنگ کی اصلاح"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"یہ خصوصیت تجرباتی ہے اور اس کی وجہ سے کاکردگی متاثر ہو سکتی ہے۔"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> کے ذریعہ منسوخ کردیا گیا"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"تقریبا <xliff:g id="TIME">%1$s</xliff:g> باقی ہیں"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - تقریبا <xliff:g id="TIME">%2$s</xliff:g> باقی"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> پورا ہونے تک"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"مکمل"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"منتظم نے غیر فعال کر دیا"</string> <string name="home" msgid="8263346537524314127">"ہوم"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> قبل"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> باقی ہیں"</string> </resources> diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml index e7dccae64604..d6d820797c2f 100644 --- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml +++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Tashqi xotira qurilmasidagi ilova dasturlariga majburiy ruxsat berish"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Manifest qiymatidan qat’i nazar istalgan ilovani tashqi xotiraga saqlash imkonini beradi"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Harakatlarni moslashuvchan o‘lchamga keltirish"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Manifest qiymatidan qat’i nazar barcha harakatlarni ko‘p oynali rejimga moslashtiradi."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Manifest qiymatidan qat’i nazar barcha harakatlarni ko‘p oynali rejimga moslashtirish."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Erkin shakldagi oynalarni yoqish"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Tajribaviy erkin shakldagi oynalar ta’minotini yoqadi"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Tajribaviy erkin shakldagi oynalar ta’minotini yoqish."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Zaxira nusxa uchun parol"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Kompyuterdagi zaxira nusxalar hozirgi vaqtda himoyalanmagan"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Ish stoli to‘liq zaxira nusxalari parolini o‘zgartirish yoki o‘chirish uchun bu yerni bosing"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"O‘chiq"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Har doim yoniq tursin"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Avtomatik"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ta’minotchisi"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ta’minotchisini sozlash"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Tanlangan WebView ta’minotchisi o‘chirilgan va foydalanish uchun yoqilishi zarur. Yoqilsinmi?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Rangni tuzatish"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu funksiya tajribaviy bo‘lib, u qurilma unumdorligiga ta’sir qilishi mumkin."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> bilan almashtirildi"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – taxminan <xliff:g id="TIME">%2$s</xliff:g> qoldi"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, to‘lguncha"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"To‘la"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Administrator tomonidan o‘chirib qo‘yilgan"</string> <string name="home" msgid="8263346537524314127">"Bosh ekran"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> oldin"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> qoldi"</string> </resources> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index c803415959ac..5cc34bbfde17 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Buộc cho phép các ứng dụng trên bộ nhớ ngoài"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Giúp ứng dụng bất kỳ đủ điều kiện được ghi vào bộ nhớ ngoài bất kể giá trị tệp kê khai là gì"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Buộc các hoạt động có thể thay đổi kích thước"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Giúp tất cả hoạt động có thể thay đổi kích thước cho nhiều cửa sổ bất kể giá trị tệp kê khai là gì."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Giúp tất cả hoạt động có thể thay đổi kích thước cho nhiều cửa sổ bất kể giá trị tệp kê khai là gì."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Bật cửa sổ dạng tự do"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Bật tính năng hỗ trợ cửa sổ dạng tự do thử nghiệm."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Bật tính năng hỗ trợ cửa sổ dạng tự do thử nghiệm."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Mật khẩu sao lưu của máy tính"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Sao lưu toàn bộ máy tính hiện không được bảo vệ"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Nhấn để thay đổi hoặc xóa mật khẩu dành cho sao lưu toàn bộ tới máy tính"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Đã tắt"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Luôn bật"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Tự động"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Triển khai WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Đặt triển khai WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Triển khai WebView đã chọn bị vô hiệu hóa và bạn phải bật để sử dụng tính năng này. Bạn có muốn bật tính năng này không?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Sửa màu"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Tính năng này là tính năng thử nghiệm và có thể ảnh hưởng đến hoạt động."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Bị ghi đè bởi <xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Còn khoảng <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - còn khoảng <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> cho đến khi đầy"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Đầy"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Bị tắt bởi quản trị viên"</string> <string name="home" msgid="8263346537524314127">"Màn hình chính"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> trước"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"Còn <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index 54a6e7c6a1e0..4b6732248ab7 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -248,9 +248,11 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"强制允许将应用写入外部存储设备"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"允许将任何应用写入外部存储设备(无论清单值是什么)"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"强制将活动设为可调整大小"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"将所有活动设为可配合多窗口环境调整大小(无论清单值是什么)。"</string> + <!-- no translation found for force_resizable_activities_summary (6667493494706124459) --> + <skip /> <string name="enable_freeform_support" msgid="1461893351278940416">"启用可自由调整的窗口"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"启用可自由调整的窗口这一实验性功能。"</string> + <!-- no translation found for enable_freeform_support_summary (8247310463288834487) --> + <skip /> <string name="local_backup_password_title" msgid="3860471654439418822">"桌面备份密码"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"桌面完整备份当前未设置密码保护"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"点按即可更改或移除用于保护桌面完整备份的密码"</string> @@ -277,6 +279,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"已停用"</string> <string name="night_mode_yes" msgid="2218157265997633432">"始终开启"</string> <string name="night_mode_auto" msgid="7508348175804304327">"自动"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView 实现"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"设置 WebView 实现"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"所选的 WebView 实现已停用,您必须先启用 WebView 实现才能加以使用。要启用该 WebView 实现吗?"</string> @@ -296,8 +302,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"色彩校正"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"此功能为实验性功能,可能会影响性能。"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"已被“<xliff:g id="TITLE">%1$s</xliff:g>”覆盖"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"还剩大约 <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还可用大约<xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满"</string> @@ -314,8 +319,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"电量充足"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"已被管理员禁用"</string> <string name="home" msgid="8263346537524314127">"主屏幕"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>前"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"还剩 <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index e95a3243d942..301b90bdb8b3 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"強制允許應用程式寫入到外部儲存空間"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"允許將所有應用程式寫入到外部儲存完間 (所有資訊清單值)"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"強制可變更活動尺寸"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"在任何資訊清單值下,允許為多個視窗變更所有活動的尺寸。"</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"在任何資訊清單值下,允許系統配合多重視窗環境調整所有活動的尺寸。"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"啟用自由形態視窗"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"啟用實驗版自由形態視窗的支援功能。"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"啟用實驗版自由形態視窗的支援功能。"</string> <string name="local_backup_password_title" msgid="3860471654439418822">"桌面電腦備份密碼"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"桌上電腦的完整備份目前未受保護"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"輕按即可變更或移除桌上電腦完整備份的密碼"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"已停用"</string> <string name="night_mode_yes" msgid="2218157265997633432">"永遠開啟"</string> <string name="night_mode_auto" msgid="7508348175804304327">"自動"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView 設置"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"設定 WebView 設置"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"您選擇的 WebView 設定已停用,您必須先啟用此設定才能加以使用。要啟用此設定嗎?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"色彩校正"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"這是一項實驗性功能,可能會影響效能。"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"已由「<xliff:g id="TITLE">%1$s</xliff:g>」覆寫"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"尚餘大約 <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 尚餘大約 <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 後完成充電"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"電量已滿"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"管理員已停用此設定"</string> <string name="home" msgid="8263346537524314127">"主畫面"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>前"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"尚餘 <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index bf7ea4ed573f..ce8303c63519 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"強制允許將應用程式寫入外部儲存空間"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"允許將任何應用程式寫入外部儲存空間 (無論資訊清單值為何)"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"將活動強制設為可調整大小"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"將所有活動設為可配合多重視窗環境調整大小 (無論資訊清單值為何)。"</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"將所有活動設為可配合多重視窗環境調整大小 (無論資訊清單值為何)。"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"啟用自由形式視窗"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"啟用實驗版自由形式視窗的支援功能。"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"啟用實驗版自由形式視窗的支援功能。"</string> <string name="local_backup_password_title" msgid="3860471654439418822">"電腦備份密碼"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"電腦完整備份目前未受保護"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"輕按即可變更或移除電腦完整備份的密碼"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"已停用"</string> <string name="night_mode_yes" msgid="2218157265997633432">"一律開啟"</string> <string name="night_mode_auto" msgid="7508348175804304327">"自動"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView 實作"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"設定 WebView 實作"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"您所選的 WebView 實作已停用,您必須先啟用 WebView 實作才能加以使用。要啟用該 WebView 實作嗎?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"色彩校正"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"這是一項實驗性功能,可能會對效能造成影響。"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"已改為<xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"還剩大約 <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 大約還剩 <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"電力充足"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"已由管理員停用"</string> <string name="home" msgid="8263346537524314127">"主畫面"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>前"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"還剩 <xliff:g id="ID_1">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index c450f7722a45..149011ae4d2a 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -248,9 +248,9 @@ <string name="force_allow_on_external" msgid="3215759785081916381">"Phoqelela ukuvumela izinhlelo zokusebenza ngaphandle"</string> <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Yenza noma uluphi uhlelo lokusebenza lifaneleke ukuthi libhalwe kusitoreji sangaphandle, ngaphandle kwamavelu we-manifest"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Imisebenzi yamandla izonikezwa usayizi omusha"</string> - <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Yenza yonke imisebenzi ibe nosayizi abasha kuwindi lokuningi, ngokunganaki amanani we-manifest."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Yenza yonke imisebenzi ibe nosayizi abasha kumawindi amaningi, ngokunganaki amavelu e-manifest."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Nika amandla amawindi e-freeform"</string> - <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Inika amandla usekelo lwamawindi okuhlola e-freeform."</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Nika amandla usekelo lwe-windows yokuhlola kwe-freeform."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Iphasiwedi yokusekela ngokulondoloza ye-Desktop"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Ukusekela ngokulondoloza okugcwele kwe-Desktop akuvikelekile okwamanje."</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Thepha ukushintsha noma ukususa iphasiwedi yokwenziwa kwezipele ngokugcwele kwideskithophu"</string> @@ -277,6 +277,10 @@ <string name="night_mode_no" msgid="9171772244775838901">"Kukhutshaziwe"</string> <string name="night_mode_yes" msgid="2218157265997633432">"Njalo ivuliwe"</string> <string name="night_mode_auto" msgid="7508348175804304327">"Okuzenzakalelayo"</string> + <!-- no translation found for enable_webview_multiprocess (3405948012467585908) --> + <skip /> + <!-- no translation found for enable_webview_multiprocess_desc (852226124223847283) --> + <skip /> <string name="select_webview_provider_title" msgid="4628592979751918907">"Ukufakwa ke-WebView"</string> <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Sesba ukufakwa kwe-WebView"</string> <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Ukusetshenziswa kwe-WebView okukhethiwe kukhutshaziwe, futhi kuzomele kunikwe amandla ukuze kusetshenziswe, ingabe ufisa ukukunika amandla?"</string> @@ -296,8 +300,7 @@ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Ukulungiswa kombala"</string> <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Lesi sici esesilingo futhi singathinta ukusebenza."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Igitshezwe ngaphezulu yi-<xliff:g id="TITLE">%1$s</xliff:g>"</string> - <!-- no translation found for power_remaining_duration_only (4400068916452346544) --> - <skip /> + <string name="power_remaining_duration_only" msgid="4400068916452346544">"Cishe ngu-<xliff:g id="TIME">%1$s</xliff:g> osele"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - isilinganiso esingu-<xliff:g id="TIME">%2$s</xliff:g> esisele"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze igcwale"</string> @@ -314,8 +317,6 @@ <string name="battery_info_status_full" msgid="2824614753861462808">"Kugcwele"</string> <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Ikhutshazwe umlawuli"</string> <string name="home" msgid="8263346537524314127">"Ekhaya"</string> - <!-- no translation found for charge_length_format (8978516217024434156) --> - <skip /> - <!-- no translation found for remaining_length_format (7886337596669190587) --> - <skip /> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> edlule"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> osele"</string> </resources> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 654b398358c7..57c56847759e 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -778,7 +778,7 @@ <string name="battery_info_status_full">Full</string> <!-- Summary for settings preference disabled by administrator [CHAR LIMIT=50] --> - <string name="disabled_by_admin_summary_text">Disabled by administrator</string> + <string name="disabled_by_admin_summary_text">Controlled by admin</string> <!-- Option in navigation drawer that leads to Settings main screen [CHAR LIMIT=30] --> <string name="home">Home</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java index c44b638cc284..6d29c5f1a98e 100644 --- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java @@ -113,6 +113,12 @@ public class RestrictedLockUtils { return admin; } + public static boolean hasBaseUserRestriction(Context context, + String userRestriction, int userId) { + UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); + return um.hasBaseUserRestriction(userRestriction, UserHandle.of(userId)); + } + /** * Checks if keyguard features are disabled by policy. * diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java index 9bd4eb185bee..227b1e8e1b4d 100644 --- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java +++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java @@ -70,6 +70,12 @@ public class RestrictedPreferenceHelper { } } mAttrUserRestriction = data == null ? null : data.toString(); + // If the system has set the user restriction, then we shouldn't add the padlock. + if (RestrictedLockUtils.hasBaseUserRestriction(mContext, mAttrUserRestriction, + UserHandle.myUserId())) { + mAttrUserRestriction = null; + return; + } final TypedValue useAdminDisabledSummary = attributes.peekValue(R.styleable.RestrictedPreference_useAdminDisabledSummary); diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 7416fb564e27..5b865f97281b 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -40,6 +40,7 @@ <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" /> <uses-permission android:name="android.permission.DISABLE_KEYGUARD" /> + <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" /> <!-- System tool permissions granted to the shell. --> <uses-permission android:name="android.permission.REAL_GET_TASKS" /> <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" /> @@ -109,6 +110,7 @@ <uses-permission android:name="android.permission.GET_APP_OPS_STATS" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" /> + <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" /> <application android:label="@string/app_label" android:forceDeviceEncrypted="true" diff --git a/packages/SystemUI/res/drawable/ic_colorize.xml b/packages/SystemUI/res/drawable/ic_night_mode.xml index 79fd6d907264..caa7a47ee5b4 100644 --- a/packages/SystemUI/res/drawable/ic_colorize.xml +++ b/packages/SystemUI/res/drawable/ic_night_mode.xml @@ -1,5 +1,5 @@ <!-- - Copyright (C) 2015 The Android Open Source Project + Copyright (C) 2016 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. diff --git a/packages/SystemUI/res/drawable/ic_night_mode_disabled.xml b/packages/SystemUI/res/drawable/ic_night_mode_disabled.xml new file mode 100644 index 000000000000..010815a41819 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_night_mode_disabled.xml @@ -0,0 +1,24 @@ +<!-- + Copyright (C) 2016 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24.0dp" + android:height="24.0dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:fillColor="#4DFFFFFF" + android:pathData="M20.71,5.63l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0.0l-3.12,3.12 -1.93,-1.91 -1.41,1.41 1.42,1.42L3.0,16.25L3.0,21.0l4.75,0.0l8.92,-8.92 1.42,1.42 1.41,-1.41 -1.92,-1.92 3.12,-3.12c0.4,0.0 0.4,-1.0 0.01,-1.42zM6.92,19.0L5.0,17.08l8.06,-8.06 1.92,1.92L6.92,19.0z"/> +</vector> diff --git a/packages/SystemUI/res/layout/preference_matrix.xml b/packages/SystemUI/res/layout/calibrate_sliders.xml index 1f6066e5eaf0..0dec8a18caa4 100644 --- a/packages/SystemUI/res/layout/preference_matrix.xml +++ b/packages/SystemUI/res/layout/calibrate_sliders.xml @@ -94,11 +94,4 @@ android:layout_weight="1" /> </LinearLayout> - <Button - android:id="@+id/apply" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="end" - android:text="@string/color_apply" /> - </LinearLayout> diff --git a/packages/SystemUI/res/layout/color_matrix_settings.xml b/packages/SystemUI/res/layout/night_mode_settings.xml index 3725e78cc481..3725e78cc481 100644 --- a/packages/SystemUI/res/layout/color_matrix_settings.xml +++ b/packages/SystemUI/res/layout/night_mode_settings.xml diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml index e550d9c02396..4d0eb96f4eae 100644 --- a/packages/SystemUI/res/layout/notification_guts.xml +++ b/packages/SystemUI/res/layout/notification_guts.xml @@ -126,27 +126,6 @@ android:tint="@color/notification_guts_icon_tint" /> </FrameLayout> - - <RadioGroup - android:id="@+id/apply_to" - android:layout_width="wrap_content" - android:layout_height="wrap_content" > - <RadioButton android:id="@+id/apply_to_topic" - android:layout_width="wrap_content" - android:layout_height="48dp" - style="@style/TextAppearance.NotificationGuts.Primary" - android:visibility="gone" - android:buttonTint="#858383" - /> - <RadioButton android:id="@+id/apply_to_app" - android:layout_width="wrap_content" - android:layout_height="48dp" - android:text="@string/apply_to_app" - style="@style/TextAppearance.NotificationGuts.Primary" - android:visibility="gone" - android:buttonTint="#858383" - /> - </RadioGroup> </LinearLayout> <!-- buttons --> <LinearLayout diff --git a/packages/SystemUI/res/layout/notification_settings_icon_row.xml b/packages/SystemUI/res/layout/notification_settings_icon_row.xml new file mode 100644 index 000000000000..52d07fcc5cb7 --- /dev/null +++ b/packages/SystemUI/res/layout/notification_settings_icon_row.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2016, 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. +--> +<com.android.systemui.statusbar.NotificationSettingsIconRow + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:systemui="http://schemas.android.com/apk/res-auto" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + > + + <com.android.systemui.statusbar.AlphaOptimizedImageView + android:id="@+id/gear_icon" + android:layout_width="@dimen/notification_gear_width" + android:layout_height="@dimen/notification_gear_height" + android:paddingTop="@dimen/notification_gear_top_padding" + android:paddingStart="@dimen/notification_gear_padding" + android:paddingEnd="@dimen/notification_gear_padding" + android:paddingBottom="@dimen/notification_gear_padding" + android:src="@drawable/ic_settings" + android:tint="@color/notification_gear_color" + android:visibility="invisible" + android:alpha="0" + android:background="?android:attr/selectableItemBackgroundBorderless" + /> + +</com.android.systemui.statusbar.NotificationSettingsIconRow>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/qs_paged_page.xml b/packages/SystemUI/res/layout/qs_paged_page.xml index eef08baed736..a246e0dffdd9 100644 --- a/packages/SystemUI/res/layout/qs_paged_page.xml +++ b/packages/SystemUI/res/layout/qs_paged_page.xml @@ -19,4 +19,6 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tile_page" android:layout_width="match_parent" - android:layout_height="wrap_content" /> + android:layout_height="wrap_content" + android:clipChildren="false" + android:clipToPadding="false" /> diff --git a/packages/SystemUI/res/layout/qs_paged_tile_layout.xml b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml index c23c745931c6..9dd3ad284217 100644 --- a/packages/SystemUI/res/layout/qs_paged_tile_layout.xml +++ b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml @@ -18,12 +18,14 @@ <com.android.systemui.qs.PagedTileLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="wrap_content"> + android:layout_height="wrap_content" + android:clipChildren="false" + android:clipToPadding="false"> <FrameLayout android:id="@+id/page_decor" android:layout_width="wrap_content" - android:layout_height="wrap_content" + android:layout_height="48dp" android:layout_gravity="bottom"> <com.android.systemui.qs.PageIndicator diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml index 9f90af231b20..b8f10dbec87c 100644 --- a/packages/SystemUI/res/layout/qs_panel.xml +++ b/packages/SystemUI/res/layout/qs_panel.xml @@ -26,7 +26,9 @@ android:layout_marginTop="@dimen/status_bar_header_height" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingBottom="8dp" /> + android:paddingBottom="8dp" + android:clipToPadding="false" + android:clipChildren="false" /> <include layout="@layout/quick_status_bar_expanded_header" /> diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml index 62fdd4264841..c4c45bb0be22 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_row.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml @@ -23,6 +23,14 @@ android:clickable="true" > + <ViewStub + android:layout="@layout/notification_settings_icon_row" + android:id="@+id/settings_icon_row_stub" + android:inflatedId="@+id/notification_settings_icon_row" + android:layout_width="wrap_content" + android:layout_height="match_parent" + /> + <com.android.systemui.statusbar.NotificationBackgroundView android:id="@+id/backgroundNormal" android:layout_width="match_parent" diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 4cd920a86733..8f69bbb16000 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -102,6 +102,9 @@ <!-- The color of the circle around the primary user in the user switcher --> <color name="current_user_border_color">@color/system_accent_color</color> + <!-- The color of the gear shown behind a notification --> + <color name="notification_gear_color">#ff757575</color> + <!-- The "inside" of a notification, reached via longpress --> <color name="notification_guts_bg_color">#eeeeee</color> <color name="notification_guts_slider_color">@*android:color/material_deep_teal_500</color> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index b8044ba53db8..ee61e00225a6 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -58,7 +58,7 @@ <item name="status_bar_icon_scale_factor" format="float" type="dimen">1.0</item> <!-- Height of a small notification in the status bar--> - <dimen name="notification_min_height">84dp</dimen> + <dimen name="notification_min_height">86dp</dimen> <!-- Height of a small notification in the status bar which was used before android N --> <dimen name="notification_min_height_legacy">64dp</dimen> @@ -78,6 +78,18 @@ <!-- Minimum layouted height of a notification in the statusbar--> <dimen name="min_notification_layout_height">48dp</dimen> + <!-- Width of the space containing the gear icon behind a notification --> + <dimen name="notification_gear_width">64dp</dimen> + + <!-- Height of the space containing the gear icon behind a notification --> + <dimen name="notification_gear_height">74dp</dimen> + + <!-- The space above the gear icon displayed behind a notification --> + <dimen name="notification_gear_top_padding">30dp</dimen> + + <!-- The space on either side and below the gear icon displayed behind a notification --> + <dimen name="notification_gear_padding">20dp</dimen> + <!-- size at which Notification icons will be drawn in the status bar --> <dimen name="status_bar_icon_drawing_size">17dip</dimen> @@ -166,7 +178,7 @@ <dimen name="qs_date_alarm_anim_translation">26dp</dimen> <dimen name="qs_date_collapsed_text_size">14sp</dimen> <dimen name="qs_date_text_size">16sp</dimen> - <dimen name="qs_header_gear_translation">120dp</dimen> + <dimen name="qs_header_gear_translation">150dp</dimen> <dimen name="qs_page_indicator_size">12dp</dimen> <dimen name="qs_tile_icon_size">24dp</dimen> <dimen name="qs_tile_text_size">12sp</dimen> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 6135dc624906..0bd7c4e18a67 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1234,29 +1234,43 @@ <!-- Notification: Control panel: Label for button that dismisses control panel. [CHAR LIMIT=NONE] --> <string name="notification_done">Done</string> - <!-- Label for no color transform [CHAR LIMIT=30] --> - <string name="color_matrix_none">Normal colors</string> + <!-- SysUI Tuner: Color and appearance screen title [CHAR LIMIT=50] --> + <string name="color_and_appearance">Color and appearance</string> - <!-- Label for night color transform [CHAR LIMIT=30] --> - <string name="color_matrix_night">Night colors</string> + <!-- SysUI Tuner: Name of the night mode feature [CHAR LIMIT=30] --> + <string name="night_mode">Night mode</string> - <!-- Label for custom color transform [CHAR LIMIT=30] --> - <string name="color_matrix_custom">Custom colors</string> + <!-- SysUI Tuner: Name of calibrate display dialog [CHAR LIMIT=30] --> + <string name="calibrate_display">Calibrate display</string> - <!-- Label for auto color transforms [CHAR LIMIT=30] --> - <string name="color_matrix_auto">Auto</string> + <!-- SysUI Tuner: Summary of night mode when its on [CHAR LIMIT=NONE] --> + <string name="night_mode_on">On</string> - <!-- Label for unknown color transform [CHAR LIMIT=30] --> - <string name="color_matrix_unknown">Unknown colors</string> + <!-- SysUI Tuner: Summary of night mode when its off [CHAR LIMIT=NONE] --> + <string name="night_mode_off">Off</string> - <!-- Title for color transform [CHAR LIMIT=30] --> - <string name="color_transform">Color modification</string> + <!-- SysUI Tuner: Label for switch to turn on night mode automatically [CHAR LIMIT=50] --> + <string name="turn_on_automatically">Turn on automatically</string> - <!-- Title for setting to show Quick Settings tile [CHAR LIMIT=60] --> - <string name="color_matrix_show_qs">Show Quick Settings tile</string> + <!-- SysUI Tuner: Summary for switch to turn on night mode automatically [CHAR LIMIT=NONE] --> + <string name="turn_on_auto_summary">Switch into Night Mode as appropriate for location and time of day</string> - <!-- Title for switch to enable custom color transform [CHAR LIMIT=60] --> - <string name="color_enable_custom">Enable custom transform</string> + <!-- SysUI Tuner: Label for section controlling what night mode does [CHAR LIMIT=60] --> + <string name="when_night_mode_on">When Night Mode is on</string> + + <!-- SysUI Tuner: Switch controlling whether dark theme is turned on with night mode [CHAR LIMIT=45] --> + <string name="use_dark_theme">Use dark theme for Android OS</string> + + <!-- SysUI Tuner: Switch controlling whether tint is changed with night mode [CHAR LIMIT=45] --> + <string name="adjust_tint">Adjust tint</string> + + <!-- SysUI Tuner: Switch controlling whether brightness is changed with night mode [CHAR LIMIT=45] --> + <string name="adjust_brightness">Adjust brightness</string> + + <!-- SysUI Tuner: Disclaimer about using dark theme with night mode [CHAR LIMIT=NONE] --> + <string name="night_mode_disclaimer">The dark theme is applied to + core areas of Android OS that are normally displayed in a light theme, + such as Settings and notifications.</string> <!-- Button to apply settings [CHAR LIMIT=30] --> <string name="color_apply">Apply</string> @@ -1295,15 +1309,14 @@ <string name="keyboard_shortcut_group_system_back">Back</string> <!-- SysUI Tuner: Option to show full do not disturb panel in volume [CHAR LIMIT=60] --> - <string name="tuner_full_zen_title">Show do not disturb in volume</string> - <!-- SysUI Tuner: Summary of option to show full do not disturb panel in volume [CHAR LIMIT=NONE] --> - <string name="tuner_full_zen_summary">Allow full control of do not disturb in the volume dialog.</string> + <string name="tuner_full_zen_title">Show with volume controls</string> - <!-- SysUI Tuner: Label for screen about volume and do not disturb settings [CHAR LIMIT=60] --> - <string name="volume_and_do_not_disturb">Volume and Do not disturb</string> + <!-- SysUI Tuner: Label for screen about do not disturb settings [CHAR LIMIT=60] --> + <string name="volume_and_do_not_disturb">Do not disturb</string> - <!-- SysUI Tuner: Switch to control volume down behavior [CHAR LIMIT=60] --> - <string name="volume_down_silent">Enter do not disturb on volume down</string> + <!-- SysUI Tuner: Switch to control whether volume buttons enter/exit do + not disturb [CHAR LIMIT=60] --> + <string name="volume_dnd_silent">Volume buttons shortcut</string> <!-- SysUI Tuner: Switch to control volume up behavior [CHAR LIMIT=60] --> <string name="volume_up_silent">Exit do not disturb on volume up</string> @@ -1323,9 +1336,6 @@ <!-- Accessibility description of headset icon [CHAR LIMIT=NONE] --> <string name="accessibility_status_bar_headset">Headset connected</string> - <!-- Explanation of the status bar section of the tuner [CHAR LIMIT=NONE] --> - <string name="tuner_status_bar_explanation">Enable or disable icons from being shown in the status bar.</string> - <!-- Label for quick settings tile for data saver [CHAR LIMIT=30] --> <string name="data_saver">Data Saver</string> @@ -1338,6 +1348,9 @@ <!-- Label for feature switch [CHAR LIMIT=30] --> <string name="switch_bar_on">On</string> + <!-- Label for feature switch [CHAR LIMIT=30] --> + <string name="switch_bar_off">Off</string> + <!-- SysUI Tuner: Button that leads to the navigation bar customization screen [CHAR LIMIT=60] --> <string name="nav_bar">Navigation bar</string> @@ -1398,4 +1411,21 @@ <!-- Button to edit the tile ordering of quick settings [CHAR LIMIT=60] --> <string name="qs_edit">Edit</string> + <!-- SysUI Tuner: Options for how clock is displayed [CHAR LIMIT=NONE] --> + <string name="tuner_time">Time</string> + + <!-- SysUI Tuner: Options for how clock is displayed [CHAR LIMIT=NONE] --> + <string-array name="clock_options"> + <item>Show hours, minutes, and seconds</item> + <item>Show hours and minutes (default)</item> + <item>Don\'t show this icon</item> + </string-array> + + <!-- SysUI Tuner: Options for how battery is displayed [CHAR LIMIT=NONE] --> + <string-array name="battery_options"> + <item>Always show percentage</item> + <item>Show percentage when charging (default)</item> + <item>Don\'t show this icon</item> + </string-array> + </resources> diff --git a/packages/SystemUI/res/xml/color_and_appearance.xml b/packages/SystemUI/res/xml/color_and_appearance.xml new file mode 100644 index 000000000000..21f890eb058d --- /dev/null +++ b/packages/SystemUI/res/xml/color_and_appearance.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2016 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. +--> + +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:sysui="http://schemas.android.com/apk/res-auto" + android:title="@string/color_and_appearance"> + + <Preference + android:key="night_mode" + android:title="@string/night_mode" + android:fragment="com.android.systemui.tuner.NightModeFragment" /> + + <com.android.systemui.tuner.CalibratePreference + android:key="calibrate" + android:title="@string/calibrate_display" /> + +</PreferenceScreen> diff --git a/packages/SystemUI/res/xml/night_mode.xml b/packages/SystemUI/res/xml/night_mode.xml new file mode 100644 index 000000000000..d5f5333a513b --- /dev/null +++ b/packages/SystemUI/res/xml/night_mode.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2016 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. +--> + +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:sysui="http://schemas.android.com/apk/res-auto" + android:title="@string/night_mode"> + + <SwitchPreference + android:key="auto" + android:title="@string/turn_on_automatically" + android:summary="@string/turn_on_auto_summary" /> + + <PreferenceCategory + android:title="@string/when_night_mode_on"> + + <SwitchPreference + android:key="dark_theme" + android:title="@string/use_dark_theme" /> + + <SwitchPreference + android:key="adjust_tint" + android:title="@string/adjust_tint" /> + + <SwitchPreference + android:key="adjust_brightness" + android:title="@string/adjust_brightness" /> + + </PreferenceCategory> + + <Preference + android:selectable="false" + android:summary="@string/night_mode_disclaimer" /> + +</PreferenceScreen> diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml index 39281bcb0809..023a3f047755 100644 --- a/packages/SystemUI/res/xml/tuner_prefs.xml +++ b/packages/SystemUI/res/xml/tuner_prefs.xml @@ -18,19 +18,10 @@ xmlns:sysui="http://schemas.android.com/apk/res-auto" android:title="@string/system_ui_tuner"> - <com.android.systemui.tuner.TunerSwitch - android:key="qs_show_brightness" - android:title="@string/show_brightness" - sysui:defValue="true" /> - <PreferenceScreen android:key="status_bar" android:title="@string/status_bar" > - <Preference - android:selectable="false" - android:summary="@string/tuner_status_bar_explanation" /> - <com.android.systemui.tuner.StatusBarSwitch android:key="rotate" android:title="@string/status_bar_settings_auto_rotation" /> @@ -91,9 +82,10 @@ <!-- other weird signal stuff --> - <com.android.systemui.tuner.StatusBarSwitch - android:key="battery" - android:title="@string/battery" /> + <com.android.systemui.tuner.BatteryPreference + android:title="@string/battery" + android:summary="%s" + android:entries="@array/battery_options" /> <com.android.systemui.tuner.StatusBarSwitch android:key="alarm_clock" @@ -101,49 +93,17 @@ <!-- secure --> - <com.android.systemui.tuner.StatusBarSwitch - android:key="clock" - android:title="@string/clock" /> - - </PreferenceScreen> - - - <PreferenceScreen - android:key="overview" - android:title="@string/overview" > - - <com.android.systemui.tuner.TunerSwitch - android:key="overview_disable_fast_toggle_via_button" - android:title="@string/overview_disable_fast_toggle_via_button" - android:summary="@string/overview_disable_fast_toggle_via_button_desc" /> - - <com.android.systemui.tuner.TunerSwitch - android:key="overview_nav_bar_gesture" - android:title="@string/overview_nav_bar_gesture" - android:summary="@string/overview_nav_bar_gesture_desc" /> + <com.android.systemui.tuner.ClockPreference + android:title="@string/tuner_time" + android:summary="%s" + android:entries="@array/clock_options" /> </PreferenceScreen> - <SwitchPreference - android:key="battery_pct" - android:title="@string/show_battery_percentage" - android:summary="@string/show_battery_percentage_summary" - android:persistent="false" /> - - <com.android.systemui.tuner.TunerSwitch - android:key="clock_seconds" - android:title="@string/clock_seconds" - android:summary="@string/clock_seconds_desc" /> - - <Preference - android:key="demo_mode" - android:title="@string/demo_mode" - android:fragment="com.android.systemui.tuner.DemoModeFragment" /> - <Preference android:key="color_transform" - android:title="@string/color_transform" - android:fragment="com.android.systemui.tuner.ColorMatrixFragment" /> + android:title="@string/color_and_appearance" + android:fragment="com.android.systemui.tuner.ColorAndAppearanceFragment" /> <PreferenceScreen android:key="volume_and_do_not_disturb" @@ -151,17 +111,11 @@ <com.android.systemui.tuner.TunerSwitch android:key="sysui_show_full_zen" - android:title="@string/tuner_full_zen_title" - android:summary="@string/tuner_full_zen_summary" /> - - <com.android.systemui.tuner.TunerSwitch - android:key="sysui_volume_down_silent" - android:title="@string/volume_down_silent" - sysui:defValue="true" /> + android:title="@string/tuner_full_zen_title" /> <com.android.systemui.tuner.TunerSwitch - android:key="sysui_volume_up_silent" - android:title="@string/volume_up_silent" + android:key="sysui_volume_down_silent,sysui_volume_up_silent" + android:title="@string/volume_dnd_silent" sysui:defValue="true" /> </PreferenceScreen> @@ -171,6 +125,22 @@ android:title="@string/nav_bar" android:fragment="com.android.systemui.tuner.NavBarTuner" /> + <PreferenceScreen + android:key="overview" + android:title="@string/overview" > + + <com.android.systemui.tuner.TunerSwitch + android:key="overview_disable_fast_toggle_via_button" + android:title="@string/overview_disable_fast_toggle_via_button" + android:summary="@string/overview_disable_fast_toggle_via_button_desc" /> + + <com.android.systemui.tuner.TunerSwitch + android:key="overview_nav_bar_gesture" + android:title="@string/overview_nav_bar_gesture" + android:summary="@string/overview_nav_bar_gesture_desc" /> + + </PreferenceScreen> + <!-- Warning, this goes last. --> <Preference android:summary="@string/tuner_persistent_warning" diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java index 33b43fec6fc1..33f3c30fcc12 100644 --- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -69,9 +69,9 @@ public class SwipeHelper implements Gefingerpoken { private float mPerpendicularInitialTouchPos; private boolean mDragging; private View mCurrView; - private View mCurrAnimView; private boolean mCanCurrViewBeDimissed; private float mDensityScale; + private float mTranslation = 0; private boolean mLongPressSent; private LongPressListener mLongPressListener; @@ -121,7 +121,7 @@ public class SwipeHelper implements Gefingerpoken { return mSwipeDirection == X ? ev.getY() : ev.getX(); } - private float getTranslation(View v) { + protected float getTranslation(View v) { return mSwipeDirection == X ? v.getTranslationX() : v.getTranslationY(); } @@ -130,7 +130,7 @@ public class SwipeHelper implements Gefingerpoken { vt.getYVelocity(); } - private ObjectAnimator createTranslationAnimation(View v, float newPos) { + protected ObjectAnimator createTranslationAnimation(View v, float newPos) { ObjectAnimator anim = ObjectAnimator.ofFloat(v, mSwipeDirection == X ? View.TRANSLATION_X : View.TRANSLATION_Y, newPos); return anim; @@ -141,7 +141,17 @@ public class SwipeHelper implements Gefingerpoken { vt.getXVelocity(); } - private void setTranslation(View v, float translate) { + protected Animator getViewTranslationAnimator(View v, float target, + AnimatorUpdateListener listener) { + ObjectAnimator anim = createTranslationAnimation(v, target); + anim.addUpdateListener(listener); + return anim; + } + + protected void setTranslation(View v, float translate) { + if (v == null) { + return; + } if (mSwipeDirection == X) { v.setTranslationX(translate); } else { @@ -237,15 +247,16 @@ public class SwipeHelper implements Gefingerpoken { mTouchAboveFalsingThreshold = false; mDragging = false; mLongPressSent = false; - mCurrView = mCallback.getChildAtPosition(ev); mVelocityTracker.clear(); + mCurrView = mCallback.getChildAtPosition(ev); + if (mCurrView != null) { - mCurrAnimView = mCallback.getChildContentView(mCurrView); + onDownUpdate(mCurrView); mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView); mVelocityTracker.addMovement(ev); mInitialTouchPos = getPos(ev); mPerpendicularInitialTouchPos = getPerpendicularPos(ev); - + mTranslation = getTranslation(mCurrView); if (mLongPressListener != null) { if (mWatchLongPress == null) { mWatchLongPress = new Runnable() { @@ -268,7 +279,6 @@ public class SwipeHelper implements Gefingerpoken { } mHandler.postDelayed(mWatchLongPress, mLongPressTimeout); } - } break; @@ -283,8 +293,8 @@ public class SwipeHelper implements Gefingerpoken { && Math.abs(delta) > Math.abs(deltaPerpendicular)) { mCallback.onBeginDrag(mCurrView); mDragging = true; - mInitialTouchPos = getPos(ev) - getTranslation(mCurrAnimView); - + mInitialTouchPos = getPos(ev); + mTranslation = getTranslation(mCurrView); removeLongPressCallback(); } } @@ -295,7 +305,6 @@ public class SwipeHelper implements Gefingerpoken { final boolean captured = (mDragging || mLongPressSent); mDragging = false; mCurrView = null; - mCurrAnimView = null; mLongPressSent = false; removeLongPressCallback(); if (captured) return true; @@ -320,12 +329,11 @@ public class SwipeHelper implements Gefingerpoken { * @param useAccelerateInterpolator Should an accelerating Interpolator be used * @param fixedDuration If not 0, this exact duration will be taken */ - public void dismissChild(final View view, float velocity, final Runnable endAction, + public void dismissChild(final View animView, float velocity, final Runnable endAction, long delay, boolean useAccelerateInterpolator, long fixedDuration) { - final View animView = mCallback.getChildContentView(view); - final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view); + final boolean canBeDismissed = mCallback.canChildBeDismissed(animView); float newPos; - boolean isLayoutRtl = view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; + boolean isLayoutRtl = animView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; if (velocity < 0 || (velocity == 0 && getTranslation(animView) < 0) @@ -355,7 +363,13 @@ public class SwipeHelper implements Gefingerpoken { if (!mDisableHwLayers) { animView.setLayerType(View.LAYER_TYPE_HARDWARE, null); } - ObjectAnimator anim = createTranslationAnimation(animView, newPos); + AnimatorUpdateListener updateListener = new AnimatorUpdateListener() { + public void onAnimationUpdate(ValueAnimator animation) { + onTranslationUpdate(animView, (float) animation.getAnimatedValue(), canBeDismissed); + } + }; + + Animator anim = getViewTranslationAnimator(animView, newPos, updateListener); if (useAccelerateInterpolator) { anim.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN); } else { @@ -367,8 +381,8 @@ public class SwipeHelper implements Gefingerpoken { } anim.addListener(new AnimatorListenerAdapter() { public void onAnimationEnd(Animator animation) { - updateSwipeProgressFromOffset(animView, canAnimViewBeDismissed); - mCallback.onChildDismissed(view); + updateSwipeProgressFromOffset(animView, canBeDismissed); + mCallback.onChildDismissed(animView); if (endAction != null) { endAction.run(); } @@ -377,11 +391,6 @@ public class SwipeHelper implements Gefingerpoken { } } }); - anim.addUpdateListener(new AnimatorUpdateListener() { - public void onAnimationUpdate(ValueAnimator animation) { - updateSwipeProgressFromOffset(animView, canAnimViewBeDismissed); - } - }); prepareDismissAnimation(animView, anim); anim.start(); } @@ -393,21 +402,21 @@ public class SwipeHelper implements Gefingerpoken { // Do nothing } - public void snapChild(final View view, float velocity) { - final View animView = mCallback.getChildContentView(view); - final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(animView); - ObjectAnimator anim = createTranslationAnimation(animView, 0); - int duration = SNAP_ANIM_LEN; - anim.setDuration(duration); - anim.addUpdateListener(new AnimatorUpdateListener() { + public void snapChild(final View animView, final float targetLeft, float velocity) { + final boolean canBeDismissed = mCallback.canChildBeDismissed(animView); + AnimatorUpdateListener updateListener = new AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { - updateSwipeProgressFromOffset(animView, canAnimViewBeDismissed); + onTranslationUpdate(animView, (float) animation.getAnimatedValue(), canBeDismissed); } - }); + }; + + Animator anim = getViewTranslationAnimator(animView, targetLeft, updateListener); + int duration = SNAP_ANIM_LEN; + anim.setDuration(duration); anim.addListener(new AnimatorListenerAdapter() { public void onAnimationEnd(Animator animator) { - updateSwipeProgressFromOffset(animView, canAnimViewBeDismissed); - mCallback.onChildSnappedBack(animView); + updateSwipeProgressFromOffset(animView, canBeDismissed); + mCallback.onChildSnappedBack(animView, targetLeft); } }); prepareSnapBackAnimation(animView, anim); @@ -421,6 +430,28 @@ public class SwipeHelper implements Gefingerpoken { // Do nothing } + /** + * Called when there's a down event. + */ + public void onDownUpdate(View currView) { + // Do nothing + } + + /** + * Called on a move event. + */ + protected void onMoveUpdate(View view, float totalTranslation, float delta) { + // Do nothing + } + + /** + * Called in {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)} when the current + * view is being animated to dismiss or snap. + */ + public void onTranslationUpdate(View animView, float value, boolean canBeDismissed) { + updateSwipeProgressFromOffset(animView, canBeDismissed); + } + public boolean onTouchEvent(MotionEvent ev) { if (mLongPressSent) { return true; @@ -456,17 +487,18 @@ public class SwipeHelper implements Gefingerpoken { // don't let items that can't be dismissed be dragged more than // maxScrollDistance if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) { - float size = getSize(mCurrAnimView); - float maxScrollDistance = 0.15f * size; + float size = getSize(mCurrView); + float maxScrollDistance = 0.25f * size; if (absDelta >= size) { delta = delta > 0 ? maxScrollDistance : -maxScrollDistance; } else { delta = maxScrollDistance * (float) Math.sin((delta/size)*(Math.PI/2)); } } - setTranslation(mCurrAnimView, delta); - updateSwipeProgressFromOffset(mCurrAnimView, mCanCurrViewBeDimissed); + setTranslation(mCurrView, mTranslation + delta); + updateSwipeProgressFromOffset(mCurrView, mCanCurrViewBeDimissed); + onMoveUpdate(mCurrView, mTranslation + delta, delta); } break; case MotionEvent.ACTION_UP: @@ -478,12 +510,13 @@ public class SwipeHelper implements Gefingerpoken { float velocity = getVelocity(mVelocityTracker); float perpendicularVelocity = getPerpendicularVelocity(mVelocityTracker); + float translation = getTranslation(mCurrView); // Decide whether to dismiss the current view boolean childSwipedFarEnough = DISMISS_IF_SWIPED_FAR_ENOUGH && - Math.abs(getTranslation(mCurrAnimView)) > 0.4 * getSize(mCurrAnimView); + Math.abs(translation) > 0.4 * getSize(mCurrView); boolean childSwipedFastEnough = (Math.abs(velocity) > escapeVelocity) && (Math.abs(velocity) > Math.abs(perpendicularVelocity)) && - (velocity > 0) == (getTranslation(mCurrAnimView) > 0); + (velocity > 0) == (translation > 0); boolean falsingDetected = mCallback.isAntiFalsingNeeded(); if (mFalsingManager.isClassiferEnabled()) { @@ -502,7 +535,7 @@ public class SwipeHelper implements Gefingerpoken { } else { // snappity mCallback.onDragCancelled(mCurrView); - snapChild(mCurrView, velocity); + snapChild(mCurrView, 0 /* leftTarget */, velocity); } } break; @@ -518,8 +551,6 @@ public class SwipeHelper implements Gefingerpoken { public interface Callback { View getChildAtPosition(MotionEvent ev); - View getChildContentView(View v); - boolean canChildBeDismissed(View v); boolean isAntiFalsingNeeded(); @@ -530,7 +561,13 @@ public class SwipeHelper implements Gefingerpoken { void onDragCancelled(View v); - void onChildSnappedBack(View animView); + /** + * Called when the child is snapped to a position. + * + * @param animView the view that was snapped. + * @param targetLeft the left position the view was snapped to. + */ + void onChildSnappedBack(View animView, float targetLeft); /** * Updates the swipe progress on a child. diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java index 8e9857d27f74..0915ee1c1745 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java +++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java @@ -27,6 +27,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { private int mNumPages; private View mDecorGroup; + private PageListener mPageListener; public PagedTileLayout(Context context, AttributeSet attrs) { super(context, attrs); @@ -36,10 +37,14 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { public void onPageSelected(int position) { if (mPageIndicator == null) return; mPageIndicator.setLocation(position); + if (mPageListener != null) { + mPageListener.onPageChanged(position); + } } @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + public void onPageScrolled(int position, float positionOffset, + int positionOffsetPixels) { if (mPageIndicator == null) return; mPageIndicator.setLocation(position + positionOffset); } @@ -80,6 +85,10 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { } } + public void setPageListener(PageListener listener) { + mPageListener = listener; + } + private void postDistributeTiles() { removeCallbacks(mDistribute); post(mDistribute); @@ -198,4 +207,8 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { return view == object; } }; + + public interface PageListener { + void onPageChanged(int page); + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java new file mode 100644 index 000000000000..6479b0ce6833 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2016 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.qs; + +import android.util.Log; +import android.view.View; +import android.view.View.OnLayoutChangeListener; +import android.view.ViewGroup; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.PathInterpolator; +import android.widget.TextView; +import com.android.systemui.Interpolators; +import com.android.systemui.qs.PagedTileLayout.PageListener; +import com.android.systemui.qs.QSPanel.QSTileLayout; +import com.android.systemui.qs.QSTile.Host.Callback; +import com.android.systemui.qs.TouchAnimator.Builder; +import com.android.systemui.qs.TouchAnimator.Listener; +import com.android.systemui.statusbar.phone.QSTileHost; + +import java.util.ArrayList; +import java.util.Collection; + +public class QSAnimator implements Callback, PageListener, Listener, OnLayoutChangeListener { + + private static final String TAG = "QSAnimator"; + + public static final PathInterpolator TRANSLATION_Y_INTERPOLATOR = + new PathInterpolator(.1f, .3f, 1, 1); + + public static final float EXPANDED_TILE_DELAY = .7f; + + private final ArrayList<View> mAllViews = new ArrayList<>(); + private final QuickQSPanel mQuickQsPanel; + private final QSPanel mQsPanel; + private final QSContainer mQsContainer; + + private boolean mOnFirstPage = true; + private TouchAnimator mFirstPageAnimator; + private TouchAnimator mFirstPageDelayedAnimator; + private TouchAnimator mTranslationYAnimator; + private TouchAnimator mNonfirstPageAnimator; + + public QSAnimator(QSContainer container, QuickQSPanel quickPanel, QSPanel panel) { + mQsContainer = container; + mQuickQsPanel = quickPanel; + mQsPanel = panel; + mQuickQsPanel.addOnLayoutChangeListener(this); + mQsPanel.addOnLayoutChangeListener(this); + QSTileLayout tileLayout = mQsPanel.getTileLayout(); + if (tileLayout instanceof PagedTileLayout) { + ((PagedTileLayout) tileLayout).setPageListener(this); + } else { + Log.w(TAG, "QS Not using page layout"); + } + } + + public void setHost(QSTileHost qsh) { + qsh.addCallback(this); + } + + @Override + public void onPageChanged(int page) { + mOnFirstPage = page == 0; + if (!mOnFirstPage) { + clearAnimationState(); + } + } + + private void updateAnimators() { + TouchAnimator.Builder firstPageBuilder = new Builder(); + TouchAnimator.Builder translationYBuilder = new Builder(); + TouchAnimator.Builder firstPageDelayedBuilder = new Builder(); + Collection<QSTile<?>> tiles = mQsPanel.getHost().getTiles(); + int count = 0; + int[] loc1 = new int[2]; + int[] loc2 = new int[2]; + firstPageDelayedBuilder.setStartDelay(EXPANDED_TILE_DELAY); + firstPageBuilder.setListener(this); + translationYBuilder.setInterpolator(TRANSLATION_Y_INTERPOLATOR); + mAllViews.clear(); + for (QSTile<?> tile : tiles) { + QSTileBaseView tileView = mQsPanel.getTileView(tile); + final TextView label = ((QSTileView) tileView).getLabel(); + if (count++ < 5) { + // Quick tiles. + QSTileBaseView quickTileView = mQuickQsPanel.getTileView(tile); + final View tileIcon = tileView.getIcon(); + + getRelativePosition(loc1, quickTileView.getIcon(), mQsContainer); + getRelativePosition(loc2, tileIcon, mQsContainer); + final int xDiff = loc2[0] - loc1[0]; + final int yDiff = loc2[1] - loc1[1]; + // Move the quick tile right from its location to the new one. + firstPageBuilder.addFloat(quickTileView, "translationX", 0, xDiff); + translationYBuilder.addFloat(quickTileView, "translationY", 0, yDiff); + + // Counteract the parent translation on the tile. So we have a static base to + // animate off from. + firstPageBuilder.addFloat(tileView, "translationY", mQsPanel.getHeight(), 0); + + // Move the real tile's icon and label from the quick tile position to its final + // location. + firstPageBuilder.addFloat(tileIcon, "translationX", -xDiff, 0); + translationYBuilder.addFloat(tileIcon, "translationY", -yDiff, 0); + firstPageBuilder.addFloat(label, "translationX", -xDiff, 0); + translationYBuilder.addFloat(label, "translationY", -yDiff, 0); + + // Fade in the label as we reach the final position. + firstPageDelayedBuilder.addFloat(label, "alpha", 0, 1); + mAllViews.add(quickTileView); + } else { + firstPageDelayedBuilder.addFloat(tileView, "alpha", 0, 1); + } + mAllViews.add(tileView); + mAllViews.add(label); + } + mFirstPageAnimator = firstPageBuilder.build(); + mFirstPageDelayedAnimator = firstPageDelayedBuilder.build(); + mTranslationYAnimator = translationYBuilder.build(); + mNonfirstPageAnimator = new TouchAnimator.Builder() + .addFloat(mQuickQsPanel, "alpha", 1, 0) + .setEndDelay(.5f) + .build(); + } + + private void getRelativePosition(int[] loc1, View view, View parent) { + loc1[0] = 0 + view.getWidth() / 2; + loc1[1] = 0; + getRelativePositionInt(loc1, view, parent); + } + + private void getRelativePositionInt(int[] loc1, View view, View parent) { + if(view == parent || view == null) return; + loc1[0] += view.getLeft(); + loc1[1] += view.getTop(); + getRelativePositionInt(loc1, (View) view.getParent(), parent); + } + + public void setPosition(float position) { + if (mFirstPageAnimator == null) return; + if (mOnFirstPage) { + mQuickQsPanel.setAlpha(1); + mFirstPageAnimator.setPosition(position); + mFirstPageDelayedAnimator.setPosition(position); + mTranslationYAnimator.setPosition(position); + } else { + mNonfirstPageAnimator.setPosition(position); + } + } + + @Override + public void onAnimationAtStart() { + + } + + @Override + public void onAnimationAtEnd() { + mQuickQsPanel.setVisibility(View.INVISIBLE); + } + + @Override + public void onAnimationStarted() { + mQuickQsPanel.setVisibility(View.VISIBLE); + } + + private void clearAnimationState() { + final int N = mAllViews.size(); + mQuickQsPanel.setAlpha(0); + for (int i = 0; i < N; i++) { + View v = mAllViews.get(i); + v.setAlpha(1); + v.setTranslationX(1); + v.setTranslationY(1); + } + } + + @Override + public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, + int oldTop, int oldRight, int oldBottom) { + updateAnimators(); + } + + @Override + public void onTilesChanged() { + // Give the QS panels a moment to generate their new tiles, then create all new animators + // hooked up to the new views. + mQsPanel.post(mUpdateAnimators); + } + + private Runnable mUpdateAnimators = new Runnable() { + @Override + public void run() { + updateAnimators(); + } + }; +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java index 34dfd6c55abd..c59da8d8baf7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java @@ -27,6 +27,7 @@ import android.widget.FrameLayout; import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.statusbar.phone.BaseStatusBarHeader; +import com.android.systemui.statusbar.phone.QSTileHost; import com.android.systemui.statusbar.stack.StackStateAnimator; /** @@ -49,6 +50,7 @@ public class QSContainer extends FrameLayout { private boolean mStackScrollerOverscrolling; private long mDelay; + private QSAnimator mQSAnimator; public QSContainer(Context context, AttributeSet attrs) { super(context, attrs); @@ -61,6 +63,23 @@ public class QSContainer extends FrameLayout { mQSDetail = (QSDetail) findViewById(R.id.qs_detail); mQSDetail.setQsPanel(mQSPanel); mHeader = (BaseStatusBarHeader) findViewById(R.id.header); + mQSAnimator = new QSAnimator(this, (QuickQSPanel) mHeader.findViewById(R.id.quick_qs_panel), + mQSPanel); + } + + public void setHost(QSTileHost qsh) { + mQSPanel.setHost(qsh); + mHeader.setQSPanel(mQSPanel); + mQSDetail.setHost(qsh); + mQSAnimator.setHost(qsh); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // Since we control our own bottom, be whatever size we want. + // Otherwise the QSPanel ends up with 0 height when the window is only the + // size of the status bar. + super.onMeasure(widthMeasureSpec, MeasureSpec.UNSPECIFIED); } @Override @@ -163,6 +182,7 @@ public class QSContainer extends FrameLayout { mHeader.setExpansion(mKeyguardShowing ? 1 : expansion); mQSPanel.setTranslationY(translationScaleY * mQSPanel.getHeight()); mQSDetail.setFullyExpanded(expansion == 1); + mQSAnimator.setPosition(expansion); updateBottom(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 53abe37d4752..30a985052bc2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -25,7 +25,6 @@ import android.os.Message; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; -import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import com.android.internal.logging.MetricsLogger; @@ -45,7 +44,7 @@ import java.util.ArrayList; import java.util.Collection; /** View that represents the quick settings tile panel. **/ -public class QSPanel extends FrameLayout implements Tunable { +public class QSPanel extends LinearLayout implements Tunable { public static final String QS_SHOW_BRIGHTNESS = "qs_show_brightness"; @@ -66,7 +65,6 @@ public class QSPanel extends FrameLayout implements Tunable { protected QSFooter mFooter; private boolean mGridContentVisible = true; - protected LinearLayout mQsContainer; protected QSTileLayout mTileLayout; private QSCustomizer mCustomizePanel; @@ -80,20 +78,15 @@ public class QSPanel extends FrameLayout implements Tunable { super(context, attrs); mContext = context; - - mQsContainer = new LinearLayout(mContext); - mQsContainer.setOrientation(LinearLayout.VERTICAL); - mQsContainer.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, - LayoutParams.WRAP_CONTENT)); - addView(mQsContainer); + setOrientation(VERTICAL); mBrightnessView = LayoutInflater.from(context).inflate( R.layout.quick_settings_brightness_dialog, this, false); - mQsContainer.addView(mBrightnessView); + addView(mBrightnessView); mTileLayout = (QSTileLayout) LayoutInflater.from(mContext).inflate( - R.layout.qs_paged_tile_layout, mQsContainer, false); - mQsContainer.addView((View) mTileLayout); + R.layout.qs_paged_tile_layout, this, false); + addView((View) mTileLayout); findViewById(android.R.id.edit).setOnClickListener(new OnClickListener() { @Override public void onClick(final View v) { @@ -107,7 +100,7 @@ public class QSPanel extends FrameLayout implements Tunable { }); mFooter = new QSFooter(this, context); - mQsContainer.addView(mFooter.getView()); + addView(mFooter.getView()); updateResources(); @@ -187,7 +180,7 @@ public class QSPanel extends FrameLayout implements Tunable { final Resources res = mContext.getResources(); mPanelPaddingBottom = res.getDimensionPixelSize(R.dimen.qs_panel_padding_bottom); mBrightnessPaddingTop = res.getDimensionPixelSize(R.dimen.qs_brightness_padding_top); - mQsContainer.setPadding(0, mBrightnessPaddingTop, 0, mPanelPaddingBottom); + setPadding(0, mBrightnessPaddingTop, 0, mPanelPaddingBottom); for (TileRecord r : mRecords) { r.tile.clearState(); } @@ -214,6 +207,9 @@ public class QSPanel extends FrameLayout implements Tunable { public void setExpanded(boolean expanded) { if (mExpanded == expanded) return; mExpanded = expanded; + if (!mExpanded && mTileLayout instanceof PagedTileLayout) { + ((PagedTileLayout) mTileLayout).setCurrentItem(0, false); + } MetricsLogger.visibility(mContext, MetricsEvent.QS_PANEL, mExpanded); if (!mExpanded) { closeDetail(); @@ -329,7 +325,8 @@ public class QSPanel extends FrameLayout implements Tunable { final View.OnLongClickListener longClick = new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { - return false; + r.tile.longClick(); + return true; } }; r.tileView.init(click, longClick); @@ -376,7 +373,7 @@ public class QSPanel extends FrameLayout implements Tunable { } public int getGridHeight() { - return mQsContainer.getMeasuredHeight(); + return getMeasuredHeight(); } protected void handleShowDetail(Record r, boolean show) { @@ -425,7 +422,7 @@ public class QSPanel extends FrameLayout implements Tunable { void setGridContentVisibility(boolean visible) { int newVis = visible ? VISIBLE : INVISIBLE; - mQsContainer.setVisibility(newVis); + setVisibility(newVis); if (mGridContentVisible != visible) { MetricsLogger.visibility(mContext, MetricsEvent.QS_PANEL, newVis); } @@ -468,6 +465,19 @@ public class QSPanel extends FrameLayout implements Tunable { } } + QSTileLayout getTileLayout() { + return mTileLayout; + } + + QSTileBaseView getTileView(QSTile<?> tile) { + for (TileRecord r : mRecords) { + if (r.tile == tile) { + return r.tileView; + } + } + return null; + } + private class H extends Handler { private static final int SHOW_DETAIL = 1; private static final int SET_TILE_VISIBILITY = 2; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java index e363b767ab9f..f02424ba1a93 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java @@ -36,7 +36,7 @@ import com.android.systemui.statusbar.phone.ManagedProfileController; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.BluetoothController; import com.android.systemui.statusbar.policy.CastController; -import com.android.systemui.statusbar.policy.DisplayController; +import com.android.systemui.statusbar.policy.NightModeController; import com.android.systemui.statusbar.policy.FlashlightController; import com.android.systemui.statusbar.policy.HotspotController; import com.android.systemui.statusbar.policy.KeyguardMonitor; @@ -212,9 +212,11 @@ public abstract class QSTile<TState extends State> implements Listenable { } protected void handleLongClick() { - // optional + mHost.startActivityDismissingKeyguard(getLongClickIntent()); } + public abstract Intent getLongClickIntent(); + protected void handleClearState() { mTmpState = newTileState(); mState = newTileState(); @@ -279,10 +281,11 @@ public abstract class QSTile<TState extends State> implements Listenable { mCallbacks.clear(); } - protected void checkIfRestrictionEnforced(State state, String userRestriction) { + protected void checkIfRestrictionEnforcedByAdminOnly(State state, String userRestriction) { EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext, userRestriction, ActivityManager.getCurrentUser()); - if (admin != null) { + if (admin != null && !RestrictedLockUtils.hasBaseUserRestriction(mContext, + userRestriction, ActivityManager.getCurrentUser())) { state.disabledByPolicy = true; state.enforcedAdmin = admin; } else { @@ -400,7 +403,7 @@ public abstract class QSTile<TState extends State> implements Listenable { UserInfoController getUserInfoController(); BatteryController getBatteryController(); TileServices getTileServices(); - DisplayController getDisplayController(); + NightModeController getNightModeController(); void removeTile(String tileSpec); ManagedProfileController getManagedProfileController(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java index 1a854c22193b..f35aacf8f72d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java @@ -49,6 +49,8 @@ public class QSTileBaseView extends LinearLayout { // Default to Quick Tile padding, and QSTileView will specify its own padding. int padding = context.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_padding); setPadding(padding, padding, padding, padding); + setClipChildren(false); + setClipToPadding(false); } private Drawable newTileBackground() { @@ -77,6 +79,7 @@ public class QSTileBaseView extends LinearLayout { public void init(OnClickListener click, OnLongClickListener longClick) { setClickable(true); setOnClickListener(click); + setOnLongClickListener(longClick); } @Override @@ -110,6 +113,10 @@ public class QSTileBaseView extends LinearLayout { setContentDescription(state.contentDescription); } + View getIcon() { + return mIcon; + } + private class H extends Handler { private static final int STATE_CHANGED = 1; public H() { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java index 0d5d115ec817..98a1c23aa645 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java @@ -28,6 +28,7 @@ import android.widget.TextView; import com.android.systemui.FontSizeUtils; import com.android.systemui.R; +import libcore.util.Objects; /** View that represents a standard quick settings tile. **/ public class QSTileView extends QSTileBaseView { @@ -57,6 +58,10 @@ public class QSTileView extends QSTileBaseView { setGravity(Gravity.CENTER); } + TextView getLabel() { + return mLabel; + } + private void updateTopPadding() { Resources res = getResources(); int padding = res.getDimensionPixelSize(R.dimen.qs_tile_padding_top); @@ -84,14 +89,11 @@ public class QSTileView extends QSTileBaseView { addView(view); } - public void init(OnClickListener clickPrimary, OnLongClickListener longClick) { - setOnClickListener(clickPrimary); - setOnLongClickListener(longClick); - } - protected void handleStateChanged(QSTile.State state) { super.handleStateChanged(state); - mLabel.setText(state.label); + if (!Objects.equal(mLabel.getText(), state.label)) { + mLabel.setText(state.label); + } mLabel.setEnabled(!state.disabledByPolicy); mPadLock.setVisibility(state.disabledByPolicy ? View.VISIBLE : View.GONE); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java index d0f7e6eb805a..abe4c7798a01 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java @@ -43,10 +43,10 @@ public class QuickQSPanel extends QSPanel { for (int i = 0; i < mRecords.size(); i++) { mTileLayout.removeTile(mRecords.get(i)); } - mQsContainer.removeView((View) mTileLayout); + removeView((View) mTileLayout); } mTileLayout = new HeaderTileLayout(context); - mQsContainer.addView((View) mTileLayout, 1 /* Between brightness and footer */); + addView((View) mTileLayout, 1 /* Between brightness and footer */); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java index f7e2338e9be9..55eda9838664 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java +++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java @@ -81,7 +81,7 @@ public class TileLayout extends ViewGroup implements QSTileLayout { record.tileView.measure(exactly(mCellWidth), exactly(mCellHeight)); previousView = record.tileView.updateAccessibilityOrder(previousView); } - setMeasuredDimension(width, (mCellHeight + mCellMargin) * rows + mCellMargin); + setMeasuredDimension(width, (mCellHeight + mCellMargin) * rows); } private static int exactly(int size) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java index 5e6b52b3b1af..b33d31df1cbd 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java @@ -15,8 +15,10 @@ package com.android.systemui.qs; import android.animation.Keyframe; +import android.util.Log; import android.util.MathUtils; import android.util.Property; +import android.view.View; import android.view.animation.Interpolator; import java.util.ArrayList; @@ -129,11 +131,36 @@ public class TouchAnimator { private void add(Object target, String property, KeyframeSet keyframeSet) { mTargets.add(target); - // TODO: Optimize the properties here, to use those in View when possible. - mProperties.add(Property.of(target.getClass(), float.class, property)); + mProperties.add(getProperty(target, property)); mValues.add(keyframeSet); } + private static Property getProperty(Object target, String property) { + if (target instanceof View) { + switch (property) { + case "translationX": + return View.TRANSLATION_X; + case "translationY": + return View.TRANSLATION_Y; + case "translationZ": + return View.TRANSLATION_Z; + case "alpha": + return View.ALPHA; + case "rotation": + return View.ROTATION; + case "x": + return View.X; + case "y": + return View.Y; + case "scaleX": + return View.SCALE_X; + case "scaleY": + return View.SCALE_Y; + } + } + return Property.of(target.getClass(), float.class, property); + } + public Builder setStartDelay(float startDelay) { mStartDelay = startDelay; return this; @@ -164,77 +191,61 @@ public class TouchAnimator { private static abstract class KeyframeSet { - private final Keyframe[] mKeyframes; + private final float mFrameWidth; + private final int mSize; - public KeyframeSet(Keyframe[] keyframes) { - mKeyframes = keyframes; + public KeyframeSet(int size) { + mSize = size; + mFrameWidth = 1 / (float) (size - 1); } Object getValue(float fraction) { int i; - for (i = 1; i < mKeyframes.length && fraction > mKeyframes[i].getFraction(); i++) ; - Keyframe first = mKeyframes[i - 1]; - Keyframe second = mKeyframes[i]; - float amount = (fraction - first.getFraction()) - / (second.getFraction() - first.getFraction()); - return interpolate(first, second, amount); + for (i = 1; i < mSize - 1 && fraction > mFrameWidth; i++); + float amount = fraction / mFrameWidth; + return interpolate(i, amount); } - protected abstract Object interpolate(Keyframe first, Keyframe second, float amount); + protected abstract Object interpolate(int index, float amount); public static KeyframeSet ofInt(int... values) { - int numKeyframes = values.length; - Keyframe keyframes[] = new Keyframe[Math.max(numKeyframes, 2)]; - if (numKeyframes == 1) { - keyframes[0] = Keyframe.ofInt(0f); - keyframes[1] = Keyframe.ofInt(1f, values[0]); - } else { - keyframes[0] = Keyframe.ofInt(0f, values[0]); - for (int i = 1; i < numKeyframes; ++i) { - keyframes[i] = Keyframe.ofInt((float) i / (numKeyframes - 1), values[i]); - } - } - return new IntKeyframeSet(keyframes); + return new IntKeyframeSet(values); } public static KeyframeSet ofFloat(float... values) { - int numKeyframes = values.length; - Keyframe keyframes[] = new Keyframe[Math.max(numKeyframes, 2)]; - if (numKeyframes == 1) { - keyframes[0] = Keyframe.ofFloat(0f); - keyframes[1] = Keyframe.ofFloat(1f, values[0]); - } else { - keyframes[0] = Keyframe.ofFloat(0f, values[0]); - for (int i = 1; i < numKeyframes; ++i) { - keyframes[i] = Keyframe.ofFloat((float) i / (numKeyframes - 1), values[i]); - } - } - return new FloatKeyframeSet(keyframes); + return new FloatKeyframeSet(values); } } - public static class FloatKeyframeSet extends KeyframeSet { - public FloatKeyframeSet(Keyframe[] keyframes) { - super(keyframes); + private static class FloatKeyframeSet extends KeyframeSet { + private final float[] mValues; + + public FloatKeyframeSet(float[] values) { + super(values.length); + mValues = values; } @Override - protected Object interpolate(Keyframe first, Keyframe second, float amount) { - float firstFloat = (float) first.getValue(); - float secondFloat = (float) second.getValue(); + protected Object interpolate(int index, float amount) { + float firstFloat = mValues[index - 1]; + float secondFloat = mValues[index]; return firstFloat + (secondFloat - firstFloat) * amount; } } - public static class IntKeyframeSet extends KeyframeSet { - public IntKeyframeSet(Keyframe[] keyframes) { - super(keyframes); + private static class IntKeyframeSet extends KeyframeSet { + + private final int[] mValues; + + public IntKeyframeSet(int[] values) { + super(values.length); + mValues = values; } @Override - protected Object interpolate(Keyframe first, Keyframe second, float amount) { - int firstFloat = (int) first.getValue(); - int secondFloat = (int) second.getValue(); + protected Object interpolate(int index, float amount) { + int firstFloat = mValues[index - 1]; + int secondFloat = mValues[index]; return (int) (firstFloat + (secondFloat - firstFloat) * amount); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java index 5c34cebe428c..45f2d75b6233 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java @@ -53,9 +53,9 @@ public class TileQueryHelper { } private void addSystemTiles(QSTileHost host) { - boolean hasColorMod = host.getDisplayController().isEnabled(); + boolean hasColorMod = host.getNightModeController().isEnabled(); String possible = mContext.getString(R.string.quick_settings_tiles_default) - + ",hotspot,inversion,saver,work,cast" + (hasColorMod ? ",colors" : ""); + + ",hotspot,inversion,saver,work,cast" + (hasColorMod ? ",night" : ""); String[] possibleTiles = possible.split(","); final Handler qsHandler = new Handler(host.getLooper()); final Handler mainHandler = new Handler(Looper.getMainLooper()); diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java index 3cd9e67e1269..0709992c07ac 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java @@ -15,13 +15,18 @@ */ package com.android.systemui.qs.external; +import android.app.ActivityManager; import android.content.ComponentName; +import android.content.Intent; import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; +import android.provider.Settings; import android.service.quicksettings.IQSTileService; import android.service.quicksettings.Tile; import android.service.quicksettings.TileService; @@ -156,8 +161,22 @@ public class CustomTile extends QSTile<QSTile.State> { } @Override - protected void handleUserSwitch(int newUserId) { - super.handleUserSwitch(newUserId); + public Intent getLongClickIntent() { + Intent i = new Intent(TileService.ACTION_QS_TILE_PREFERENCES); + i.setPackage(mComponent.getPackageName()); + i = resolveIntent(i); + if (i != null) { + return i; + } + return new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData( + Uri.fromParts("package", mComponent.getPackageName(), null)); + } + + private Intent resolveIntent(Intent i) { + ResolveInfo result = mContext.getPackageManager().resolveActivityAsUser(i, 0, + ActivityManager.getCurrentUser()); + return result != null ? new Intent(TileService.ACTION_QS_TILE_PREFERENCES) + .setClassName(result.activityInfo.packageName, result.activityInfo.name) : null; } @Override @@ -184,10 +203,6 @@ public class CustomTile extends QSTile<QSTile.State> { } @Override - protected void handleLongClick() { - } - - @Override protected void handleUpdateState(State state, Object arg) { Drawable drawable = mTile.getIcon().loadDrawable(mContext); int color = mContext.getColor(getColor(mTile.getState())); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java index 5222e61ab5d3..f0860fe181d3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java @@ -21,6 +21,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.ConnectivityManager; +import android.provider.Settings; import android.provider.Settings.Global; import com.android.internal.logging.MetricsLogger; @@ -68,6 +69,11 @@ public class AirplaneModeTile extends QSTile<QSTile.BooleanState> { } @Override + public Intent getLongClickIntent() { + return new Intent(Settings.ACTION_AIRPLANE_MODE_SETTINGS); + } + + @Override protected void handleUpdateState(BooleanState state, Object arg) { final int value = arg instanceof Integer ? (Integer)arg : mSetting.getValue(); final boolean airplaneMode = value != 0; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java index 6a9d82602fc2..93e075d945db 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java @@ -19,6 +19,7 @@ import android.content.Context; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Handler; +import android.provider.Settings; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.style.RelativeSizeSpan; @@ -91,6 +92,11 @@ public class BatteryTile extends QSTile<QSTile.State> implements BatteryControll } @Override + public Intent getLongClickIntent() { + return new Intent(Intent.ACTION_POWER_USAGE_SUMMARY); + } + + @Override protected void handleClick() { showDetail(true); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java index c4b7944039ad..80f667c41987 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java @@ -78,6 +78,11 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> { } @Override + public Intent getLongClickIntent() { + return new Intent(Settings.ACTION_BLUETOOTH_SETTINGS); + } + + @Override protected void handleClick() { if (!mController.canConfigBluetooth()) { mHost.startActivityDismissingKeyguard(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS)); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java index 15e082abff67..e0ad002bc149 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -86,6 +86,11 @@ public class CastTile extends QSTile<QSTile.BooleanState> { } @Override + public Intent getLongClickIntent() { + return new Intent(Settings.ACTION_CAST_SETTINGS); + } + + @Override protected void handleClick() { if (mKeyguard.isSecure() && !mKeyguard.canSkipBouncer()) { mHost.startRunnableDismissingKeyguard(new Runnable() { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java index 15617c7f9c8f..5f87741ced8a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java @@ -37,7 +37,7 @@ import com.android.systemui.statusbar.policy.SignalCallbackAdapter; /** Quick settings tile: Cellular **/ public class CellularTile extends QSTile<QSTile.SignalState> { - private static final Intent CELLULAR_SETTINGS = new Intent().setComponent(new ComponentName( + static final Intent CELLULAR_SETTINGS = new Intent().setComponent(new ComponentName( "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity")); private final NetworkController mController; @@ -78,6 +78,11 @@ public class CellularTile extends QSTile<QSTile.SignalState> { } @Override + public Intent getLongClickIntent() { + return CELLULAR_SETTINGS; + } + + @Override protected void handleClick() { MetricsLogger.action(mContext, getMetricsCategory()); if (mDataController.isMobileDataSupported()) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java index e98734cb3f43..42ce69c57978 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java @@ -16,6 +16,8 @@ package com.android.systemui.qs.tiles; +import android.content.Intent; +import android.provider.Settings; import android.provider.Settings.Secure; import com.android.internal.logging.MetricsLogger; @@ -70,6 +72,11 @@ public class ColorInversionTile extends QSTile<QSTile.BooleanState> { } @Override + public Intent getLongClickIntent() { + return new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS); + } + + @Override protected void handleClick() { MetricsLogger.action(mContext, getMetricsCategory(), !mState.value); mSetting.setValue(mState.value ? 0 : 1); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java index c6a98b4fb1d9..a1789a5a1d63 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java @@ -14,6 +14,7 @@ package com.android.systemui.qs.tiles; +import android.content.Intent; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.systemui.R; import com.android.systemui.qs.QSTile; @@ -44,6 +45,11 @@ public class DataSaverTile extends QSTile<QSTile.BooleanState> implements } @Override + public Intent getLongClickIntent() { + return CellularTile.CELLULAR_SETTINGS; + } + + @Override protected void handleClick() { mState.value = !mDataSaverController.isDataSaverEnabled(); mDataSaverController.setDataSaverEnabled(mState.value); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java index 29ca06bfb878..8982b3e1de13 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -29,11 +29,13 @@ import android.view.LayoutInflater; import android.view.View; import android.view.View.OnAttachStateChangeListener; import android.view.ViewGroup; +import android.widget.Toast; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.systemui.Prefs; import com.android.systemui.R; +import com.android.systemui.SysUIToast; import com.android.systemui.qs.QSTile; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.volume.ZenModePanel; @@ -99,7 +101,20 @@ public class DndTile extends QSTile<QSTile.BooleanState> { } @Override + public Intent getLongClickIntent() { + return ZEN_SETTINGS; + } + + @Override public void handleClick() { + if (mController.isVolumeRestricted()) { + // Collapse the panels, so the user can see the toast. + mHost.collapsePanels(); + SysUIToast.makeText(mContext, mContext.getString( + com.android.internal.R.string.error_message_change_not_allowed), + Toast.LENGTH_LONG).show(); + return; + } MetricsLogger.action(mContext, getMetricsCategory(), !mState.value); if (mState.value) { mController.setZen(Global.ZEN_MODE_OFF, null, TAG); @@ -116,8 +131,7 @@ public class DndTile extends QSTile<QSTile.BooleanState> { final boolean newValue = zen != Global.ZEN_MODE_OFF; final boolean valueChanged = state.value != newValue; state.value = newValue; - state.disabledByPolicy = mController.isVolumeRestricted(); - checkIfRestrictionEnforced(state, UserManager.DISALLOW_ADJUST_VOLUME); + checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_ADJUST_VOLUME); switch (zen) { case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java index f06634e9cb78..c10843a30547 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java @@ -18,6 +18,8 @@ package com.android.systemui.qs.tiles; import android.app.ActivityManager; +import android.content.Intent; +import android.provider.MediaStore; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.systemui.R; @@ -60,6 +62,11 @@ public class FlashlightTile extends QSTile<QSTile.BooleanState> implements } @Override + public Intent getLongClickIntent() { + return new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); + } + + @Override protected void handleClick() { if (ActivityManager.isUserAMonkey()) { return; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java index 943b502a565f..ad1c7a0acf01 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java @@ -16,8 +16,10 @@ package com.android.systemui.qs.tiles; +import android.content.Intent; import android.os.UserManager; +import android.provider.Settings; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.systemui.R; @@ -58,6 +60,11 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> { } @Override + public Intent getLongClickIntent() { + return new Intent(Settings.ACTION_WIRELESS_SETTINGS); + } + + @Override protected void handleClick() { final boolean isEnabled = (Boolean) mState.value; MetricsLogger.action(mContext, getMetricsCategory(), !isEnabled); @@ -68,8 +75,7 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> { protected void handleUpdateState(BooleanState state, Object arg) { state.label = mContext.getString(R.string.quick_settings_hotspot_label); - state.disabledByPolicy = mController.isTetheringAllowed(); - checkIfRestrictionEnforced(state, UserManager.DISALLOW_CONFIG_TETHERING); + checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_CONFIG_TETHERING); if (arg instanceof Boolean) { state.value = (boolean) arg; } else { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java index bdf95d8782bf..bb5ff8e4cc16 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java @@ -92,6 +92,11 @@ public class IntentTile extends QSTile<QSTile.State> { } @Override + public Intent getLongClickIntent() { + return null; + } + + @Override protected void handleLongClick() { sendIntent("long-click", mOnLongClick, mOnLongClickUri); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java index 9f41f9a17a83..65332529d881 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java @@ -16,8 +16,10 @@ package com.android.systemui.qs.tiles; +import android.content.Intent; import android.os.UserManager; +import android.provider.Settings; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.systemui.R; @@ -61,6 +63,11 @@ public class LocationTile extends QSTile<QSTile.BooleanState> { } @Override + public Intent getLongClickIntent() { + return new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); + } + + @Override protected void handleClick() { if (mKeyguard.isSecure() && mKeyguard.isShowing()) { mHost.startRunnableDismissingKeyguard(new Runnable() { @@ -87,8 +94,7 @@ public class LocationTile extends QSTile<QSTile.BooleanState> { // bug is fixed, this should be reverted to only hiding it on secure lock screens: // state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing()); state.value = locationEnabled; - state.disabledByPolicy = mController.isUserLocationRestricted(); - checkIfRestrictionEnforced(state, UserManager.DISALLOW_SHARE_LOCATION); + checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_SHARE_LOCATION); if (locationEnabled) { state.icon = mEnable; state.label = mContext.getString(R.string.quick_settings_location_label); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java index c94cf5a9bec2..b267ccd1ec46 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java @@ -17,8 +17,10 @@ package com.android.systemui.qs.tiles; import android.content.Context; +import android.content.Intent; import android.content.res.Configuration; +import android.provider.Settings; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.systemui.R; @@ -60,6 +62,11 @@ public class RotationLockTile extends QSTile<QSTile.BooleanState> { } @Override + public Intent getLongClickIntent() { + return new Intent(Settings.ACTION_DISPLAY_SETTINGS); + } + + @Override protected void handleClick() { if (mController == null) return; MetricsLogger.action(mContext, getMetricsCategory(), !mState.value); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java index ba7ea4d66453..f1066c11c11a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java @@ -16,7 +16,9 @@ package com.android.systemui.qs.tiles; import android.content.Context; +import android.content.Intent; import android.graphics.drawable.Drawable; +import android.provider.Settings; import android.util.Pair; import com.android.internal.logging.MetricsProto.MetricsEvent; @@ -42,6 +44,11 @@ public class UserTile extends QSTile<QSTile.State> implements UserInfoController } @Override + public Intent getLongClickIntent() { + return new Intent(Settings.ACTION_USER_SETTINGS); + } + + @Override protected void handleClick() { showDetail(true); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java index 7a58f1553bcd..7ee795f924b3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java @@ -93,6 +93,11 @@ public class WifiTile extends QSTile<QSTile.SignalState> { } @Override + public Intent getLongClickIntent() { + return WIFI_SETTINGS; + } + + @Override protected void handleSecondaryClick() { // Secondary clicks are header clicks, just toggle. mState.copyTo(mStateBeforeClick); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java index 053a98a5ce05..003e9c15ad43 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java @@ -16,6 +16,8 @@ package com.android.systemui.qs.tiles; +import android.content.Intent; +import android.provider.Settings; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.systemui.R; @@ -52,6 +54,11 @@ public class WorkModeTile extends QSTile<QSTile.BooleanState> implements } @Override + public Intent getLongClickIntent() { + return new Intent(Settings.ACTION_SYNC_SETTINGS); + } + + @Override public void handleClick() { MetricsLogger.action(mContext, getMetricsCategory(), !mState.value); mProfileController.setWorkModeEnabled(!mState.value); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java index fe504fefef26..3f0630d70c94 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java @@ -494,7 +494,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { * onChildDismissed() calls. */ @Override - public void onChildSnappedBack(View v) { + public void onChildSnappedBack(View v, float targetLeft) { TaskView tv = (TaskView) v; // Re-enable clipping with the stack @@ -517,11 +517,6 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { } @Override - public View getChildContentView(View v) { - return v; - } - - @Override public boolean isAntiFalsingNeeded() { return false; } diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java index 189e651b7dca..dd59face9ac7 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java @@ -40,6 +40,7 @@ public class Divider extends SystemUI { private DividerView mView; private DockDividerVisibilityListener mDockDividerVisibilityListener; private boolean mVisible = false; + private boolean mMinimized = false; @Override public void start() { @@ -81,6 +82,10 @@ public class Divider extends SystemUI { private void update(Configuration configuration) { removeDivider(); addDivider(configuration); + if (mMinimized) { + mView.setMinimizedDockStack(true); + mWindowManager.setTouchable(false); + } } private void updateVisibility(final boolean visible) { @@ -95,6 +100,23 @@ public class Divider extends SystemUI { }); } + private void updateMinimizedDockedStack(final boolean minimized, final long animDuration) { + mView.post(new Runnable() { + @Override + public void run() { + if (mMinimized != minimized) { + mMinimized = minimized; + mWindowManager.setTouchable(!minimized); + if (animDuration > 0) { + mView.setMinimizedDockStack(minimized, animDuration); + } else { + mView.setMinimizedDockStack(minimized); + } + } + } + }); + } + class DockDividerVisibilityListener extends IDockedStackListener.Stub { @Override @@ -105,5 +127,11 @@ public class Divider extends SystemUI { @Override public void onDockedStackExistsChanged(boolean exists) throws RemoteException { } + + @Override + public void onDockedStackMinimizedChanged(boolean minimized, long animDuration) + throws RemoteException { + updateMinimizedDockedStack(minimized, animDuration); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java index 36cfac8dd092..9118e9cb8635 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java @@ -140,4 +140,9 @@ public class DividerHandleView extends ImageButton { canvas.drawRoundRect(left, top, left + mCurrentWidth, top + mCurrentHeight, radius, radius, mPaint); } + + @Override + public boolean hasOverlappingRendering() { + return false; + } } diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 1bdf5a1e698d..65a2f8fc8f06 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -40,7 +40,6 @@ import android.view.ViewTreeObserver.InternalInsetsInfo; import android.view.ViewTreeObserver.OnComputeInternalInsetsListener; import android.view.WindowInsets; import android.view.WindowManager; -import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; import android.widget.FrameLayout; @@ -86,6 +85,11 @@ public class DividerView extends FrameLayout implements OnTouchListener, */ private static final float BOTTOM_RIGHT_SWITCH_BIGGER_FRACTION = 0.2f; + /** + * How much the background gets scaled when we are in the minimized dock state. + */ + private static final float MINIMIZE_DOCK_SCALE = 0.375f; + private static final PathInterpolator SLOWDOWN_INTERPOLATOR = new PathInterpolator(0.5f, 1f, 0.5f, 1f); private static final PathInterpolator DIM_INTERPOLATOR = @@ -126,6 +130,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, private boolean mAnimateAfterRecentsDrawn; private boolean mGrowAfterRecentsDrawn; private boolean mGrowRecents; + private Animator mCurrentAnimator; public DividerView(Context context) { super(context); @@ -205,6 +210,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, } public boolean startDragging(boolean animate, boolean touching) { + cancelFlingAnimation(); if (touching) { mHandle.setTouching(true, animate); } @@ -364,11 +370,19 @@ public class DividerView extends FrameLayout implements OnTouchListener, commitSnapFlags(snapTarget); mWindowManagerProxy.setResizing(false); mDockSide = WindowManager.DOCKED_INVALID; + mCurrentAnimator = null; } }); + mCurrentAnimator = anim; return anim; } + private void cancelFlingAnimation() { + if (mCurrentAnimator != null) { + mCurrentAnimator.cancel(); + } + } + private void commitSnapFlags(SnapTarget target) { if (target.flag == SnapTarget.FLAG_NONE) { return; @@ -433,6 +447,47 @@ public class DividerView extends FrameLayout implements OnTouchListener, mBackgroundLifted = false; } + + public void setMinimizedDockStack(boolean minimized) { + updateDockSide(); + mHandle.setAlpha(minimized ? 0f : 1f); + if (mDockSide == WindowManager.DOCKED_TOP) { + mBackground.setPivotY(0); + mBackground.setScaleY(minimized ? MINIMIZE_DOCK_SCALE : 1f); + } else if (mDockSide == WindowManager.DOCKED_LEFT + || mDockSide == WindowManager.DOCKED_RIGHT) { + mBackground.setPivotX(mDockSide == WindowManager.DOCKED_LEFT + ? 0 + : mBackground.getWidth()); + mBackground.setScaleX(minimized ? MINIMIZE_DOCK_SCALE : 1f); + } + } + + public void setMinimizedDockStack(boolean minimized, long animDuration) { + updateDockSide(); + mHandle.animate() + .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) + .setDuration(animDuration) + .alpha(minimized ? 0f : 1f) + .start(); + if (mDockSide == WindowManager.DOCKED_TOP) { + mBackground.setPivotY(0); + mBackground.animate() + .scaleY(minimized ? MINIMIZE_DOCK_SCALE : 1f); + } else if (mDockSide == WindowManager.DOCKED_LEFT + || mDockSide == WindowManager.DOCKED_RIGHT) { + mBackground.setPivotX(mDockSide == WindowManager.DOCKED_LEFT + ? 0 + : mBackground.getWidth()); + mBackground.animate() + .scaleX(minimized ? MINIMIZE_DOCK_SCALE : 1f); + } + mBackground.animate() + .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) + .setDuration(animDuration) + .start(); + } + @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java index 2294d40d318d..3db03d0abf11 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java @@ -22,6 +22,7 @@ import android.view.View; import android.view.WindowManager; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; +import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY; import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; @@ -79,4 +80,18 @@ public class DividerWindowManager { mWindowManager.updateViewLayout(mView, mLp); } } + + public void setTouchable(boolean touchable) { + boolean changed = false; + if (!touchable && (mLp.flags & FLAG_NOT_TOUCHABLE) == 0) { + mLp.flags |= FLAG_NOT_TOUCHABLE; + changed = true; + } else if (touchable && (mLp.flags & FLAG_NOT_TOUCHABLE) != 0) { + mLp.flags &= ~FLAG_NOT_TOUCHABLE; + changed = true; + } + if (changed) { + mWindowManager.updateViewLayout(mView, mLp); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java index 874defad3f7d..315c5092922c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java @@ -208,6 +208,10 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView return false; } + protected boolean handleSlideBack() { + return false; + } + @Override public boolean onTouchEvent(MotionEvent event) { boolean result; @@ -260,6 +264,9 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView break; case MotionEvent.ACTION_UP: if (isWithinTouchSlop(event)) { + if (handleSlideBack()) { + return true; + } if (!mActivated) { makeActive(); postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 2bebac2c5136..ea8b75ed164c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -103,6 +103,7 @@ import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.PreviewInflater; import com.android.systemui.statusbar.policy.RemoteInputView; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; +import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.GearDisplayedListener; import com.android.systemui.statusbar.stack.StackStateAnimator; import java.util.ArrayList; @@ -115,7 +116,7 @@ import static com.android.keyguard.KeyguardHostView.OnDismissAction; public abstract class BaseStatusBar extends SystemUI implements CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener, ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment, - ExpandableNotificationRow.OnExpandClickListener { + ExpandableNotificationRow.OnExpandClickListener, GearDisplayedListener { public static final String TAG = "StatusBar"; public static final boolean DEBUG = false; public static final boolean MULTIUSER_DEBUG = false; @@ -220,6 +221,7 @@ public abstract class BaseStatusBar extends SystemUI implements // which notification is currently being longpress-examined by the user private NotificationGuts mNotificationGutsExposed; + private ExpandableNotificationRow mNotificationGearDisplayed; private KeyboardShortcuts mKeyboardShortcuts; @@ -1008,6 +1010,10 @@ public abstract class BaseStatusBar extends SystemUI implements guts.bindImportance(sbn, row, mNotificationData.getImportance(sbn.getKey())); } + protected GearDisplayedListener getGearDisplayedListener() { + return this; + } + protected SwipeHelper.LongPressListener getNotificationLongClicker() { return new SwipeHelper.LongPressListener() { @Override @@ -1020,7 +1026,7 @@ public abstract class BaseStatusBar extends SystemUI implements return false; } - ExpandableNotificationRow row = (ExpandableNotificationRow) v; + final ExpandableNotificationRow row = (ExpandableNotificationRow) v; bindGuts(row); // Assume we are a status_bar_notification_row @@ -1052,6 +1058,14 @@ public abstract class BaseStatusBar extends SystemUI implements = ViewAnimationUtils.createCircularReveal(guts, x, y, 0, r); a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); a.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); + a.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + // Move the notification view back over the gear + row.resetTranslation(); + } + }); a.start(); guts.setExposed(true); mStackScroller.onHeightChanged(null, true /* needsAnimation */); @@ -1063,6 +1077,11 @@ public abstract class BaseStatusBar extends SystemUI implements }; } + @Override + public void onGearDisplayed(ExpandableNotificationRow row) { + mNotificationGearDisplayed = row; + } + public void dismissPopups() { dismissPopups(-1, -1); } @@ -1095,6 +1114,11 @@ public abstract class BaseStatusBar extends SystemUI implements v.setExposed(false); mStackScroller.onHeightChanged(null, true /* needsAnimation */); } + + if (mNotificationGearDisplayed != null) { + mNotificationGearDisplayed.resetTranslation(); + mNotificationGearDisplayed = null; + } } @Override @@ -1633,6 +1657,12 @@ public abstract class BaseStatusBar extends SystemUI implements return; } + // Check if the notification is displaying the gear, if so slide notification back + if (row.getSettingsRow() != null && row.getSettingsRow().isVisible()) { + row.animateTranslateNotification(0); + return; + } + Notification notification = sbn.getNotification(); final PendingIntent intent = notification.contentIntent != null ? notification.contentIntent diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index 7422902e593e..c73e115d9dd0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -16,6 +16,12 @@ package com.android.systemui.statusbar; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.animation.ValueAnimator.AnimatorUpdateListener; import android.app.Notification; import android.content.Context; import android.graphics.drawable.AnimatedVectorDrawable; @@ -45,6 +51,7 @@ import com.android.systemui.statusbar.stack.StackScrollState; import com.android.systemui.statusbar.stack.StackStateAnimator; import com.android.systemui.statusbar.stack.StackViewState; +import java.util.ArrayList; import java.util.List; public class ExpandableNotificationRow extends ActivatableNotificationView { @@ -87,6 +94,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { */ private boolean mOnKeyguard; + private AnimatorSet mTranslateAnim; + private ArrayList<View> mTranslateableViews; private NotificationContentView mPublicLayout; private NotificationContentView mPrivateLayout; private int mMaxExpandHeight; @@ -96,6 +105,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { private ExpansionLogger mLogger; private String mLoggingKey; private boolean mWasReset; + private NotificationSettingsIconRow mSettingsIconRow; private NotificationGuts mGuts; private NotificationData.Entry mEntry; private StatusBarNotification mStatusBarNotification; @@ -108,6 +118,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { private boolean mChildrenExpanded; private boolean mIsSummaryWithChildren; private NotificationChildrenContainer mChildrenContainer; + private ViewStub mSettingsIconRowStub; private ViewStub mGutsStub; private boolean mIsSystemChildExpanded; private boolean mIsPinned; @@ -240,7 +251,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { != com.android.internal.R.id.status_bar_latest_event_content; int headsUpheight = headsUpCustom && beforeN ? mMaxHeadsUpHeightLegacy : mMaxHeadsUpHeight; - mMaxViewHeight = mNotificationMaxHeight; mPrivateLayout.setHeights(minHeight, headsUpheight, mNotificationMaxHeight); mPublicLayout.setHeights(minHeight, headsUpheight, mNotificationMaxHeight); } @@ -329,6 +339,15 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { } @Override + protected boolean handleSlideBack() { + if (mSettingsIconRow != null && mSettingsIconRow.isVisible()) { + animateTranslateNotification(0 /* targetLeft */); + return true; + } + return false; + } + + @Override protected boolean shouldHideBackground() { return super.shouldHideBackground() || mShowNoBackground; } @@ -500,6 +519,13 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { return mPrivateLayout.getNotificationHeader(); } + private NotificationHeaderView getVisibleNotificationHeader() { + if (mNotificationHeader != null) { + return mNotificationHeader; + } + return getShowingLayout().getVisibleNotificationHeader(); + } + public void setOnExpandClickListener(OnExpandClickListener onExpandClickListener) { mOnExpandClickListener = onExpandClickListener; } @@ -527,6 +553,17 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { mGuts.setVisibility(oldGuts.getVisibility()); addView(mGuts, index); } + if (mSettingsIconRow != null) { + View oldSettings = mSettingsIconRow; + int settingsIndex = indexOfChild(oldSettings); + removeView(oldSettings); + mSettingsIconRow = (NotificationSettingsIconRow) LayoutInflater.from(mContext).inflate( + R.layout.notification_settings_icon_row, this, false); + mSettingsIconRow.setNotificationRowParent(ExpandableNotificationRow.this); + mSettingsIconRow.setVisibility(oldSettings.getVisibility()); + addView(mSettingsIconRow, settingsIndex); + + } mPrivateLayout.reInflateViews(); mPublicLayout.reInflateViews(); } @@ -542,16 +579,23 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { } private void initDimens() { - mNotificationMinHeightLegacy = getResources().getDimensionPixelSize( - R.dimen.notification_min_height_legacy); - mNotificationMinHeight = getResources().getDimensionPixelSize( - R.dimen.notification_min_height); - mNotificationMaxHeight = getResources().getDimensionPixelSize( - R.dimen.notification_max_height); - mMaxHeadsUpHeightLegacy = getResources().getDimensionPixelSize( + mNotificationMinHeightLegacy = getFontScaledHeight(R.dimen.notification_min_height_legacy); + mNotificationMinHeight = getFontScaledHeight(R.dimen.notification_min_height); + mNotificationMaxHeight = getFontScaledHeight(R.dimen.notification_max_height); + mMaxHeadsUpHeightLegacy = getFontScaledHeight( R.dimen.notification_max_heads_up_height_legacy); - mMaxHeadsUpHeight = getResources().getDimensionPixelSize( - R.dimen.notification_max_heads_up_height); + mMaxHeadsUpHeight = getFontScaledHeight(R.dimen.notification_max_heads_up_height); + } + + /** + * @param dimenId the dimen to look up + * @return the font scaled dimen as if it were in sp but doesn't shrink sizes below dp + */ + private int getFontScaledHeight(int dimenId) { + int dimensionPixelSize = getResources().getDimensionPixelSize(dimenId); + float factor = Math.max(1.0f, getResources().getDisplayMetrics().scaledDensity / + getResources().getDisplayMetrics().density); + return (int) (dimensionPixelSize * factor); } /** @@ -561,7 +605,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { public void reset() { super.reset(); final boolean wasExpanded = isExpanded(); - mMaxViewHeight = 0; mExpandable = false; mHasUserChangedExpansion = false; mUserLocked = false; @@ -573,6 +616,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { mPublicLayout.reset(mIsHeadsUp); mPrivateLayout.reset(mIsHeadsUp); resetHeight(); + resetTranslation(); logExpansionEvent(false, wasExpanded); } @@ -596,6 +640,14 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { mPrivateLayout.setExpandClickListener(mExpandClickListener); mPrivateLayout.setContainingNotification(this); mPublicLayout.setExpandClickListener(mExpandClickListener); + mSettingsIconRowStub = (ViewStub) findViewById(R.id.settings_icon_row_stub); + mSettingsIconRowStub.setOnInflateListener(new ViewStub.OnInflateListener() { + @Override + public void onInflate(ViewStub stub, View inflated) { + mSettingsIconRow = (NotificationSettingsIconRow) inflated; + mSettingsIconRow.setNotificationRowParent(ExpandableNotificationRow.this); + } + }); mGutsStub = (ViewStub) findViewById(R.id.notification_guts_stub); mGutsStub.setOnInflateListener(new ViewStub.OnInflateListener() { @Override @@ -603,6 +655,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { mGuts = (NotificationGuts) inflated; mGuts.setClipTopAmount(getClipTopAmount()); mGuts.setActualHeight(getActualHeight()); + mTranslateableViews.add(mGuts); mGutsStub = null; } }); @@ -613,9 +666,89 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { public void onInflate(ViewStub stub, View inflated) { mChildrenContainer = (NotificationChildrenContainer) inflated; mChildrenContainer.setNotificationParent(ExpandableNotificationRow.this); + mTranslateableViews.add(mChildrenContainer); } }); mVetoButton = findViewById(R.id.veto); + + // Add the views that we translate to reveal the gear + mTranslateableViews = new ArrayList<View>(); + for (int i = 0; i < getChildCount(); i++) { + mTranslateableViews.add(getChildAt(i)); + } + // Remove views that don't translate + mTranslateableViews.remove(mVetoButton); + mTranslateableViews.remove(mSettingsIconRowStub); + mTranslateableViews.remove(mChildrenContainerStub); + mTranslateableViews.remove(mGutsStub); + } + + public void setTranslationForOutline(float translationX) { + setOutlineRect(false, translationX, getTop(), getRight() + translationX, getBottom()); + } + + public void resetTranslation() { + if (mTranslateableViews != null) { + for (int i = 0; i < mTranslateableViews.size(); i++) { + mTranslateableViews.get(i).setTranslationX(0); + } + setTranslationForOutline(0); + } + if (mSettingsIconRow != null) { + mSettingsIconRow.resetState(); + } + } + + public void animateTranslateNotification(final float leftTarget) { + if (mTranslateAnim != null) { + mTranslateAnim.cancel(); + } + AnimatorSet set = new AnimatorSet(); + if (mTranslateableViews != null) { + for (int i = 0; i < mTranslateableViews.size(); i++) { + final View animView = mTranslateableViews.get(i); + final ObjectAnimator translateAnim = ObjectAnimator.ofFloat( + animView, "translationX", leftTarget); + if (i == 0) { + translateAnim.addUpdateListener(new AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + setTranslationForOutline((float) animation.getAnimatedValue()); + } + }); + } + translateAnim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator anim) { + if (mSettingsIconRow != null && leftTarget == 0) { + mSettingsIconRow.resetState(); + } + mTranslateAnim = null; + } + }); + set.play(translateAnim); + } + } + mTranslateAnim = set; + set.start(); + } + + public float getSpaceForGear() { + if (mSettingsIconRow != null) { + return mSettingsIconRow.getSpaceForGear(); + } + return 0; + } + + public NotificationSettingsIconRow getSettingsRow() { + if (mSettingsIconRow == null) { + mSettingsIconRowStub.inflate(); + } + return mSettingsIconRow; + } + + public ArrayList<View> getContentViews() { + return mTranslateableViews; } public void inflateGuts() { @@ -772,7 +905,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { if (mIsSummaryWithChildren) { mChildrenContainer.updateGroupOverflow(); } - notifyHeightChanged(false /* needsAnimation */); + notifyHeightChanged(false /* needsAnimation */); } } } @@ -1097,6 +1230,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { mNotificationHeaderWrapper = NotificationViewWrapper.wrap(getContext(), mNotificationHeader); addView(mNotificationHeader, indexOfChild(mChildrenContainer) + 1); + mTranslateableViews.add(mNotificationHeader); } else { header.reapply(getContext(), mNotificationHeader); mNotificationHeaderWrapper.notifyContentUpdated(mEntry.notification); @@ -1166,7 +1300,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { protected boolean disallowSingleClick(MotionEvent event) { float x = event.getX(); float y = event.getY(); - NotificationHeaderView header = getNotificationHeader(); + NotificationHeaderView header = getVisibleNotificationHeader(); if (header != null) { return header.isInTouchRect(x, y); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java index 44c6a5d36c64..782a38cc4023 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java @@ -81,8 +81,13 @@ public abstract class ExpandableOutlineView extends ExpandableView { } protected void setOutlineRect(float left, float top, float right, float bottom) { + setOutlineRect(true, left, top, right, bottom); + } + + protected void setOutlineRect(boolean clipToOutline, float left, float top, float right, + float bottom) { mCustomOutline = true; - setClipToOutline(true); + setClipToOutline(clipToOutline); mOutlineRect.set((int) left, (int) top, (int) right, (int) bottom); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java index 8042b60714b2..3176e2e1851a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java @@ -24,7 +24,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; -import com.android.systemui.R; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; import java.util.ArrayList; @@ -35,7 +34,6 @@ import java.util.ArrayList; public abstract class ExpandableView extends FrameLayout { protected OnHeightChangedListener mOnHeightChangedListener; - protected int mMaxViewHeight; private int mActualHeight; protected int mClipTopAmount; private boolean mActualHeightInitialized; @@ -49,8 +47,6 @@ public abstract class ExpandableView extends FrameLayout { public ExpandableView(Context context, AttributeSet attrs) { super(context, attrs); - mMaxViewHeight = getResources().getDimensionPixelSize( - R.dimen.notification_max_height); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java index d5361dd75e83..647f0bfd0e26 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java @@ -144,11 +144,11 @@ public class NotificationContentView extends FrameLayout { } if (mContractedChild != null) { int heightSpec; + int size = Math.min(maxSize, mSmallHeight); if (shouldContractedBeFixedSize()) { - int size = Math.min(maxSize, mSmallHeight); heightSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY); } else { - heightSpec = MeasureSpec.makeMeasureSpec(maxSize, MeasureSpec.AT_MOST); + heightSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST); } mContractedChild.measure(widthMeasureSpec, heightSpec); int measuredHeight = mContractedChild.getMeasuredHeight(); @@ -475,6 +475,19 @@ public class NotificationContentView extends FrameLayout { } } + private NotificationViewWrapper getCurrentVisibleWrapper() { + switch (mVisibleType) { + case VISIBLE_TYPE_EXPANDED: + return mExpandedWrapper; + case VISIBLE_TYPE_HEADSUP: + return mHeadsUpWrapper; + case VISIBLE_TYPE_CONTRACTED: + return mContractedWrapper; + default: + return null; + } + } + /** * @return one of the static enum types in this view, calculated form the current state */ @@ -684,6 +697,11 @@ public class NotificationContentView extends FrameLayout { return header; } + public NotificationHeaderView getVisibleNotificationHeader() { + NotificationViewWrapper wrapper = getCurrentVisibleWrapper(); + return wrapper == null ? null : wrapper.getNotificationHeader(); + } + public void setContainingNotification(ExpandableNotificationRow containingNotification) { mContainingNotification = containingNotification; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java index 2cacb8aedd65..ccd0ad857bbe 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java @@ -34,6 +34,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.Objects; /** * The list of currently displaying notifications. @@ -118,10 +119,16 @@ public class NotificationData { final RemoteViews newPublicNotification = updatedNotificationBuilder.makePublicContentView(); + boolean sameCustomView = Objects.equals( + notification.getNotification().extras.getBoolean( + Notification.EXTRA_CONTAINS_CUSTOM_VIEW), + updatedNotification.extras.getBoolean( + Notification.EXTRA_CONTAINS_CUSTOM_VIEW)); applyInPlace = compareRemoteViews(cachedContentView, newContentView) && compareRemoteViews(cachedBigContentView, newBigContentView) && compareRemoteViews(cachedHeadsUpContentView, newHeadsUpContentView) - && compareRemoteViews(cachedPublicContentView, newPublicNotification); + && compareRemoteViews(cachedPublicContentView, newPublicNotification) + && sameCustomView; cachedPublicContentView = newPublicNotification; cachedHeadsUpContentView = newHeadsUpContentView; cachedBigContentView = newBigContentView; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java index 7346becdb0eb..fe84d81354dd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java @@ -49,9 +49,7 @@ public class NotificationGuts extends LinearLayout { private int mClipTopAmount; private int mActualHeight; private boolean mExposed; - private RadioButton mApplyToTopic; private SeekBar mSeekBar; - private Notification.Topic mTopic; private INotificationManager mINotificationManager; private int mStartingImportance; @@ -109,24 +107,9 @@ public class NotificationGuts extends LinearLayout { mStartingImportance = importance; mINotificationManager = INotificationManager.Stub.asInterface( ServiceManager.getService(Context.NOTIFICATION_SERVICE)); - mTopic = sbn.getNotification().getTopic() == null - ? new Notification.Topic(Notification.TOPIC_DEFAULT, mContext.getString( - com.android.internal.R.string.default_notification_topic_label)) - : sbn.getNotification().getTopic(); - boolean doesUserUseTopics = false; - try { - doesUserUseTopics = - mINotificationManager.doesUserUseTopics(sbn.getPackageName(), sbn.getUid()); - } catch (RemoteException e) {} - final boolean userUsesTopics = doesUserUseTopics; - - mApplyToTopic = (RadioButton) row.findViewById(R.id.apply_to_topic); - if (userUsesTopics) { - mApplyToTopic.setChecked(true); - } - final View applyToApp = row.findViewById(R.id.apply_to_app); - final TextView topicSummary = ((TextView) row.findViewById(R.id.summary)); - final TextView topicTitle = ((TextView) row.findViewById(R.id.title)); + + final TextView importanceSummary = ((TextView) row.findViewById(R.id.summary)); + final TextView importanceTitle = ((TextView) row.findViewById(R.id.title)); mSeekBar = (SeekBar) row.findViewById(R.id.seekbar); boolean systemApp = false; try { @@ -156,12 +139,6 @@ public class NotificationGuts extends LinearLayout { updateTitleAndSummary(progress); if (fromUser) { MetricsLogger.action(mContext, MetricsEvent.ACTION_MODIFY_IMPORTANCE_SLIDER); - if (userUsesTopics) { - mApplyToTopic.setVisibility(View.VISIBLE); - mApplyToTopic.setText( - mContext.getString(R.string.apply_to_topic, mTopic.getLabel())); - applyToApp.setVisibility(View.VISIBLE); - } } } @@ -178,29 +155,29 @@ public class NotificationGuts extends LinearLayout { private void updateTitleAndSummary(int progress) { switch (progress) { case NotificationListenerService.Ranking.IMPORTANCE_NONE: - topicSummary.setText(mContext.getString( + importanceSummary.setText(mContext.getString( R.string.notification_importance_blocked)); - topicTitle.setText(mContext.getString(R.string.blocked_importance)); + importanceTitle.setText(mContext.getString(R.string.blocked_importance)); break; case NotificationListenerService.Ranking.IMPORTANCE_LOW: - topicSummary.setText(mContext.getString( + importanceSummary.setText(mContext.getString( R.string.notification_importance_low)); - topicTitle.setText(mContext.getString(R.string.low_importance)); + importanceTitle.setText(mContext.getString(R.string.low_importance)); break; case NotificationListenerService.Ranking.IMPORTANCE_DEFAULT: - topicSummary.setText(mContext.getString( + importanceSummary.setText(mContext.getString( R.string.notification_importance_default)); - topicTitle.setText(mContext.getString(R.string.default_importance)); + importanceTitle.setText(mContext.getString(R.string.default_importance)); break; case NotificationListenerService.Ranking.IMPORTANCE_HIGH: - topicSummary.setText(mContext.getString( + importanceSummary.setText(mContext.getString( R.string.notification_importance_high)); - topicTitle.setText(mContext.getString(R.string.high_importance)); + importanceTitle.setText(mContext.getString(R.string.high_importance)); break; case NotificationListenerService.Ranking.IMPORTANCE_MAX: - topicSummary.setText(mContext.getString( + importanceSummary.setText(mContext.getString( R.string.notification_importance_max)); - topicTitle.setText(mContext.getString(R.string.max_importance)); + importanceTitle.setText(mContext.getString(R.string.max_importance)); break; } } @@ -213,8 +190,7 @@ public class NotificationGuts extends LinearLayout { MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE, progress - mStartingImportance); try { - mINotificationManager.setImportance(sbn.getPackageName(), sbn.getUid(), - mApplyToTopic.isChecked() ? mTopic : null, progress); + mINotificationManager.setImportance(sbn.getPackageName(), sbn.getUid(), progress); } catch (RemoteException e) { // :( } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java new file mode 100644 index 000000000000..4491ebde742b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; + +import com.android.systemui.Interpolators; +import com.android.systemui.R; + +public class NotificationSettingsIconRow extends FrameLayout implements View.OnClickListener { + + public interface SettingsIconRowListener { + /** + * Called when the gear behind a notification is touched. + */ + public void onGearTouched(ExpandableNotificationRow row); + } + + private ExpandableNotificationRow mParent; + private AlphaOptimizedImageView mGearIcon; + private float mHorizSpaceForGear; + private SettingsIconRowListener mListener; + + private ValueAnimator mFadeAnimator; + private boolean mSettingsFadedIn = false; + private boolean mAnimating = false; + private boolean mOnLeft = true; + + public NotificationSettingsIconRow(Context context) { + this(context, null); + } + + public NotificationSettingsIconRow(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public NotificationSettingsIconRow(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public NotificationSettingsIconRow(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes) { + super(context, attrs); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + mGearIcon = (AlphaOptimizedImageView) findViewById(R.id.gear_icon); + mGearIcon.setOnClickListener(this); + setOnClickListener(this); + mHorizSpaceForGear = + getResources().getDimensionPixelOffset(R.dimen.notification_gear_width); + resetState(); + } + + public void setGearListener(SettingsIconRowListener listener) { + mListener = listener; + } + + public void setNotificationRowParent(ExpandableNotificationRow parent) { + mParent = parent; + } + + public ExpandableNotificationRow getNotificationParent() { + return mParent; + } + + public void resetState() { + setGearAlpha(0f); + mAnimating = false; + setIconLocation(true /* on left */); + } + + private void setGearAlpha(float alpha) { + if (alpha == 0) { + mSettingsFadedIn = false; // Can fade in again once it's gone. + mGearIcon.setVisibility(View.INVISIBLE); + } else { + if (alpha == 1) { + mSettingsFadedIn = true; + } + mGearIcon.setVisibility(View.VISIBLE); + } + mGearIcon.setAlpha(alpha); + } + + /** + * Returns the horizontal space in pixels required to display the gear behind a notification. + */ + public float getSpaceForGear() { + return mHorizSpaceForGear; + } + + /** + * Indicates whether the gear is visible at 1 alpha. Does not indicate + * if entire view is visible. + */ + public boolean isVisible() { + return mSettingsFadedIn; + } + + public void cancelFadeAnimator() { + if (mFadeAnimator != null) { + mFadeAnimator.cancel(); + } + } + + public void updateSettingsIcons(final float transX, final float size) { + if (mAnimating || (mGearIcon.getAlpha() == 0)) { + // Don't adjust when animating or settings aren't visible + return; + } + setIconLocation(transX > 0 /* fromLeft */); + final float fadeThreshold = size * 0.3f; + final float absTrans = Math.abs(transX); + float desiredAlpha = 0; + + if (absTrans <= fadeThreshold) { + desiredAlpha = 1; + } else { + desiredAlpha = 1 - ((absTrans - fadeThreshold) / (size - fadeThreshold)); + } + setGearAlpha(desiredAlpha); + } + + public void fadeInSettings(final boolean fromLeft, final float transX, + final float notiThreshold) { + setIconLocation(transX > 0 /* fromLeft */); + mFadeAnimator = ValueAnimator.ofFloat(mGearIcon.getAlpha(), 1); + mFadeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + final float absTrans = Math.abs(transX); + + boolean pastGear = (fromLeft && transX <= notiThreshold) + || (!fromLeft && absTrans <= notiThreshold); + if (pastGear && !mSettingsFadedIn) { + setGearAlpha((float) animation.getAnimatedValue()); + } + } + }); + mFadeAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationCancel(Animator animation) { + super.onAnimationCancel(animation); + mAnimating = false; + mSettingsFadedIn = false; + } + + @Override + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + mAnimating = true; + } + + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + mAnimating = false; + mSettingsFadedIn = true; + } + }); + mFadeAnimator.setInterpolator(Interpolators.ALPHA_IN); + mFadeAnimator.setDuration(200); + mFadeAnimator.start(); + } + + private void setIconLocation(boolean onLeft) { + if (onLeft == mOnLeft) { + // Same side? Do nothing. + return; + } + + setTranslationX(onLeft ? 0 : (mParent.getWidth() - mHorizSpaceForGear)); + mOnLeft = onLeft; + } + + @Override + public void onClick(View v) { + if (v.getId() == R.id.gear_icon) { + if (mListener != null) { + mListener.onGearTouched(mParent); + } + } else { + // Do nothing when the background is touched. + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java new file mode 100644 index 000000000000..4f3c61e1119d --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui.statusbar.phone; + +import android.app.ActivityManager; +import android.app.IWallpaperManager; +import android.app.IWallpaperManagerCallback; +import android.app.WallpaperManager; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.os.Handler; +import android.os.ParcelFileDescriptor; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; + +import libcore.io.IoUtils; + +/** + * Manages the lockscreen wallpaper. + */ +public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implements Runnable { + + private static final String TAG = "LockscreenWallpaper"; + + private final Context mContext; + private final PhoneStatusBar mBar; + private final IWallpaperManager mService; + private final Handler mH; + + private boolean mCached; + private Bitmap mCache; + private int mUserId; + + public LockscreenWallpaper(Context ctx, PhoneStatusBar bar, Handler h) { + mContext = ctx; + mBar = bar; + mH = h; + mService = IWallpaperManager.Stub.asInterface( + ServiceManager.getService(Context.WALLPAPER_SERVICE)); + mUserId = ActivityManager.getCurrentUser(); + + try { + mService.setLockWallpaperCallback(this); + } catch (RemoteException e) { + Log.e(TAG, "System dead?" + e); + } + } + + public Bitmap getBitmap() { + try { + if (mCached) { + return mCache; + } + if (!mService.isWallpaperSupported(mContext.getOpPackageName())) { + mCached = true; + mCache = null; + return null; + } + ParcelFileDescriptor fd = mService.getWallpaper(null, WallpaperManager.FLAG_SET_LOCK, + new Bundle(), mUserId); + if (fd != null) { + try { + BitmapFactory.Options options = new BitmapFactory.Options(); + mCache = BitmapFactory.decodeFileDescriptor( + fd.getFileDescriptor(), null, options); + mCached = true; + return mCache; + } catch (OutOfMemoryError e) { + Log.w(TAG, "Can't decode file", e); + return null; + } finally { + IoUtils.closeQuietly(fd); + } + } else { + mCached = true; + mCache = null; + return null; + } + } catch (RemoteException e) { + Log.e(TAG, "System dead?" + e); + return null; + } + } + + public void setUser(int user) { + if (user != mUserId) { + mCached = false; + mUserId = user; + } + } + + @Override + public void onWallpaperChanged() { + // Called on Binder thread. + mH.removeCallbacks(this); + mH.post(this); + } + + @Override + public void run() { + // Called in response to onWallpaperChanged on the main thread. + mCached = false; + mCache = null; + getBitmap(); + mBar.updateMediaMetaData(true /* metaDataChanged */, true /* allowEnterAnimation */); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index 6698076471c2..e53f044f4295 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -512,6 +512,11 @@ public class NavigationBarView extends LinearLayout { } }); } + + @Override + public void onDockedStackMinimizedChanged(boolean minimized, long animDuration) + throws RemoteException { + } }); } catch (RemoteException e) { Log.e(TAG, "Failed registering docked stack exists listener", e); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 401d405e83b9..1089852191fd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -23,6 +23,7 @@ import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.IActivityManager; +import android.app.IWallpaperManagerCallback; import android.app.Notification; import android.app.PendingIntent; import android.app.StatusBarManager; @@ -115,7 +116,7 @@ import com.android.systemui.classifier.FalsingManager; import com.android.systemui.doze.DozeHost; import com.android.systemui.doze.DozeLog; import com.android.systemui.keyguard.KeyguardViewMediator; -import com.android.systemui.qs.QSDetail; +import com.android.systemui.qs.QSContainer; import com.android.systemui.qs.QSPanel; import com.android.systemui.recents.ScreenPinningRequest; import com.android.systemui.recents.events.EventBus; @@ -248,9 +249,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private static final boolean ONLY_CORE_APPS; /** If true, the lockscreen will show a distinct wallpaper */ - private static final boolean ENABLE_LOCKSCREEN_WALLPAPER = - !ActivityManager.isLowRamDeviceStatic() - && SystemProperties.getBoolean("debug.lockscreen_wallpaper", false); + private static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true; /* If true, the device supports freeform window management. * This affects the status bar UI. */ @@ -296,6 +295,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, AccessibilityController mAccessibilityController; FingerprintUnlockController mFingerprintUnlockController; LightStatusBarController mLightStatusBarController; + private LockscreenWallpaper mLockscreenWallpaper; int mNaturalBarHeight = -1; @@ -746,6 +746,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById( R.id.notification_stack_scroller); mStackScroller.setLongPressListener(getNotificationLongClicker()); + mStackScroller.setGearDisplayedListener(getGearDisplayedListener()); mStackScroller.setPhoneStatusBar(this); mStackScroller.setGroupManager(mGroupManager); mStackScroller.setHeadsUpManager(mHeadsUpManager); @@ -792,6 +793,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mKeyguardBottomArea.getLockIcon()); mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController); + if (ENABLE_LOCKSCREEN_WALLPAPER) { + mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler); + } + // set the initial view visibility setAreThereNotifications(); @@ -867,13 +872,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mCastController, mFlashlightController, mUserSwitcherController, mUserInfoController, mKeyguardMonitor, mSecurityController, mBatteryController, mIconController); - mQSPanel.setHost(qsh); mQSPanel.setTiles(qsh.getTiles()); mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow); mQSPanel.setBrightnessMirror(mBrightnessMirrorController); - mHeader.setQSPanel(mQSPanel); - QSDetail qsDetail = (QSDetail) mStatusBarWindow.findViewById(R.id.qs_detail); - qsDetail.setHost(qsh); + QSContainer qsContainer = (QSContainer) mStatusBarWindow.findViewById( + R.id.quick_settings_container); + qsContainer.setHost(qsh); qsh.addCallback(new QSTileHost.Callback() { @Override public void onTilesChanged() { @@ -1819,7 +1823,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, }; /** - * Refresh or remove lockscreen artwork from media metadata. + * Refresh or remove lockscreen artwork from media metadata or the lockscreen wallpaper. */ public void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation) { if (!SHOW_LOCKSCREEN_MEDIA_ARTWORK) return; @@ -1847,10 +1851,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } } if (ENABLE_LOCKSCREEN_WALLPAPER && artworkBitmap == null) { - // TODO: use real lockscreen wallpaper. - WallpaperManager wallpaperManager = mContext - .getSystemService(WallpaperManager.class); - artworkBitmap = wallpaperManager.getBitmap(); + artworkBitmap = mLockscreenWallpaper.getBitmap(); } final boolean hasArtwork = artworkBitmap != null; @@ -3084,10 +3085,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, else if (Intent.ACTION_SCREEN_ON.equals(action)) { notifyNavigationBarScreenOn(true); } - else if (ENABLE_LOCKSCREEN_WALLPAPER - && Intent.ACTION_WALLPAPER_CHANGED.equals(action)) { - updateMediaMetaData(true, true); - } } }; @@ -3173,6 +3170,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, resetUserSetupObserver(); setControllerUsers(); clearCurrentMediaNotification(); + mLockscreenWallpaper.setUser(newUserId); updateMediaMetaData(true, false); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index df5a62229633..6550c8736164 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -456,11 +456,9 @@ public class PhoneStatusBarPolicy implements Callback, RotationLockController.Ro mIconController.setIcon(mSlotRotate, R.drawable.stat_sys_rotate_landscape, mContext.getString(R.string.accessibility_rotation_lock_on_landscape)); } + mIconController.setIconVisibility(mSlotRotate, true); } else { - mIconController.setIcon(mSlotRotate, portrait - ? R.drawable.stat_sys_auto_rotate_portrait - : R.drawable.stat_sys_auto_rotate_landscape, - mContext.getString(R.string.accessibility_rotation_lock_off)); + mIconController.setIconVisibility(mSlotRotate, false); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java index 2af2009ac505..80afb9a3c705 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java @@ -57,7 +57,7 @@ import com.android.systemui.qs.tiles.WorkModeTile; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.BluetoothController; import com.android.systemui.statusbar.policy.CastController; -import com.android.systemui.statusbar.policy.DisplayController; +import com.android.systemui.statusbar.policy.NightModeController; import com.android.systemui.statusbar.policy.FlashlightController; import com.android.systemui.statusbar.policy.HotspotController; import com.android.systemui.statusbar.policy.KeyguardMonitor; @@ -68,7 +68,7 @@ import com.android.systemui.statusbar.policy.SecurityController; import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.statusbar.policy.ZenModeController; -import com.android.systemui.tuner.ColorMatrixTile; +import com.android.systemui.tuner.NightModeTile; import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService.Tunable; @@ -108,7 +108,7 @@ public final class QSTileHost implements QSTile.Host, Tunable { private final TileServices mServices; private final List<Callback> mCallbacks = new ArrayList<>(); - private final DisplayController mDisplayController; + private final NightModeController mNightModeController; private final AutoTileManager mAutoTiles; private final ManagedProfileController mProfileController; private View mHeader; @@ -137,7 +137,7 @@ public final class QSTileHost implements QSTile.Host, Tunable { mSecurity = security; mBattery = battery; mIconController = iconController; - mDisplayController = new DisplayController(mContext); + mNightModeController = new NightModeController(mContext, true); mProfileController = new ManagedProfileController(this); final HandlerThread ht = new HandlerThread(QSTileHost.class.getSimpleName(), @@ -292,8 +292,8 @@ public final class QSTileHost implements QSTile.Host, Tunable { return mIconController; } - public DisplayController getDisplayController() { - return mDisplayController; + public NightModeController getNightModeController() { + return mNightModeController; } public ManagedProfileController getManagedProfileController() { @@ -422,8 +422,8 @@ public final class QSTileHost implements QSTile.Host, Tunable { else if (tileSpec.equals("user")) return new UserTile(this); else if (tileSpec.equals("battery")) return new BatteryTile(this); else if (tileSpec.equals("saver")) return new DataSaverTile(this); - else if (tileSpec.equals(ColorMatrixTile.COLOR_MATRIX_SPEC)) - return new ColorMatrixTile(this); + else if (tileSpec.equals(NightModeTile.NIGHT_MODE_SPEC)) + return new NightModeTile(this); // Intent tiles. else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(this,tileSpec); else if (tileSpec.startsWith(CustomTile.PREFIX)) return CustomTile.create(this,tileSpec); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java index bd5bac2506fb..ab8067ddebbe 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java @@ -34,6 +34,7 @@ import android.widget.Toast; import com.android.keyguard.KeyguardStatusView; import com.android.systemui.FontSizeUtils; import com.android.systemui.R; +import com.android.systemui.qs.QSAnimator; import com.android.systemui.qs.QSPanel; import com.android.systemui.qs.QSTile; import com.android.systemui.qs.QuickQSPanel; @@ -50,7 +51,7 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements private static final String TAG = "QuickStatusBarHeader"; - private static final float EXPAND_INDICATOR_THRESHOLD = .8f; + private static final float EXPAND_INDICATOR_THRESHOLD = .93f; private ActivityStarter mActivityStarter; private NextAlarmController mNextAlarmController; @@ -89,6 +90,7 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements private TouchAnimator mFirstHalfAnimator; private TouchAnimator mDateSizeAnimator; private TouchAnimator mAlarmTranslation; + private TouchAnimator mSettingsAlpha; private float mExpansionAmount; public QuickStatusBarHeader(Context context, AttributeSet attrs) { @@ -164,18 +166,16 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements mAnimator = new TouchAnimator.Builder() .addFloat(mSettingsContainer, "translationY", -mGearTranslation, 0) .addFloat(mMultiUserSwitch, "translationY", -mGearTranslation, 0) - .addFloat(mSettingsButton, "rotation", -90, 0) .setListener(this) .build(); mSecondHalfAnimator = new TouchAnimator.Builder() - .addFloat(mSettingsButton, "rotation", -90, 0) + .addFloat(mSettingsButton, "rotation", -180, 0) .addFloat(mAlarmStatus, "alpha", 0, 1) .addFloat(mEmergencyOnly, "alpha", 0, 1) .setStartDelay(.5f) .build(); mFirstHalfAnimator = new TouchAnimator.Builder() .addFloat(mAlarmStatusCollapsed, "alpha", 1, 0) - .addFloat(mHeaderQsPanel, "alpha", 1, 0) .setEndDelay(.5f) .build(); mDateSizeAnimator = new TouchAnimator.Builder() @@ -183,6 +183,11 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements .addFloat(mDateTimeGroup, "scaleY", 1, mDateScaleFactor) .setStartDelay(.36f) .build(); + mSettingsAlpha = new TouchAnimator.Builder() + .addFloat(mSettingsContainer, "alpha", 0, 1) + .addFloat(mMultiUserSwitch, "alpha", 0, 1) + .setStartDelay(QSAnimator.EXPANDED_TILE_DELAY) + .build(); } @Override @@ -221,6 +226,7 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements mFirstHalfAnimator.setPosition(headerExpansionFraction); mDateSizeAnimator.setPosition(headerExpansionFraction); mAlarmTranslation.setPosition(headerExpansionFraction); + mSettingsAlpha.setPosition(headerExpansionFraction); updateAlarmVisibilities(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DisplayController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DisplayController.java deleted file mode 100644 index d47050c18519..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DisplayController.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package com.android.systemui.statusbar.policy; - -import libcore.util.Objects; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.res.Configuration; -import android.provider.Settings; - -import com.android.systemui.R; -import com.android.systemui.tuner.TunerService; - -import java.util.ArrayList; - -public class DisplayController implements TunerService.Tunable { - - public static final String COLOR_MATRIX_CUSTOM_ENABLED = "tuner_color_custom_enabled"; - public static final String COLOR_MATRIX_CUSTOM_VALUES = "tuner_color_custom_values"; - - public static final String COLOR_STATE = "sysui_color_matrix_state"; - - public static final int COLOR_STATE_DISABLED = 0; - public static final int COLOR_STATE_ENABLED = 1; - public static final int COLOR_STATE_AUTO = 2; - - public static final String AUTO_STRING = "auto_mode"; - public static final String NONE_STRING = "none"; - - public static final int AUTO_INDEX = 2; - public static final int CUSTOM_INDEX = 3; - - // Night mode ~= 3400 K - private static final float[] NIGHT_VALUES = new float[] { - 1, 0, 0, 0, - 0, .754f, 0, 0, - 0, 0, .516f, 0, - 0, 0, 0, 1, - }; - public static final float[] IDENTITY_MATRIX = new float[] { - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1, - }; - - private final ArrayList<Listener> mListeners = new ArrayList<>(); - - private final Context mContext; - - private String mCurrentValue; - private boolean mListening; - - public DisplayController(Context context) { - mContext = context; - TunerService.get(mContext).addTunable(this, COLOR_STATE, - Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX); - } - - public void addListener(Listener listener) { - mListeners.add(listener); - listener.onCurrentMatrixChanged(); - } - - public void removeListener(Listener listener) { - mListeners.remove(listener); - } - - public boolean isEnabled() { - return TunerService.get(mContext).getValue(COLOR_STATE, COLOR_STATE_DISABLED) - != COLOR_STATE_DISABLED; - } - - public boolean isAuto() { - return mListening; - } - - public void setAuto(boolean auto) { - TunerService.get(mContext).setValue(COLOR_STATE, auto ? COLOR_STATE_AUTO - : COLOR_STATE_DISABLED); - } - - public boolean isCustomSet() { - return isCustomEnabled() && Objects.equal(getCurrentMatrix(), getCustomValues()); - } - - public String getCurrentMatrix() { - return mCurrentValue; - } - - public String getCustomValues() { - return TunerService.get(mContext).getValue(COLOR_MATRIX_CUSTOM_VALUES); - } - - public boolean isCustomEnabled() { - return TunerService.get(mContext).getValue(COLOR_MATRIX_CUSTOM_ENABLED, 0) != 0; - } - - @Override - public void onTuningChanged(String key, String newValue) { - if (Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX.equals(key)) { - mCurrentValue = newValue; - for (int i = 0; i < mListeners.size(); i++) { - mListeners.get(i).onCurrentMatrixChanged(); - } - } else if (COLOR_STATE.equals(key)) { - final boolean listening = newValue != null - && Integer.parseInt(newValue) == COLOR_STATE_AUTO; - if (listening && !mListening) { - mListening = true; - mContext.registerReceiver(mReceiver, - new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED)); - updateNightMode(); - } else if (!listening && mListening) { - mListening = false; - mContext.unregisterReceiver(mReceiver); - } - for (int i = 0; i < mListeners.size(); i++) { - mListeners.get(i).onCurrentMatrixChanged(); - } - } - } - - private void updateNightMode() { - final int uiMode = mContext.getResources().getConfiguration().uiMode; - final boolean isNightMode = (uiMode & Configuration.UI_MODE_NIGHT_MASK) - == Configuration.UI_MODE_NIGHT_YES; - String value = null; - if (isNightMode) { - value = toString(NIGHT_VALUES); - } - TunerService.get(mContext).setValue(Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, - value); - } - - private final BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (Intent.ACTION_CONFIGURATION_CHANGED.equals(intent.getAction())) { - updateNightMode(); - } - } - }; - - public interface Listener { - void onCurrentMatrixChanged(); - } - - public static String[] getColorTransforms(Context context) { - return new String[] { - NONE_STRING, - toString(NIGHT_VALUES), - AUTO_STRING, // Blank spot for auto values - null, // Blank spot for custom values - }; - } - - public static CharSequence[] getColorTitles(Context context) { - // TODO: Move to string array resource. - return new CharSequence[]{ - context.getString(R.string.color_matrix_none), - context.getString(R.string.color_matrix_night), - context.getString(R.string.color_matrix_auto), - context.getString(R.string.color_matrix_custom), - }; - } - - public static String toString(float[] values) { - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < values.length; i++) { - if (builder.length() != 0) { - builder.append(','); - } - builder.append(values[i]); - } - return builder.toString(); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java index 500d60359145..047f14def5cb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java @@ -21,7 +21,6 @@ public interface HotspotController { void removeCallback(Callback callback); boolean isHotspotEnabled(); void setHotspotEnabled(boolean enabled); - boolean isTetheringAllowed(); public interface Callback { void onHotspotChanged(boolean enabled); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java index 07b74094ffb2..f03d9e9dce84 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java @@ -16,15 +16,12 @@ package com.android.systemui.statusbar.policy; -import android.app.ActivityManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.wifi.WifiManager; -import android.os.UserHandle; -import android.os.UserManager; import android.util.Log; import java.io.FileDescriptor; @@ -40,8 +37,6 @@ public class HotspotControllerImpl implements HotspotController { private final Receiver mReceiver = new Receiver(); private final ConnectivityManager mConnectivityManager; private final Context mContext; - private final UserManager mUserManager; - private final int mCurrentUser; private int mHotspotState; @@ -49,8 +44,6 @@ public class HotspotControllerImpl implements HotspotController { mContext = context; mConnectivityManager = (ConnectivityManager) context.getSystemService( Context.CONNECTIVITY_SERVICE); - mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); - mCurrentUser = ActivityManager.getCurrentUser(); } public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { @@ -95,12 +88,6 @@ public class HotspotControllerImpl implements HotspotController { return mHotspotState == WifiManager.WIFI_AP_STATE_ENABLED; } - @Override - public boolean isTetheringAllowed() { - return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING, - UserHandle.of(mCurrentUser)); - } - static final class OnStartTetheringCallback extends ConnectivityManager.OnStartTetheringCallback { @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java index 401943e1c321..29a8981fd89e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java @@ -21,7 +21,6 @@ public interface LocationController { boolean setLocationEnabled(boolean enabled); void addSettingsChangedCallback(LocationSettingsChangeCallback cb); void removeSettingsChangedCallback(LocationSettingsChangeCallback cb); - boolean isUserLocationRestricted(); /** * A callback for change in location settings (the user has enabled/disabled location). diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java index 436a40d25bfa..8d84be485c91 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java @@ -52,7 +52,6 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio private AppOpsManager mAppOpsManager; private StatusBarManager mStatusBarManager; - private final int mCurrentUser; private boolean mAreActiveLocationRequests; @@ -74,7 +73,6 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); mStatusBarManager = (StatusBarManager) context.getSystemService(Context.STATUS_BAR_SERVICE); - mCurrentUser = ActivityManager.getCurrentUser(); // Examine the current location state and initialize the status view. updateActiveLocationRequests(); @@ -105,6 +103,10 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio * @return true if attempt to change setting was successful. */ public boolean setLocationEnabled(boolean enabled) { + int currentUserId = ActivityManager.getCurrentUser(); + if (isUserLocationRestricted(currentUserId)) { + return false; + } final ContentResolver cr = mContext.getContentResolver(); // When enabling location, a user consent dialog will pop up, and the // setting won't be fully enabled until the user accepts the agreement. @@ -113,7 +115,7 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio // QuickSettings always runs as the owner, so specifically set the settings // for the current foreground user. return Settings.Secure - .putIntForUser(cr, Settings.Secure.LOCATION_MODE, mode, mCurrentUser); + .putIntForUser(cr, Settings.Secure.LOCATION_MODE, mode, currentUserId); } /** @@ -131,10 +133,10 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio /** * Returns true if the current user is restricted from using location. */ - public boolean isUserLocationRestricted() { + private boolean isUserLocationRestricted(int userId) { final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); return um.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, - UserHandle.of(mCurrentUser)); + UserHandle.of(userId)); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java new file mode 100644 index 000000000000..0b1911bb15fc --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package com.android.systemui.statusbar.policy; + +import libcore.util.Objects; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.opengl.Matrix; +import android.provider.Settings; +import android.provider.Settings.Secure; +import android.util.MathUtils; + +import com.android.systemui.tuner.TunerService; + +import java.util.ArrayList; + +/** + * Listens for changes to twilight from the TwilightService. + * + * Also pushes the current matrix to accessibility based on the current twilight + * and various tuner settings. + */ +public class NightModeController implements TunerService.Tunable { + + public static final String NIGHT_MODE_ADJUST_TINT = "tuner_night_mode_adjust_tint"; + private static final String COLOR_MATRIX_CUSTOM_VALUES = "tuner_color_custom_values"; + + private static final String ACTION_TWILIGHT_CHANGED = "android.intent.action.TWILIGHT_CHANGED"; + + private static final String EXTRA_IS_NIGHT = "isNight"; + private static final String EXTRA_AMOUNT = "amount"; + + // Night mode ~= 3400 K + private static final float[] NIGHT_VALUES = new float[] { + 1, 0, 0, 0, + 0, .754f, 0, 0, + 0, 0, .516f, 0, + 0, 0, 0, 1, + }; + public static final float[] IDENTITY_MATRIX = new float[] { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + }; + + private final ArrayList<Listener> mListeners = new ArrayList<>(); + + private final Context mContext; + + // This is whether or not this is the main NightMode controller in SysUI that should be + // updating relevant color matrixes or if its in the tuner process getting current state + // for UI. + private final boolean mUpdateMatrix; + + private float[] mCustomMatrix; + private boolean mListening; + private boolean mAdjustTint; + + private boolean mIsNight; + private float mAmount; + private boolean mIsAuto; + + public NightModeController(Context context) { + this(context, false); + } + + public NightModeController(Context context, boolean updateMatrix) { + mContext = context; + mUpdateMatrix = updateMatrix; + TunerService.get(mContext).addTunable(this, NIGHT_MODE_ADJUST_TINT, + COLOR_MATRIX_CUSTOM_VALUES, Secure.TWILIGHT_MODE); + } + + public void setNightMode(boolean isNight) { + if (mIsAuto) { + if (mIsNight != isNight) { + TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE, isNight + ? Secure.TWILIGHT_MODE_AUTO_OVERRIDE_ON + : Secure.TWILIGHT_MODE_AUTO_OVERRIDE_OFF); + } else { + TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE, + Secure.TWILIGHT_MODE_AUTO); + } + } else { + TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE, isNight + ? Secure.TWILIGHT_MODE_LOCKED_ON : Secure.TWILIGHT_MODE_LOCKED_OFF); + } + } + + public void setAuto(boolean auto) { + mIsAuto = auto; + if (auto) { + TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE, Secure.TWILIGHT_MODE_AUTO); + } else { + // Lock into the current state + TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE, mIsNight + ? Secure.TWILIGHT_MODE_LOCKED_ON : Secure.TWILIGHT_MODE_LOCKED_OFF); + } + } + + public boolean isAuto() { + return mIsAuto; + } + + public void setAdjustTint(Boolean newValue) { + TunerService.get(mContext).setValue(NIGHT_MODE_ADJUST_TINT, ((Boolean) newValue) ? 1 : 0); + } + + public void addListener(Listener listener) { + mListeners.add(listener); + listener.onNightModeChanged(); + updateListening(); + } + + public void removeListener(Listener listener) { + mListeners.remove(listener); + updateListening(); + } + + private void updateListening() { + boolean shouldListen = mListeners.size() != 0 || (mUpdateMatrix && mAdjustTint); + if (shouldListen == mListening) return; + mListening = shouldListen; + if (mListening) { + mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_TWILIGHT_CHANGED)); + } else { + mContext.unregisterReceiver(mReceiver); + } + } + + public boolean isEnabled() { + if (!mListening) { + updateNightMode(mContext.registerReceiver(null, + new IntentFilter(ACTION_TWILIGHT_CHANGED))); + } + return mIsNight; + } + + public String getCustomValues() { + return TunerService.get(mContext).getValue(COLOR_MATRIX_CUSTOM_VALUES); + } + + public void setCustomValues(String values) { + TunerService.get(mContext).setValue(COLOR_MATRIX_CUSTOM_VALUES, values); + } + + @Override + public void onTuningChanged(String key, String newValue) { + if (COLOR_MATRIX_CUSTOM_VALUES.equals(key)) { + mCustomMatrix = newValue != null ? toValues(newValue) : null; + updateCurrentMatrix(); + } else if (NIGHT_MODE_ADJUST_TINT.equals(key)) { + mAdjustTint = newValue == null || Integer.parseInt(newValue) != 0; + updateListening(); + updateCurrentMatrix(); + } else if (Secure.TWILIGHT_MODE.equals(key)) { + mIsAuto = newValue != null && Integer.parseInt(newValue) >= Secure.TWILIGHT_MODE_AUTO; + } + } + + private void updateCurrentMatrix() { + if (!mUpdateMatrix) return; + if ((!mAdjustTint || mAmount == 0) && mCustomMatrix == null) { + TunerService.get(mContext).setValue(Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, null); + return; + } + float[] values = scaleValues(IDENTITY_MATRIX, NIGHT_VALUES, mAdjustTint ? mAmount : 0); + if (mCustomMatrix != null) { + values = multiply(values, mCustomMatrix); + } + TunerService.get(mContext).setValue(Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, + toString(values)); + } + + private void updateNightMode(Intent intent) { + mIsNight = intent.getBooleanExtra(EXTRA_IS_NIGHT, false); + mAmount = intent.getFloatExtra(EXTRA_AMOUNT, 0); + } + + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (ACTION_TWILIGHT_CHANGED.equals(intent.getAction())) { + updateNightMode(intent); + updateCurrentMatrix(); + for (int i = 0; i < mListeners.size(); i++) { + mListeners.get(i).onNightModeChanged(); + } + } + } + }; + + public interface Listener { + void onNightModeChanged(); + void onTwilightAutoChanged(); + } + + private static float[] multiply(float[] matrix, float[] other) { + if (matrix == null) { + return other; + } + float[] result = new float[16]; + Matrix.multiplyMM(result, 0, matrix, 0, other, 0); + return result; + } + + private float[] scaleValues(float[] identityMatrix, float[] nightValues, float amount) { + float[] values = new float[identityMatrix.length]; + for (int i = 0; i < values.length; i++) { + values[i] = MathUtils.lerp(identityMatrix[i], nightValues[i], amount); + } + return values; + } + + public static String toString(float[] values) { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < values.length; i++) { + if (builder.length() != 0) { + builder.append(','); + } + builder.append(values[i]); + } + return builder.toString(); + } + + public static float[] toValues(String customValues) { + String[] strValues = customValues.split(","); + float[] values = new float[strValues.length]; + for (int i = 0; i < values.length; i++) { + values[i] = Float.parseFloat(strValues[i]); + } + return values; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java index 6ca7dc8a4566..13369f2e36f5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -210,12 +210,16 @@ public class UserSwitcherController { } } + boolean systemCanCreateUsers = !mUserManager.hasBaseUserRestriction( + UserManager.DISALLOW_ADD_USER, UserHandle.SYSTEM); boolean currentUserCanCreateUsers = currentUserInfo != null && (currentUserInfo.isAdmin() - || currentUserInfo.id == UserHandle.USER_SYSTEM); - boolean canCreateGuest = (currentUserCanCreateUsers || addUsersWhenLocked) + || currentUserInfo.id == UserHandle.USER_SYSTEM) + && systemCanCreateUsers; + boolean anyoneCanCreateUsers = systemCanCreateUsers && addUsersWhenLocked; + boolean canCreateGuest = (currentUserCanCreateUsers || anyoneCanCreateUsers) && guestRecord == null; - boolean canCreateUser = (currentUserCanCreateUsers || addUsersWhenLocked) + boolean canCreateUser = (currentUserCanCreateUsers || anyoneCanCreateUsers) && mUserManager.canAddMoreUsers(); boolean createIsRestricted = !addUsersWhenLocked; @@ -225,7 +229,7 @@ public class UserSwitcherController { guestRecord = new UserRecord(null /* info */, null /* picture */, true /* isGuest */, false /* isCurrent */, false /* isAddUser */, createIsRestricted); - checkIfAddUserDisallowed(guestRecord); + checkIfAddUserDisallowedByAdminOnly(guestRecord); records.add(guestRecord); } } else { @@ -238,7 +242,7 @@ public class UserSwitcherController { UserRecord addUserRecord = new UserRecord(null /* info */, null /* picture */, false /* isGuest */, false /* isCurrent */, true /* isAddUser */, createIsRestricted); - checkIfAddUserDisallowed(addUserRecord); + checkIfAddUserDisallowedByAdminOnly(addUserRecord); records.add(addUserRecord); } @@ -615,10 +619,11 @@ public class UserSwitcherController { } } - private void checkIfAddUserDisallowed(UserRecord record) { + private void checkIfAddUserDisallowedByAdminOnly(UserRecord record) { EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext, UserManager.DISALLOW_ADD_USER, ActivityManager.getCurrentUser()); - if (admin != null) { + if (admin != null && !RestrictedLockUtils.hasBaseUserRestriction(mContext, + UserManager.DISALLOW_ADD_USER, ActivityManager.getCurrentUser())) { record.isDisabledByAdmin = true; record.enforcedAdmin = admin; } else { @@ -683,7 +688,7 @@ public class UserSwitcherController { } public final QSTile.DetailAdapter userDetailAdapter = new QSTile.DetailAdapter() { - private final Intent USER_SETTINGS_INTENT = new Intent("android.settings.USER_SETTINGS"); + private final Intent USER_SETTINGS_INTENT = new Intent(Settings.ACTION_USER_SETTINGS); @Override public CharSequence getTitle() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index bf4245b5e7ed..f078b53a9e10 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -18,10 +18,12 @@ package com.android.systemui.statusbar.stack; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.animation.TimeAnimator; import android.animation.ValueAnimator; +import android.animation.ValueAnimator.AnimatorUpdateListener; import android.annotation.Nullable; import android.content.Context; import android.content.res.Configuration; @@ -32,6 +34,7 @@ import android.graphics.PointF; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; +import android.os.Handler; import android.util.AttributeSet; import android.util.Log; import android.util.Pair; @@ -56,6 +59,8 @@ import com.android.systemui.statusbar.EmptyShadeView; import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.ExpandableView; import com.android.systemui.statusbar.NotificationOverflowContainer; +import com.android.systemui.statusbar.NotificationSettingsIconRow; +import com.android.systemui.statusbar.NotificationSettingsIconRow.SettingsIconRowListener; import com.android.systemui.statusbar.StackScrollerDecorView; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.NotificationGroupManager; @@ -72,7 +77,8 @@ import java.util.HashSet; */ public class NotificationStackScrollLayout extends ViewGroup implements SwipeHelper.Callback, ExpandHelper.Callback, ScrollAdapter, - ExpandableView.OnHeightChangedListener, NotificationGroupManager.OnGroupChangeListener { + ExpandableView.OnHeightChangedListener, NotificationGroupManager.OnGroupChangeListener, + SettingsIconRowListener { public static final float BACKGROUND_ALPHA_DIMMED = 0.7f; private static final String TAG = "StackScroller"; @@ -207,6 +213,11 @@ public class NotificationStackScrollLayout extends ViewGroup */ private int mMaxScrollAfterExpand; private SwipeHelper.LongPressListener mLongPressListener; + private GearDisplayedListener mGearDisplayedListener; + + private NotificationSettingsIconRow mCurrIconRow; + private View mTranslatingParentView; + private View mGearExposedView; /** * Should in this touch motion only be scrolling allowed? It's true when the scroller was @@ -304,8 +315,7 @@ public class NotificationStackScrollLayout extends ViewGroup minHeight, maxHeight); mExpandHelper.setEventSource(this); mExpandHelper.setScrollAdapter(this); - - mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, getContext()); + mSwipeHelper = new NotificationSwipeHelper(SwipeHelper.X, this, getContext()); mSwipeHelper.setLongPressListener(mLongPressListener); mStackScrollAlgorithm = new StackScrollAlgorithm(context); initView(context); @@ -321,6 +331,13 @@ public class NotificationStackScrollLayout extends ViewGroup } @Override + public void onGearTouched(ExpandableNotificationRow row) { + if (mLongPressListener != null) { + mLongPressListener.onLongPress(row, 0, 0); + } + } + + @Override protected void onDraw(Canvas canvas) { canvas.drawRect(0, mCurrentBounds.top, getWidth(), mCurrentBounds.bottom, mBackgroundPaint); if (DEBUG) { @@ -630,6 +647,10 @@ public class NotificationStackScrollLayout extends ViewGroup mLongPressListener = listener; } + public void setGearDisplayedListener(GearDisplayedListener listener) { + mGearDisplayedListener = listener; + } + public void setQsContainer(ViewGroup qsContainer) { mQsContainer = qsContainer; } @@ -666,7 +687,7 @@ public class NotificationStackScrollLayout extends ViewGroup } @Override - public void onChildSnappedBack(View animView) { + public void onChildSnappedBack(View animView, float targetLeft) { mAmbientState.onDragFinished(animView); if (!mDragAnimPendingChildren.contains(animView)) { if (mAnimationsEnabled) { @@ -678,6 +699,13 @@ public class NotificationStackScrollLayout extends ViewGroup // We start the swipe and snap back in the same frame, we don't want any animation mDragAnimPendingChildren.remove(animView); } + + if (targetLeft == 0 && mCurrIconRow != null) { + mCurrIconRow.resetState(); + if (mGearExposedView != null && mGearExposedView == mTranslatingParentView) { + mGearExposedView = null; + } + } } @Override @@ -686,7 +714,7 @@ public class NotificationStackScrollLayout extends ViewGroup mScrimController.setTopHeadsUpDragAmount(animView, Math.min(Math.abs(swipeProgress - 1.0f), 1.0f)); } - return false; + return true; // Don't fade out the notification } public void onBeginDrag(View v) { @@ -726,8 +754,21 @@ public class NotificationStackScrollLayout extends ViewGroup return mPhoneStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f; } + @Override public View getChildAtPosition(MotionEvent ev) { - return getChildAtPosition(ev.getX(), ev.getY()); + View child = getChildAtPosition(ev.getX(), ev.getY()); + if (child instanceof ExpandableNotificationRow) { + ExpandableNotificationRow row = (ExpandableNotificationRow) child; + ExpandableNotificationRow parent = row.getNotificationParent(); + if (mGearExposedView != null && parent != null + && parent.areChildrenExpanded() && mGearExposedView == parent) { + // In this case the group is expanded and showing the gear for the + // group, further interaction should apply to the group, not any + // child notifications so we use the parent of the child. + child = row.getNotificationParent(); + } + } + return child; } public ExpandableView getClosestChildAtRawPosition(float touchX, float touchY) { @@ -841,10 +882,6 @@ public class NotificationStackScrollLayout extends ViewGroup return mScrollingEnabled; } - public View getChildContentView(View v) { - return v; - } - public boolean canChildBeDismissed(View v) { return StackScrollAlgorithm.canChildBeDismissed(v); } @@ -3008,6 +3045,9 @@ public class NotificationStackScrollLayout extends ViewGroup disableClipOptimization(); } handleDismissAllClipping(); + if (mCurrIconRow != null & mCurrIconRow.isVisible()) { + mCurrIconRow.getNotificationParent().animateTranslateNotification(0 /* left target */); + } } private void handleDismissAllClipping() { @@ -3268,6 +3308,247 @@ public class NotificationStackScrollLayout extends ViewGroup public void flingTopOverscroll(float velocity, boolean open); } + /** + * A listener that is notified when the gear is shown behind a notification. + */ + public interface GearDisplayedListener { + void onGearDisplayed(ExpandableNotificationRow row); + } + + private class NotificationSwipeHelper extends SwipeHelper { + private static final int MOVE_STATE_LEFT = -1; + private static final int MOVE_STATE_UNDEFINED = 0; + private static final int MOVE_STATE_RIGHT = 1; + + private static final long GEAR_SHOW_DELAY = 60; + + private ArrayList<View> mTranslatingViews = new ArrayList<>(); + private CheckForDrag mCheckForDrag; + private Handler mHandler; + private int mMoveState = MOVE_STATE_UNDEFINED; + + public NotificationSwipeHelper(int swipeDirection, Callback callback, Context context) { + super(swipeDirection, callback, context); + mHandler = new Handler(); + } + + @Override + public void onDownUpdate(View currView) { + // Set the active view + mTranslatingParentView = currView; + + // Reset check for drag gesture + mCheckForDrag = null; + + // Slide back any notifications that might be showing a gear + resetExposedGearView(); + + if (currView instanceof ExpandableNotificationRow) { + // Set the listener for the current row's gear + mCurrIconRow = ((ExpandableNotificationRow) currView).getSettingsRow(); + mCurrIconRow.setGearListener(NotificationStackScrollLayout.this); + + // And the translating children + mTranslatingViews = ((ExpandableNotificationRow) currView).getContentViews(); + } + mMoveState = MOVE_STATE_UNDEFINED; + } + + @Override + public void onMoveUpdate(View view, float translation, float delta) { + final int newMoveState = (delta < 0) ? MOVE_STATE_RIGHT : MOVE_STATE_LEFT; + if (mMoveState != MOVE_STATE_UNDEFINED && mMoveState != newMoveState) { + // Changed directions, make sure we check for drag again. + mCheckForDrag = null; + } + mMoveState = newMoveState; + + if (view instanceof ExpandableNotificationRow) { + ((ExpandableNotificationRow) view).setTranslationForOutline(translation); + if (!isPinnedHeadsUp(view)) { + // Only show the gear if we're not a heads up view. + checkForDrag(); + if (mCurrIconRow != null) { + mCurrIconRow.updateSettingsIcons(translation, getSize(view)); + } + } + } + } + + @Override + public void dismissChild(final View view, float velocity) { + cancelCheckForDrag(); + super.dismissChild(view, velocity); + } + + @Override + public void snapChild(final View animView, final float targetLeft, float velocity) { + final float snapBackThreshold = getSpaceForGear(animView); + final float translation = getTranslation(animView); + final boolean fromLeft = translation > 0; + final float absTrans = Math.abs(translation); + final float notiThreshold = getSize(mTranslatingParentView) * 0.4f; + + boolean pastGear = (fromLeft && translation >= snapBackThreshold * 0.4f + && translation <= notiThreshold) || + (!fromLeft && absTrans >= snapBackThreshold * 0.4f + && absTrans <= notiThreshold); + + if (pastGear && !isPinnedHeadsUp(animView)) { + // bouncity + final float target = fromLeft ? snapBackThreshold : -snapBackThreshold; + mGearExposedView = mTranslatingParentView; + if (mGearDisplayedListener != null + && (animView instanceof ExpandableNotificationRow)) { + mGearDisplayedListener.onGearDisplayed((ExpandableNotificationRow) animView); + } + super.snapChild(animView, target, velocity); + } else { + super.snapChild(animView, 0, velocity); + } + } + + @Override + public void onTranslationUpdate(View animView, float value, boolean canBeDismissed) { + if (mDismissAllInProgress) { + // When dismissing all, we translate the entire view instead. + super.onTranslationUpdate(animView, value, canBeDismissed); + return; + } + if (animView instanceof ExpandableNotificationRow) { + ((ExpandableNotificationRow) animView).setTranslationForOutline(value); + } + if (mCurrIconRow != null) { + mCurrIconRow.updateSettingsIcons(value, getSize(animView)); + } + } + + @Override + public Animator getViewTranslationAnimator(View v, float target, + AnimatorUpdateListener listener) { + if (mDismissAllInProgress) { + // When dismissing all, we translate the entire view instead. + return super.getViewTranslationAnimator(v, target, listener); + } + ArrayList<Animator> animators = new ArrayList<Animator>(); + for (int i = 0; i < mTranslatingViews.size(); i++) { + ObjectAnimator anim = createTranslationAnimation(mTranslatingViews.get(i), target); + animators.add(anim); + if (i == 0 && listener != null) { + anim.addUpdateListener(listener); + } + } + AnimatorSet set = new AnimatorSet(); + set.playTogether(animators); + return set; + } + + @Override + public void setTranslation(View v, float translate) { + if (mDismissAllInProgress) { + // When dismissing all, we translate the entire view instead. + super.setTranslation(v, translate); + return; + } + // Translate the group of views + for (int i = 0; i < mTranslatingViews.size(); i++) { + if (mTranslatingViews.get(i) != null) { + super.setTranslation(mTranslatingViews.get(i), translate); + } + } + } + + @Override + public float getTranslation(View v) { + if (mDismissAllInProgress) { + // When dismissing all, we translate the entire view instead. + return super.getTranslation(v); + } + // All of the views in the list should have same translation, just use first one. + if (mTranslatingViews.size() > 0) { + return super.getTranslation(mTranslatingViews.get(0)); + } + return 0; + } + + + /** + * Returns the horizontal space in pixels required to display the gear behind a + * notification. + */ + private float getSpaceForGear(View view) { + if (view instanceof ExpandableNotificationRow) { + return ((ExpandableNotificationRow) view).getSpaceForGear(); + } + return 0; + } + + private void checkForDrag() { + if (mCheckForDrag == null) { + mCheckForDrag = new CheckForDrag(); + mHandler.postDelayed(mCheckForDrag, GEAR_SHOW_DELAY); + } + } + + private void cancelCheckForDrag() { + if (mCurrIconRow != null) { + mCurrIconRow.cancelFadeAnimator(); + } + mHandler.removeCallbacks(mCheckForDrag); + mCheckForDrag = null; + } + + private final class CheckForDrag implements Runnable { + @Override + public void run() { + final float translation = getTranslation(mTranslatingParentView); + final float absTransX = Math.abs(translation); + final float bounceBackToGearWidth = getSpaceForGear(mTranslatingParentView); + final float notiThreshold = getSize(mTranslatingParentView) * 0.4f; + if (mCurrIconRow != null && absTransX >= bounceBackToGearWidth * 0.4 + && absTransX < notiThreshold) { + // Show icon + mCurrIconRow.fadeInSettings(translation > 0 /* fromLeft */, translation, + notiThreshold); + } else { + // Allow more to be posted if this wasn't a drag. + mCheckForDrag = null; + } + } + } + + private void resetExposedGearView() { + if (mGearExposedView == null || mGearExposedView == mTranslatingParentView) { + // If no gear is showing or it's showing for this view we do nothing. + return; + } + + final View prevGearExposedView = mGearExposedView; + mGearExposedView = null; + + AnimatorListenerAdapter listener = new AnimatorListenerAdapter() { + public void onAnimationEnd(Animator animator) { + if (prevGearExposedView instanceof ExpandableNotificationRow) { + ((ExpandableNotificationRow) prevGearExposedView).getSettingsRow() + .resetState(); + } + } + }; + AnimatorUpdateListener updateListener = new AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + if (prevGearExposedView instanceof ExpandableNotificationRow) { + ((ExpandableNotificationRow) prevGearExposedView) + .setTranslationForOutline((float) animation.getAnimatedValue()); + } + } + }; + Animator set = getViewTranslationAnimator(prevGearExposedView, 0, updateListener); + set.addListener(listener); + set.start(); + } + } + static class AnimationEvent { static AnimationFilter[] FILTERS = new AnimationFilter[] { diff --git a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java new file mode 100644 index 000000000000..8881c7939337 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2016 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.tuner; + +import android.content.Context; +import android.provider.Settings; +import android.support.v7.preference.DropDownPreference; +import android.text.TextUtils; +import android.util.ArraySet; +import android.util.AttributeSet; +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.MetricsProto.MetricsEvent; +import com.android.systemui.statusbar.phone.StatusBarIconController; + +import static com.android.systemui.BatteryMeterDrawable.SHOW_PERCENT_SETTING; + +public class BatteryPreference extends DropDownPreference implements TunerService.Tunable { + + private static final String PERCENT = "percent"; + private static final String DEFAULT = "default"; + private static final String DISABLED = "disabled"; + + private final String mBattery; + private boolean mBatteryEnabled; + private boolean mHasPercentage; + private ArraySet<String> mBlacklist; + private boolean mHasSetValue; + + public BatteryPreference(Context context, AttributeSet attrs) { + super(context, attrs); + mBattery = context.getString(com.android.internal.R.string.status_bar_battery); + setEntryValues(new CharSequence[] {PERCENT, DEFAULT, DISABLED }); + } + + @Override + public void onAttached() { + super.onAttached(); + TunerService.get(getContext()).addTunable(this, StatusBarIconController.ICON_BLACKLIST); + mHasPercentage = Settings.System.getInt(getContext().getContentResolver(), + SHOW_PERCENT_SETTING, 0) != 0; + } + + @Override + public void onDetached() { + TunerService.get(getContext()).removeTunable(this); + super.onDetached(); + } + + @Override + public void onTuningChanged(String key, String newValue) { + if (StatusBarIconController.ICON_BLACKLIST.equals(key)) { + mBlacklist = StatusBarIconController.getIconBlacklist(newValue); + mBatteryEnabled = !mBlacklist.contains(mBattery); + } + if (!mHasSetValue) { + // Because of the complicated tri-state it can end up looping and setting state back to + // what the user didn't choose. To avoid this, just set the state once and rely on the + // preference to handle updates. + mHasSetValue = true; + if (mBatteryEnabled && mHasPercentage) { + setValue(PERCENT); + } else if (mBatteryEnabled) { + setValue(DEFAULT); + } else { + setValue(DISABLED); + } + } + } + + @Override + protected boolean persistString(String value) { + final boolean v = PERCENT.equals(value); + MetricsLogger.action(getContext(), MetricsEvent.TUNER_BATTERY_PERCENTAGE, v); + Settings.System.putInt(getContext().getContentResolver(), SHOW_PERCENT_SETTING, v ? 1 : 0); + if (DISABLED.equals(value)) { + mBlacklist.add(mBattery); + } else { + mBlacklist.remove(mBattery); + } + TunerService.get(getContext()).setValue(StatusBarIconController.ICON_BLACKLIST, + TextUtils.join(",", mBlacklist)); + return true; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/tuner/CalibratePreference.java b/packages/SystemUI/src/com/android/systemui/tuner/CalibratePreference.java new file mode 100644 index 000000000000..ff7be1367388 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/tuner/CalibratePreference.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2016 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.tuner; + +import android.content.Context; +import android.support.v7.preference.DialogPreference; +import android.util.AttributeSet; + +public class CalibratePreference extends DialogPreference { + public CalibratePreference(Context context, AttributeSet attrs) { + super(context, attrs); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java new file mode 100644 index 000000000000..ea92443b7265 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2016 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.tuner; + +import android.content.Context; +import android.support.v7.preference.DropDownPreference; +import android.text.TextUtils; +import android.util.ArraySet; +import android.util.AttributeSet; +import com.android.systemui.statusbar.phone.StatusBarIconController; +import com.android.systemui.statusbar.policy.Clock; + +public class ClockPreference extends DropDownPreference implements TunerService.Tunable { + + private static final String SECONDS = "seconds"; + private static final String DEFAULT = "default"; + private static final String DISABLED = "disabled"; + + private final String mClock; + private boolean mClockEnabled; + private boolean mHasSeconds; + private ArraySet<String> mBlacklist; + private boolean mHasSetValue; + + public ClockPreference(Context context, AttributeSet attrs) { + super(context, attrs); + mClock = context.getString(com.android.internal.R.string.status_bar_clock); + setEntryValues(new CharSequence[] { SECONDS, DEFAULT, DISABLED }); + } + + @Override + public void onAttached() { + super.onAttached(); + TunerService.get(getContext()).addTunable(this, StatusBarIconController.ICON_BLACKLIST, + Clock.CLOCK_SECONDS); + } + + @Override + public void onDetached() { + TunerService.get(getContext()).removeTunable(this); + super.onDetached(); + } + + @Override + public void onTuningChanged(String key, String newValue) { + if (StatusBarIconController.ICON_BLACKLIST.equals(key)) { + mBlacklist = StatusBarIconController.getIconBlacklist(newValue); + mClockEnabled = !mBlacklist.contains(mClock); + } else if (Clock.CLOCK_SECONDS.equals(key)) { + mHasSeconds = newValue != null && Integer.parseInt(newValue) != 0; + } + if (!mHasSetValue) { + // Because of the complicated tri-state it can end up looping and setting state back to + // what the user didn't choose. To avoid this, just set the state once and rely on the + // preference to handle updates. + mHasSetValue = true; + if (mClockEnabled && mHasSeconds) { + setValue(SECONDS); + } else if (mClockEnabled) { + setValue(DEFAULT); + } else { + setValue(DISABLED); + } + } + } + + @Override + protected boolean persistString(String value) { + TunerService.get(getContext()).setValue(Clock.CLOCK_SECONDS, SECONDS.equals(value) ? 1 : 0); + if (DISABLED.equals(value)) { + mBlacklist.add(mClock); + } else { + mBlacklist.remove(mClock); + } + TunerService.get(getContext()).setValue(StatusBarIconController.ICON_BLACKLIST, + TextUtils.join(",", mBlacklist)); + return true; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ColorAndAppearanceFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/ColorAndAppearanceFragment.java new file mode 100644 index 000000000000..9f11325c7d15 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/tuner/ColorAndAppearanceFragment.java @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2016 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.tuner; + + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.DialogInterface; +import android.os.Bundle; +import android.provider.Settings; +import android.provider.Settings.Secure; +import android.support.v14.preference.PreferenceFragment; +import android.support.v7.preference.Preference; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.SeekBar; + +import com.android.systemui.R; +import com.android.systemui.statusbar.policy.NightModeController; + +public class ColorAndAppearanceFragment extends PreferenceFragment { + + private static final String KEY_CALIBRATE = "calibrate"; + + private static final long RESET_DELAY = 10000; + private static final CharSequence KEY_NIGHT_MODE = "night_mode"; + + private NightModeController mNightModeController; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mNightModeController = new NightModeController(getContext()); + } + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.color_and_appearance); + } + + @Override + public void onResume() { + super.onResume(); + // TODO: Figure out better title model for Tuner, to avoid any more of this. + getActivity().setTitle(R.string.color_and_appearance); + + Preference nightMode = findPreference(KEY_NIGHT_MODE); + nightMode.setSummary(mNightModeController.isEnabled() + ? R.string.night_mode_on : R.string.night_mode_off); + } + + @Override + public void onDisplayPreferenceDialog(Preference preference) { + if (preference instanceof CalibratePreference) { + CalibrateDialog.show(this); + } else { + super.onDisplayPreferenceDialog(preference); + } + } + + private void startRevertTimer() { + getView().postDelayed(mResetColorMatrix, RESET_DELAY); + } + + private void onApply() { + mNightModeController.setCustomValues(Settings.Secure.getString( + getContext().getContentResolver(), Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX)); + getView().removeCallbacks(mResetColorMatrix); + } + + private void onRevert() { + getView().removeCallbacks(mResetColorMatrix); + mResetColorMatrix.run(); + } + + private final Runnable mResetColorMatrix = new Runnable() { + @Override + public void run() { + ((DialogFragment) getFragmentManager().findFragmentByTag("RevertWarning")).dismiss(); + Settings.Secure.putString(getContext().getContentResolver(), + Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, null); + } + }; + + public static class CalibrateDialog extends DialogFragment implements + DialogInterface.OnClickListener { + private float[] mValues; + private NightModeController mNightModeController; + + public static void show(ColorAndAppearanceFragment fragment) { + CalibrateDialog dialog = new CalibrateDialog(); + dialog.setTargetFragment(fragment, 0); + dialog.show(fragment.getFragmentManager(), "Calibrate"); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mNightModeController = new NightModeController(getContext()); + String customValues = mNightModeController.getCustomValues(); + if (customValues == null) { + // Generate this as a string because its the easiest way to generate a copy of the + // identity. + customValues = NightModeController.toString(NightModeController.IDENTITY_MATRIX); + } + mValues = NightModeController.toValues(customValues); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + View v = LayoutInflater.from(getContext()).inflate(R.layout.calibrate_sliders, null); + bindView(v.findViewById(R.id.r_group), 0); + bindView(v.findViewById(R.id.g_group), 5); + bindView(v.findViewById(R.id.b_group), 10); + return new AlertDialog.Builder(getContext()) + .setTitle(R.string.calibrate_display) + .setView(v) + .setPositiveButton(R.string.color_apply, this) + .setNegativeButton(android.R.string.cancel, null) + .create(); + } + + private void bindView(View view, final int index) { + SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar); + seekBar.setMax(1000); + seekBar.setProgress((int) (1000 * mValues[index])); + seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + mValues[index] = progress / 1000f; + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + } + }); + } + + @Override + public void onClick(DialogInterface dialog, int which) { + if (mValues[0] == 1 && mValues[5] == 1 && mValues[10] == 1) { + // Allow removal of matrix by all values set to highest. + mNightModeController.setCustomValues(null); + return; + } + ((ColorAndAppearanceFragment) getTargetFragment()).startRevertTimer(); + Settings.Secure.putString(getContext().getContentResolver(), + Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, + NightModeController.toString(mValues)); + RevertWarning.show((ColorAndAppearanceFragment) getTargetFragment()); + } + } + + public static class RevertWarning extends DialogFragment + implements DialogInterface.OnClickListener { + + public static void show(ColorAndAppearanceFragment fragment) { + RevertWarning warning = new RevertWarning(); + warning.setTargetFragment(fragment, 0); + warning.show(fragment.getFragmentManager(), "RevertWarning"); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog alertDialog = new AlertDialog.Builder(getContext()) + .setTitle(R.string.color_revert_title) + .setMessage(R.string.color_revert_message) + .setPositiveButton(R.string.ok, this) + .create(); + alertDialog.setCanceledOnTouchOutside(true); + return alertDialog; + } + + @Override + public void onCancel(DialogInterface dialog) { + super.onCancel(dialog); + ((ColorAndAppearanceFragment) getTargetFragment()).onRevert(); + } + + @Override + public void onClick(DialogInterface dialog, int which) { + ((ColorAndAppearanceFragment) getTargetFragment()).onApply(); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixFragment.java deleted file mode 100644 index dfacd033a90e..000000000000 --- a/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixFragment.java +++ /dev/null @@ -1,341 +0,0 @@ -/** - * Copyright (c) 2015, 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.tuner; - -import android.annotation.Nullable; -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; -import android.content.ContentResolver; -import android.content.Context; -import android.content.DialogInterface; -import android.os.Bundle; -import android.provider.Settings; -import android.support.v14.preference.PreferenceFragment; -import android.support.v14.preference.SwitchPreference; -import android.support.v7.preference.DropDownPreference; -import android.support.v7.preference.Preference; -import android.support.v7.preference.PreferenceViewHolder; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.SeekBar; -import android.widget.Switch; - -import com.android.systemui.R; -import com.android.systemui.statusbar.phone.QSTileHost; -import com.android.systemui.statusbar.policy.DisplayController; - -import java.util.Objects; - -public class ColorMatrixFragment extends PreferenceFragment implements TunerService.Tunable { - - private static final String TAG = "ColorMatrixFragment"; - - private static final long RESET_DELAY = 10000; - - private boolean mCustomEnabled; - private DropDownPreference mSelectPreference; - private String mCurrentValue; - private String mCustomValues; - private SwitchPreference mEnableCustomPreference; - private MatrixPreference mCustomPreference; - private int mState; - private Switch mSwitch; - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - Context context = getContext(); - TunerService.get(context).addTunable(this, DisplayController.COLOR_MATRIX_CUSTOM_ENABLED, - DisplayController.COLOR_MATRIX_CUSTOM_VALUES, DisplayController.COLOR_STATE, - Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - final View view = LayoutInflater.from(getContext()).inflate( - R.layout.color_matrix_settings, container, false); - ((ViewGroup) view).addView(super.onCreateView(inflater, container, savedInstanceState)); - return view; - } - - @Override - public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { - final Context context = getPreferenceManager().getContext(); - setPreferenceScreen(getPreferenceManager().createPreferenceScreen(context)); - - mSelectPreference = new DropDownPreference(context); - mSelectPreference.setTitle(R.string.color_transform); - mSelectPreference.setSummary("%s"); - mSelectPreference.setOnPreferenceChangeListener( - new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - if (Objects.equals(newValue, DisplayController.AUTO_STRING)) { - Settings.Secure.putInt(context.getContentResolver(), - DisplayController.COLOR_STATE, - DisplayController.COLOR_STATE_AUTO); - return true; - } - if (Objects.equals(newValue, DisplayController.NONE_STRING)) { - Settings.Secure.putString(context.getContentResolver(), - Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, null); - return true; - } - Settings.Secure.putInt(context.getContentResolver(), - DisplayController.COLOR_STATE, - DisplayController.COLOR_STATE_ENABLED); - final String value = (String) newValue; - Settings.Secure.putString(context.getContentResolver(), - Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, - value); - return true; - } - }); - getPreferenceScreen().addPreference(mSelectPreference); - - mEnableCustomPreference = new SwitchPreference(context); - mEnableCustomPreference.setTitle(R.string.color_enable_custom); - mEnableCustomPreference.setOnPreferenceChangeListener( - new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - boolean enabled = (Boolean) newValue; - if (!enabled && Objects.equals(mCurrentValue, mCustomValues)) { - Settings.Secure.putString(context.getContentResolver(), - Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, null); - } - Settings.Secure.putInt(context.getContentResolver(), - DisplayController.COLOR_MATRIX_CUSTOM_ENABLED, enabled ? 1 : 0); - return true; - } - }); - getPreferenceScreen().addPreference(mEnableCustomPreference); - - mCustomPreference = new MatrixPreference(context); - getPreferenceScreen().addPreference(mCustomPreference); - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - View switchBar = view.findViewById(R.id.switch_bar); - mSwitch = (Switch) switchBar.findViewById(android.R.id.switch_widget); - mSwitch.setChecked(mState != DisplayController.COLOR_STATE_DISABLED); - switchBar.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - int newState = mState != DisplayController.COLOR_STATE_DISABLED - ? DisplayController.COLOR_STATE_DISABLED - : DisplayController.COLOR_STATE_ENABLED; - ContentResolver contentResolver = getContext().getContentResolver(); - if (newState == DisplayController.COLOR_STATE_DISABLED) { - String tiles = Settings.Secure.getString(contentResolver, - QSTileHost.TILES_SETTING); - if (tiles != null) { - if (tiles.contains(",colors")) { - tiles = tiles.replace(",colors", ""); - } else if (tiles.contains("colors,")) { - tiles = tiles.replace("colors,", ""); - } - Settings.Secure.putString(contentResolver, QSTileHost.TILES_SETTING, - tiles); - } - } - Settings.Secure.putInt(contentResolver, - DisplayController.COLOR_STATE, newState); - } - }); - } - - @Override - public void onDestroy() { - super.onDestroy(); - TunerService.get(getContext()).removeTunable(this); - } - - @Override - public void onTuningChanged(String key, String newValue) { - if (DisplayController.COLOR_MATRIX_CUSTOM_ENABLED.equals(key)) { - mCustomEnabled = newValue != null && Integer.parseInt(newValue) != 0; - mEnableCustomPreference.setChecked(mCustomEnabled); - mCustomPreference.setEnabled(mCustomEnabled - && mState != DisplayController.COLOR_STATE_DISABLED); - updateSelectOptions(); - } else if (DisplayController.COLOR_MATRIX_CUSTOM_VALUES.equals(key)) { - mCustomValues = newValue; - if (mCustomValues == null) { - mCustomValues = DisplayController.toString(DisplayController.IDENTITY_MATRIX); - } - mCustomPreference.setValues(mCustomValues); - updateSelectOptions(); - } else if (DisplayController.COLOR_STATE.equals(key)) { - mState = newValue != null ? Integer.parseInt(newValue) : 0; - if (mSwitch != null) { - mSwitch.setChecked(mState != DisplayController.COLOR_STATE_DISABLED); - } - mSelectPreference.setEnabled(mState != DisplayController.COLOR_STATE_DISABLED); - mEnableCustomPreference.setEnabled(mState != DisplayController.COLOR_STATE_DISABLED); - mCustomPreference.setEnabled(mCustomEnabled - && mState != DisplayController.COLOR_STATE_DISABLED); - } else { - mCurrentValue = newValue; - updateSelectOptions(); - } - } - - private void updateSelectOptions() { - final int N = DisplayController.CUSTOM_INDEX + (mCustomEnabled ? 1 : 0); - String[] values = new String[N]; - CharSequence[] names = new CharSequence[N]; - CharSequence[] totalNames = DisplayController.getColorTitles(getContext()); - String[] entries = DisplayController.getColorTransforms(getContext()); - entries[DisplayController.CUSTOM_INDEX] = mCustomValues != null ? mCustomValues : ""; - for (int i = 0; i < N; i++) { - values[i] = entries[i]; - names[i] = totalNames[i]; - } - mSelectPreference.setEntries(names); - mSelectPreference.setEntryValues(values); - int index = 0; - if (mState == DisplayController.COLOR_STATE_AUTO) { - index = DisplayController.AUTO_INDEX; - } else if (mCustomValues != null && Objects.equals(mCurrentValue, mCustomValues)) { - index = DisplayController.CUSTOM_INDEX; - } else if (Objects.equals(mCurrentValue, entries[1])) { - index = 1; - } - mSelectPreference.setValueIndex(index); - mSelectPreference.setSummary("%s"); - return; - } - - private void startRevertTimer() { - getView().postDelayed(mResetColorMatrix, RESET_DELAY); - } - - private void onApply() { - Settings.Secure.putString(getContext().getContentResolver(), - DisplayController.COLOR_MATRIX_CUSTOM_VALUES, mCurrentValue); - getView().removeCallbacks(mResetColorMatrix); - } - - private void onRevert() { - getView().removeCallbacks(mResetColorMatrix); - mResetColorMatrix.run(); - } - - private final Runnable mResetColorMatrix = new Runnable() { - @Override - public void run() { - ((DialogFragment) getFragmentManager().findFragmentByTag("RevertWarning")).dismiss(); - Settings.Secure.putString(getContext().getContentResolver(), - Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, null); - } - }; - - private class MatrixPreference extends Preference implements View.OnClickListener { - private float[] mValues; - - public MatrixPreference(Context context) { - super(context); - setLayoutResource(R.layout.preference_matrix); - } - - public void setValues(String customValues) { - String[] strValues = customValues.split(","); - mValues = new float[strValues.length]; - for (int i = 0; i < mValues.length; i++) { - mValues[i] = Float.parseFloat(strValues[i]); - } - notifyChanged(); - } - - @Override - public void onBindViewHolder(PreferenceViewHolder holder) { - super.onBindViewHolder(holder); - bindView(holder.findViewById(R.id.r_group), 0); - bindView(holder.findViewById(R.id.g_group), 5); - bindView(holder.findViewById(R.id.b_group), 10); - holder.findViewById(R.id.apply).setOnClickListener(this); - } - - private void bindView(View view, final int index) { - SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar); - seekBar.setMax(1000); - seekBar.setProgress((int) (1000 * mValues[index])); - seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - mValues[index] = progress / 1000f; - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - } - }); - } - - @Override - public void onClick(View v) { - startRevertTimer(); - Settings.Secure.putString(getContext().getContentResolver(), - Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, - DisplayController.toString(mValues)); - RevertWarning.show(ColorMatrixFragment.this); - } - - } - - public static class RevertWarning extends DialogFragment - implements DialogInterface.OnClickListener { - - public static void show(ColorMatrixFragment fragment) { - RevertWarning warning = new RevertWarning(); - warning.setTargetFragment(fragment, 0); - warning.show(fragment.getFragmentManager(), "RevertWarning"); - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - AlertDialog alertDialog = new AlertDialog.Builder(getContext()) - .setTitle(R.string.color_revert_title) - .setMessage(R.string.color_revert_message) - .setPositiveButton(R.string.ok, this) - .create(); - alertDialog.setCanceledOnTouchOutside(true); - return alertDialog; - } - - @Override - public void onCancel(DialogInterface dialog) { - super.onCancel(dialog); - ((ColorMatrixFragment) getTargetFragment()).onRevert(); - } - - @Override - public void onClick(DialogInterface dialog, int which) { - ((ColorMatrixFragment) getTargetFragment()).onApply(); - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java b/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java deleted file mode 100644 index d8cf2e2bcbdc..000000000000 --- a/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java +++ /dev/null @@ -1,107 +0,0 @@ -/** - * Copyright (c) 2015, 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.tuner; - -import android.app.ActivityManager; -import android.provider.Settings; - -import com.android.internal.logging.MetricsProto.MetricsEvent; -import com.android.systemui.R; -import com.android.systemui.qs.QSTile; -import com.android.systemui.statusbar.policy.DisplayController; - -import java.util.Objects; - - -public class ColorMatrixTile extends QSTile<QSTile.State> implements DisplayController.Listener { - - public static final String COLOR_MATRIX_SPEC = "colors"; - - private final DisplayController mDisplayController; - - private int mIndex; - private String mCurrentValue; - - private boolean mCustomEnabled; - private String[] mValues; - private CharSequence[] mValueTitles; - - public ColorMatrixTile(Host host) { - super(host); - mDisplayController = host.getDisplayController(); - } - - @Override - public void setListening(boolean listening) { - if (listening) { - mValues = DisplayController.getColorTransforms(mContext); - mValueTitles = DisplayController.getColorTitles(mContext); - mDisplayController.addListener(this); - } else { - mDisplayController.removeListener(this); - } - } - - @Override - public State newTileState() { - return new State(); - } - - @Override - protected void handleClick() { - mIndex++; - if (mIndex == DisplayController.AUTO_INDEX) { - mDisplayController.setAuto(true); - } else { - mDisplayController.setAuto(false); - if (!mDisplayController.isCustomEnabled() - && (mIndex == DisplayController.CUSTOM_INDEX)) { - mIndex++; - } - if (mIndex == mValues.length - 1) { - mIndex = 0; - } - Settings.Secure.putStringForUser(mContext.getContentResolver(), - Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, mValues[mIndex], - ActivityManager.getCurrentUser()); - } - refreshState(); - } - - @Override - protected void handleUpdateState(State state, Object arg) { - if (mDisplayController.isAuto()) { - mIndex = DisplayController.AUTO_INDEX; - } else if (mDisplayController.isCustomSet()) { - mIndex = DisplayController.CUSTOM_INDEX; - } else { - mIndex = Objects.equals(mDisplayController.getCurrentMatrix(), mValues[1]) ? 1 : 0; - } - state.icon = ResourceIcon.get(R.drawable.ic_colorize); - state.label = mValueTitles[mIndex]; - state.contentDescription = mValueTitles[mIndex]; - } - - @Override - public void onCurrentMatrixChanged() { - refreshState(); - } - - @Override - public int getMetricsCategory() { - return MetricsEvent.QS_COLOR_MATRIX; - } -} diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NightModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/NightModeFragment.java new file mode 100644 index 000000000000..e9650eaf83a1 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/tuner/NightModeFragment.java @@ -0,0 +1,195 @@ +/** + * Copyright (c) 2016, 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.tuner; + +import android.annotation.Nullable; +import android.app.UiModeManager; +import android.content.ContentResolver; +import android.content.Context; +import android.os.Bundle; +import android.provider.Settings; +import android.provider.Settings.Secure; +import android.support.v14.preference.PreferenceFragment; +import android.support.v14.preference.SwitchPreference; +import android.support.v7.preference.DropDownPreference; +import android.support.v7.preference.Preference; +import android.support.v7.preference.Preference.OnPreferenceChangeListener; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Switch; + +import com.android.systemui.R; +import com.android.systemui.statusbar.phone.QSTileHost; +import com.android.systemui.statusbar.policy.NightModeController; +import com.android.systemui.statusbar.policy.NightModeController.Listener; +import com.android.systemui.tuner.TunerService.Tunable; + +public class NightModeFragment extends PreferenceFragment implements Tunable, + Listener, OnPreferenceChangeListener { + + private static final String TAG = "NightModeFragment"; + + public static final String EXTRA_SHOW_NIGHT_MODE = "show_night_mode"; + + private static final CharSequence KEY_AUTO = "auto"; + private static final CharSequence KEY_DARK_THEME = "dark_theme"; + private static final CharSequence KEY_ADJUST_TINT = "adjust_tint"; + private static final CharSequence KEY_ADJUST_BRIGHTNESS = "adjust_brightness"; + + private Switch mSwitch; + + private NightModeController mNightModeController; + private SwitchPreference mAutoSwitch; + private SwitchPreference mDarkTheme; + private SwitchPreference mAdjustTint; + private SwitchPreference mAdjustBrightness; + private UiModeManager mUiModeManager; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mNightModeController = new NightModeController(getContext()); + mUiModeManager = getContext().getSystemService(UiModeManager.class); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + final View view = LayoutInflater.from(getContext()).inflate( + R.layout.night_mode_settings, container, false); + ((ViewGroup) view).addView(super.onCreateView(inflater, container, savedInstanceState)); + return view; + } + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + final Context context = getPreferenceManager().getContext(); + + addPreferencesFromResource(R.xml.night_mode); + mAutoSwitch = (SwitchPreference) findPreference(KEY_AUTO); + mAutoSwitch.setOnPreferenceChangeListener(this); + mDarkTheme = (SwitchPreference) findPreference(KEY_DARK_THEME); + mDarkTheme.setOnPreferenceChangeListener(this); + mAdjustTint = (SwitchPreference) findPreference(KEY_ADJUST_TINT); + mAdjustTint.setOnPreferenceChangeListener(this); + mAdjustBrightness = (SwitchPreference) findPreference(KEY_ADJUST_BRIGHTNESS); + mAdjustBrightness.setOnPreferenceChangeListener(this); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + View switchBar = view.findViewById(R.id.switch_bar); + mSwitch = (Switch) switchBar.findViewById(android.R.id.switch_widget); + mSwitch.setChecked(mNightModeController.isEnabled()); + switchBar.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + boolean newState = !mNightModeController.isEnabled(); + mNightModeController.setNightMode(newState); + mSwitch.setChecked(newState); + } + }); + } + + @Override + public void onResume() { + super.onResume(); + mNightModeController.addListener(this); + TunerService.get(getContext()).addTunable(this, Secure.BRIGHTNESS_USE_TWILIGHT, + NightModeController.NIGHT_MODE_ADJUST_TINT); + mDarkTheme.setChecked(mUiModeManager.getNightMode() == UiModeManager.MODE_NIGHT_AUTO); + calculateDisabled(); + } + + @Override + public void onPause() { + super.onPause(); + mNightModeController.removeListener(this); + TunerService.get(getContext()).removeTunable(this); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + if (mAutoSwitch == preference) { + mNightModeController.setAuto((Boolean) newValue); + } else if (mDarkTheme == preference) { + mUiModeManager.setNightMode(((Boolean) newValue) ? UiModeManager.MODE_NIGHT_AUTO + : UiModeManager.MODE_NIGHT_NO); + postCalculateDisabled(); + } else if (mAdjustTint == preference) { + mNightModeController.setAdjustTint((Boolean) newValue); + postCalculateDisabled(); + } else if (mAdjustBrightness == preference) { + TunerService.get(getContext()).setValue(Secure.BRIGHTNESS_USE_TWILIGHT, + ((Boolean) newValue) ? 1 : 0); + postCalculateDisabled(); + } else { + return false; + } + return true; + } + + private void postCalculateDisabled() { + // Post this because its the easiest way to wait for all state to be calculated. + getView().post(new Runnable() { + @Override + public void run() { + calculateDisabled(); + } + }); + } + + private void calculateDisabled() { + int enabledCount = (mDarkTheme.isChecked() ? 1 : 0) + + (mAdjustTint.isChecked() ? 1 : 0) + + (mAdjustBrightness.isChecked() ? 1 : 0); + if (enabledCount == 1) { + if (mDarkTheme.isChecked()) { + mDarkTheme.setEnabled(false); + } else if (mAdjustTint.isChecked()) { + mAdjustTint.setEnabled(false); + } else { + mAdjustBrightness.setEnabled(false); + } + } else { + mDarkTheme.setEnabled(true); + mAdjustTint.setEnabled(true); + mAdjustBrightness.setEnabled(true); + } + } + + @Override + public void onTuningChanged(String key, String newValue) { + if (Secure.BRIGHTNESS_USE_TWILIGHT.equals(key)) { + mAdjustBrightness.setChecked(newValue != null && Integer.parseInt(newValue) != 0); + } else if (NightModeController.NIGHT_MODE_ADJUST_TINT.equals(key)) { + // Default on. + mAdjustTint.setChecked(newValue == null || Integer.parseInt(newValue) != 0); + } + } + + @Override + public void onNightModeChanged() { + mSwitch.setChecked(mNightModeController.isEnabled()); + } + + @Override + public void onTwilightAutoChanged() { + mAutoSwitch.setChecked(mNightModeController.isAuto()); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java b/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java new file mode 100644 index 000000000000..61135bd968f9 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java @@ -0,0 +1,99 @@ +/** + * Copyright (c) 2016, 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.tuner; + +import android.app.ActivityManager; +import android.content.Intent; +import android.provider.Settings; + +import com.android.internal.logging.MetricsProto.MetricsEvent; +import com.android.systemui.R; +import com.android.systemui.qs.QSTile; +import com.android.systemui.statusbar.policy.NightModeController; + +import java.util.Objects; + + +public class NightModeTile extends QSTile<QSTile.State> implements NightModeController.Listener { + + public static final String NIGHT_MODE_SPEC = "night"; + + private final NightModeController mNightModeController; + + private int mIndex; + private String mCurrentValue; + + private boolean mCustomEnabled; + private String[] mValues; + private CharSequence[] mValueTitles; + + public NightModeTile(Host host) { + super(host); + mNightModeController = host.getNightModeController(); + } + + @Override + public void setListening(boolean listening) { + if (listening) { + mNightModeController.addListener(this); + refreshState(); + } else { + mNightModeController.removeListener(this); + } + } + + @Override + public State newTileState() { + return new State(); + } + + @Override + public Intent getLongClickIntent() { + return new Intent(mContext, TunerActivity.class) + .putExtra(NightModeFragment.EXTRA_SHOW_NIGHT_MODE, true); + } + + @Override + protected void handleClick() { + mNightModeController.setNightMode(!mNightModeController.isEnabled()); + refreshState(); + } + + @Override + protected void handleUpdateState(State state, Object arg) { + // TODO: Right now this is just a dropper, needs an actual night icon. + boolean enabled = mNightModeController.isEnabled(); + state.icon = ResourceIcon.get(enabled ? R.drawable.ic_night_mode + : R.drawable.ic_night_mode_disabled); + state.label = mContext.getString(R.string.night_mode); + state.contentDescription = mContext.getString(R.string.night_mode); + } + + @Override + public void onNightModeChanged() { + refreshState(); + } + + @Override + public void onTwilightAutoChanged() { + // Don't care. + } + + @Override + public int getMetricsCategory() { + return MetricsEvent.QS_COLOR_MATRIX; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java index 4225b48fbf45..def597d23d48 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java @@ -36,7 +36,10 @@ public class TunerActivity extends SettingsDrawerActivity implements super.onCreate(savedInstanceState); if (getFragmentManager().findFragmentByTag(TAG_TUNER) == null) { - getFragmentManager().beginTransaction().replace(R.id.content_frame, new TunerFragment(), + boolean showNightMode = getIntent().getBooleanExtra( + NightModeFragment.EXTRA_SHOW_NIGHT_MODE, false); + getFragmentManager().beginTransaction().replace(R.id.content_frame, + showNightMode ? new NightModeFragment() : new TunerFragment(), TAG_TUNER).commit(); } } diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java index 9df53682c5ad..70f2fdcfa8d3 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java @@ -37,8 +37,6 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.systemui.R; -import static com.android.systemui.BatteryMeterDrawable.SHOW_PERCENT_SETTING; - public class TunerFragment extends PreferenceFragment { private static final String TAG = "TunerFragment"; @@ -51,10 +49,6 @@ public class TunerFragment extends PreferenceFragment { private static final int MENU_REMOVE = Menu.FIRST + 1; - private final SettingObserver mSettingObserver = new SettingObserver(); - - private SwitchPreference mBatteryPct; - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -72,7 +66,6 @@ public class TunerFragment extends PreferenceFragment { public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { addPreferencesFromResource(R.xml.tuner_prefs); - mBatteryPct = (SwitchPreference) findPreference(KEY_BATTERY_PCT); if (Settings.Secure.getInt(getContext().getContentResolver(), SETTING_SEEN_TUNER_WARNING, 0) == 0) { if (getFragmentManager().findFragmentByTag(WARNING_TAG) == null) { @@ -85,9 +78,6 @@ public class TunerFragment extends PreferenceFragment { public void onResume() { super.onResume(); getActivity().setTitle(R.string.system_ui_tuner); - updateBatteryPct(); - getContext().getContentResolver().registerContentObserver( - System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver); MetricsLogger.visibility(getContext(), MetricsEvent.TUNER, true); } @@ -95,7 +85,6 @@ public class TunerFragment extends PreferenceFragment { @Override public void onPause() { super.onPause(); - getContext().getContentResolver().unregisterContentObserver(mSettingObserver); MetricsLogger.visibility(getContext(), MetricsEvent.TUNER, false); } @@ -123,35 +112,6 @@ public class TunerFragment extends PreferenceFragment { return super.onOptionsItemSelected(item); } - private void updateBatteryPct() { - mBatteryPct.setOnPreferenceChangeListener(null); - mBatteryPct.setChecked(System.getInt(getContext().getContentResolver(), - SHOW_PERCENT_SETTING, 0) != 0); - mBatteryPct.setOnPreferenceChangeListener(mBatteryPctChange); - } - - private final class SettingObserver extends ContentObserver { - public SettingObserver() { - super(new Handler()); - } - - @Override - public void onChange(boolean selfChange, Uri uri, int userId) { - super.onChange(selfChange, uri, userId); - updateBatteryPct(); - } - } - - private final OnPreferenceChangeListener mBatteryPctChange = new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - final boolean v = (Boolean) newValue; - MetricsLogger.action(getContext(), MetricsEvent.TUNER_BATTERY_PERCENTAGE, v); - System.putInt(getContext().getContentResolver(), SHOW_PERCENT_SETTING, v ? 1 : 0); - return true; - } - }; - public static class TunerWarningFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java index 7ad752ec74ce..b73813647c0d 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java @@ -23,7 +23,7 @@ public class TunerSwitch extends SwitchPreference implements Tunable { @Override public void onAttached() { super.onAttached(); - TunerService.get(getContext()).addTunable(this, getKey()); + TunerService.get(getContext()).addTunable(this, getKey().split(",")); } @Override @@ -39,7 +39,9 @@ public class TunerSwitch extends SwitchPreference implements Tunable { @Override protected boolean persistBoolean(boolean value) { - Settings.Secure.putString(getContext().getContentResolver(), getKey(), value ? "1" : "0"); + for (String key : getKey().split(",")) { + Settings.Secure.putString(getContext().getContentResolver(), key, value ? "1" : "0"); + } return true; } diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 4be6833d17b5..388c8b7298c5 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -2162,8 +2162,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { mIntent = new Intent().setComponent(mComponentName); mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL, com.android.internal.R.string.accessibility_binding_label); - mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( - mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0)); + final long idendtity = Binder.clearCallingIdentity(); + try { + mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( + mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0)); + } finally { + Binder.restoreCallingIdentity(idendtity); + } } setDynamicallyConfigurableProperties(accessibilityServiceInfo); } diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index 4646f3cd093e..2b52799304fd 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -159,7 +159,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku reloadWidgetsMaskedStateForUser(userId); } else if (Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED.equals(action)) { synchronized (mLock) { - reloadWidgetQuietModeMaskedStateLocked(userId); + reloadWidgetProfileUnavailableMaskedStateLocked(userId); } } else if (Intent.ACTION_PACKAGES_SUSPENDED.equals(action)) { String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); @@ -432,7 +432,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku /** * Reload all widgets' masked state for the given user and its associated profiles, including - * due to quiet mode and package suspension. + * due to user not being available and package suspension. */ private void reloadWidgetsMaskedStateForUser(int userId) { if (!mUserManager.isUserUnlocked(userId)) return; @@ -442,7 +442,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku if (profiles != null) { for (int i = 0; i < profiles.size(); i++) { UserInfo user = profiles.get(i); - reloadWidgetQuietModeMaskedStateLocked(user.id); + reloadWidgetProfileUnavailableMaskedStateLocked(user.id); reloadWidgetPackageSuspensionMaskedStateLocked(user.id); } } @@ -450,17 +450,18 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } /** - * Mask/unmask widgets in the given profile, depending on the quiet state of the profile. + * Mask/unmask widgets in the given profile, depending on the quiet state + * or locked state of the profile. */ - private void reloadWidgetQuietModeMaskedStateLocked(int profileId) { - if (!mUserManager.isUserUnlocked(profileId)) return; + private void reloadWidgetProfileUnavailableMaskedStateLocked(int profileId) { final long identity = Binder.clearCallingIdentity(); try { - UserInfo user = mUserManager.getUserInfo(profileId); - if (!user.isManagedProfile()) { + if (!isProfileWithUnlockedParent(profileId)) { return; } - boolean shouldMask = user.isQuietModeEnabled(); + UserInfo user = mUserManager.getUserInfo(profileId); + boolean shouldMask = user.isQuietModeEnabled() || + !mUserManager.isUserUnlocked(user.getUserHandle()); final int N = mProviders.size(); for (int i = 0; i < N; i++) { Provider provider = mProviders.get(i); @@ -468,7 +469,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku if (providerUserId != profileId) { continue; } - if (provider.setMaskedByQuietProfileLocked(shouldMask)) { + if (provider.setMaskedByProfileUnavailabledLocked(shouldMask)) { if (provider.isMaskedLocked()) { maskWidgetsViewsLocked(provider); } else { @@ -537,8 +538,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } } - private void maskWidgetsViewsLocked(Provider provider) { - Bitmap iconBitmap = null; + private Bitmap createMaskedWidgetBitmap(Provider provider) { + final long identity = Binder.clearCallingIdentity(); try { // Load the unbadged application icon and pass it to the widget to appear on // the masked view. @@ -548,11 +549,20 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku PackageManager pm = userContext.getPackageManager(); Drawable icon = pm.getApplicationInfo(providerPackage, 0).loadUnbadgedIcon(pm); // Create a bitmap of the icon which is what the widget's remoteview requires. - iconBitmap = mIconUtilities.createIconBitmap(icon); + return mIconUtilities.createIconBitmap(icon); } catch (NameNotFoundException e) { Slog.e(TAG, "Fail to get application icon", e); // Provider package removed, no need to mask its views as its state will be // purged very soon. + return null; + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + private void maskWidgetsViewsLocked(Provider provider) { + Bitmap iconBitmap = createMaskedWidgetBitmap(provider); + if (iconBitmap == null) { return; } @@ -2320,7 +2330,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku final PackageManager pm = mContext.getPackageManager(); final int userId = UserHandle.getUserId(providerId.uid); final ApplicationInfo app = pm.getApplicationInfoAsUser(activityInfo.packageName, - PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId); + 0, userId); resources = pm.getResourcesForApplication(app); } finally { Binder.restoreCallingIdentity(identity); @@ -2423,9 +2433,16 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku int flags = PackageManager.GET_META_DATA; // We really need packages to be around and parsed to know if they - // provide widgets, and we only load widgets after user is unlocked. + // provide widgets. flags |= PackageManager.MATCH_DEBUG_TRIAGED_MISSING; + // Widget hosts that are non-crypto aware may be hosting widgets + // from a profile that is still locked, so let them see those + // widgets. + if (isProfileWithUnlockedParent(userId)) { + flags |= PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE; + } + // Widgets referencing shared libraries need to have their // dependencies loaded. flags |= PackageManager.GET_SHARED_LIBRARY_FILES; @@ -2443,6 +2460,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku private void onUserUnlocked(int userId) { synchronized (mLock) { ensureGroupStateLoadedLocked(userId); + reloadWidgetsMaskedStateForUser(userId); final int N = mProviders.size(); for (int i = 0; i < N; i++) { @@ -2580,6 +2598,17 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku mWidgetPackages.put(userId, packages = new ArraySet<String>()); } packages.add(widget.provider.info.provider.getPackageName()); + + // If we are adding a widget it might be for a provider that + // is currently masked, if so mask the widget. + if (widget.provider.isMaskedLocked()) { + Bitmap bitmap = createMaskedWidgetBitmap(widget.provider); + if (bitmap != null) { + widget.replaceWithMaskedViewsLocked(mContext, bitmap); + } + } else { + widget.clearMaskedViewsLocked(); + } } /** @@ -3277,6 +3306,18 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } } + private boolean isProfileWithUnlockedParent(int userId) { + UserInfo userInfo = mUserManager.getUserInfo(userId); + if (userInfo != null && userInfo.isManagedProfile()) { + UserInfo parentInfo = mUserManager.getProfileParent(userId); + if (parentInfo != null + && mUserManager.isUserUnlocked(parentInfo.getUserHandle())) { + return true; + } + } + return false; + } + private final class CallbackHandler extends Handler { public static final int MSG_NOTIFY_UPDATE_APP_WIDGET = 1; public static final int MSG_NOTIFY_PROVIDER_CHANGED = 2; @@ -3554,7 +3595,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku PendingIntent broadcast; boolean zombie; // if we're in safe mode, don't prune this just because nobody references it - boolean maskedByQuietProfile; + boolean maskedByProfileUnavailable; boolean maskedBySuspendedPackage; int tag = TAG_UNDEFINED; // for use while saving state (the index) @@ -3587,9 +3628,9 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } // returns true if the provider's masked state is changed as a result - public boolean setMaskedByQuietProfileLocked(boolean masked) { + public boolean setMaskedByProfileUnavailabledLocked(boolean masked) { boolean oldMaskedState = isMaskedLocked(); - maskedByQuietProfile = masked; + maskedByProfileUnavailable = masked; return isMaskedLocked() != oldMaskedState; } @@ -3601,7 +3642,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } public boolean isMaskedLocked() { - return maskedByQuietProfile || maskedBySuspendedPackage; + return maskedByProfileUnavailable || maskedBySuspendedPackage; } } diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java index 91f58c56c675..32f2d593f670 100644 --- a/services/core/java/com/android/server/AppOpsService.java +++ b/services/core/java/com/android/server/AppOpsService.java @@ -31,6 +31,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import android.Manifest; import android.app.ActivityManager; import android.app.ActivityThread; import android.app.AppGlobals; @@ -67,6 +68,7 @@ import com.android.internal.app.IAppOpsCallback; import com.android.internal.os.Zygote; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastXmlSerializer; +import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; import libcore.util.EmptyArray; @@ -103,9 +105,10 @@ public class AppOpsService extends IAppOpsService.Stub { } }; - final SparseArray<UidState> mUidStates = new SparseArray<>(); + private final SparseArray<UidState> mUidStates = new SparseArray<>(); - private final SparseArray<boolean[]> mOpRestrictions = new SparseArray<boolean[]>(); + /** These are app op restrictions imposed per user from various parties */ + private final ArrayMap<IBinder, SparseArray<boolean[]>> mOpUserRestrictions = new ArrayMap<>(); private static final class UidState { public final int uid; @@ -1263,17 +1266,21 @@ public class AppOpsService extends IAppOpsService.Stub { private boolean isOpRestricted(int uid, int code, String packageName) { int userHandle = UserHandle.getUserId(uid); - boolean[] opRestrictions = mOpRestrictions.get(userHandle); - if ((opRestrictions != null) && opRestrictions[code]) { - if (AppOpsManager.opAllowSystemBypassRestriction(code)) { - synchronized (this) { - Ops ops = getOpsLocked(uid, packageName, true); - if ((ops != null) && ops.isPrivileged) { - return false; + final int restrictionSetCount = mOpUserRestrictions.size(); + for (int i = 0; i < restrictionSetCount; i++) { + SparseArray<boolean[]> perUserRestrictions = mOpUserRestrictions.valueAt(i); + boolean[] opRestrictions = perUserRestrictions.get(userHandle); + if (opRestrictions != null && opRestrictions[code]) { + if (AppOpsManager.opAllowSystemBypassRestriction(code)) { + synchronized (this) { + Ops ops = getOpsLocked(uid, packageName, true); + if ((ops != null) && ops.isPrivileged) { + return false; + } } } + return true; } - return true; } return false; } @@ -2049,27 +2056,123 @@ public class AppOpsService extends IAppOpsService.Stub { } @Override - public void setUserRestrictions(Bundle restrictions, int userHandle) throws RemoteException { + public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) { checkSystemUid("setUserRestrictions"); - boolean[] opRestrictions = mOpRestrictions.get(userHandle); - if (opRestrictions == null) { - opRestrictions = new boolean[AppOpsManager._NUM_OP]; - mOpRestrictions.put(userHandle, opRestrictions); - } + Preconditions.checkNotNull(token); + final boolean[] opRestrictions = getOrCreateUserRestrictionsForToken(token, userHandle); for (int i = 0; i < opRestrictions.length; ++i) { String restriction = AppOpsManager.opToRestriction(i); - if (restriction != null) { - opRestrictions[i] = restrictions.getBoolean(restriction, false); - } else { - opRestrictions[i] = false; + final boolean restricted = restriction != null + && restrictions.getBoolean(restriction, false); + setUserRestrictionNoCheck(i, restricted, token, userHandle); + } + } + + @Override + public void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle) { + if (Binder.getCallingPid() != Process.myPid()) { + mContext.enforcePermission(Manifest.permission.MANAGE_APP_OPS_RESTRICTIONS, + Binder.getCallingPid(), Binder.getCallingUid(), null); + } + if (userHandle != UserHandle.getCallingUserId()) { + if (mContext.checkCallingOrSelfPermission(Manifest.permission + .INTERACT_ACROSS_USERS_FULL) != PackageManager.PERMISSION_GRANTED + && mContext.checkCallingOrSelfPermission(Manifest.permission + .INTERACT_ACROSS_USERS) != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Need INTERACT_ACROSS_USERS_FULL or" + + " INTERACT_ACROSS_USERS to interact cross user "); } } + verifyIncomingOp(code); + Preconditions.checkNotNull(token); + setUserRestrictionNoCheck(code, restricted, token, userHandle); + } + + private void setUserRestrictionNoCheck(int code, boolean restricted, IBinder token, + int userHandle) { + final boolean[] opRestrictions = getOrCreateUserRestrictionsForToken(token, userHandle); + if (opRestrictions[code] == restricted) { + return; + } + opRestrictions[code] = restricted; + if (!restricted) { + pruneUserRestrictionsForToken(token, userHandle); + } + + final ArrayList<Callback> clonedCallbacks; + synchronized (this) { + ArrayList<Callback> callbacks = mOpModeWatchers.get(code); + if (callbacks == null) { + return; + } + clonedCallbacks = new ArrayList<>(callbacks); + } + + // There are components watching for mode changes such as window manager + // and location manager which are in our process. The callbacks in these + // components may require permissions our remote caller does not have. + final long identity = Binder.clearCallingIdentity(); + try { + final int callbackCount = clonedCallbacks.size(); + for (int i = 0; i < callbackCount; i++) { + Callback callback = clonedCallbacks.get(i); + try { + callback.mCallback.opChanged(code, -1, null); + } catch (RemoteException e) { + Log.w(TAG, "Error dispatching op op change", e); + } + } + } finally { + Binder.restoreCallingIdentity(identity); + } } @Override public void removeUser(int userHandle) throws RemoteException { checkSystemUid("removeUser"); - mOpRestrictions.remove(userHandle); + final int tokenCount = mOpUserRestrictions.size(); + for (int i = tokenCount - 1; i >= 0; i--) { + SparseArray<boolean[]> opRestrictions = mOpUserRestrictions.valueAt(i); + if (opRestrictions != null) { + opRestrictions.remove(userHandle); + if (opRestrictions.size() <= 0) { + mOpUserRestrictions.removeAt(i); + } + } + } + } + + + private void pruneUserRestrictionsForToken(IBinder token, int userHandle) { + SparseArray<boolean[]> perTokenRestrictions = mOpUserRestrictions.get(token); + if (perTokenRestrictions != null) { + final boolean[] opRestrictions = perTokenRestrictions.get(userHandle); + if (opRestrictions != null) { + for (boolean restriction : opRestrictions) { + if (restriction) { + return; + } + } + perTokenRestrictions.remove(userHandle); + if (perTokenRestrictions.size() <= 0) { + mOpUserRestrictions.remove(token); + } + } + } + } + + private boolean[] getOrCreateUserRestrictionsForToken(IBinder token, int userHandle) { + SparseArray<boolean[]> perTokenRestrictions = mOpUserRestrictions.get(token); + if (perTokenRestrictions == null) { + perTokenRestrictions = new SparseArray<>(); + mOpUserRestrictions.put(token, perTokenRestrictions); + } + boolean[] opRestrictions = perTokenRestrictions.get(userHandle); + if (opRestrictions == null) { + opRestrictions = new boolean[AppOpsManager._NUM_OP]; + perTokenRestrictions.put(userHandle, opRestrictions); + } + return opRestrictions; } private void checkSystemUid(String function) { diff --git a/services/core/java/com/android/server/HardwarePropertiesManagerService.java b/services/core/java/com/android/server/HardwarePropertiesManagerService.java new file mode 100644 index 000000000000..cc21e99371e4 --- /dev/null +++ b/services/core/java/com/android/server/HardwarePropertiesManagerService.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2016 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; + +import android.app.admin.DevicePolicyManager; +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.Binder; +import android.os.CpuUsageInfo; +import android.os.IHardwarePropertiesManager; + +import java.util.Arrays; + +/** + * Service for {@link HardwarePropertiesManager} + */ +public class HardwarePropertiesManagerService extends IHardwarePropertiesManager.Stub { + + private static native void nativeInit(); + + private static native float[] nativeGetFanSpeeds(); + private static native float[] nativeGetDeviceTemperatures(int type); + private static native CpuUsageInfo[] nativeGetCpuUsages(); + + private final Context mContext; + private final Object mLock = new Object(); + + public HardwarePropertiesManagerService(Context context) { + mContext = context; + synchronized (mLock) { + nativeInit(); + } + } + + @Override + public float[] getDeviceTemperatures(String callingPackage, int type) throws SecurityException { + enforceHardwarePropertiesRetrievalAllowed(callingPackage); + synchronized (mLock) { + return nativeGetDeviceTemperatures(type); + } + } + + @Override + public CpuUsageInfo[] getCpuUsages(String callingPackage) throws SecurityException { + enforceHardwarePropertiesRetrievalAllowed(callingPackage); + synchronized (mLock) { + return nativeGetCpuUsages(); + } + } + + @Override + public float[] getFanSpeeds(String callingPackage) throws SecurityException { + enforceHardwarePropertiesRetrievalAllowed(callingPackage); + synchronized (mLock) { + return nativeGetFanSpeeds(); + } + } + + /** + * Throws SecurityException if the calling package is not allowed to retrieve information + * provided by the service. + * + * @param callingPackage The calling package name. + * + * @throws SecurityException if a non profile or device owner tries to retrieve information + * provided by the service. + */ + private void enforceHardwarePropertiesRetrievalAllowed(String callingPackage) + throws SecurityException { + final PackageManager pm = mContext.getPackageManager(); + try { + final int uid = pm.getPackageUid(callingPackage, 0); + if (Binder.getCallingUid() != uid) { + throw new SecurityException("The caller has faked the package name."); + } + } catch (PackageManager.NameNotFoundException e) { + throw new SecurityException("The caller has faked the package name."); + } + + final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class); + if (!dpm.isDeviceOwnerApp(callingPackage) && !dpm.isProfileOwnerApp(callingPackage)) { + throw new SecurityException("The caller is not a device or profile owner."); + } + } +} diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 5f6fddfc411c..d1de7e57ef45 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -189,6 +189,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private InputMethodFileManager mFileManager; private final HardKeyboardListener mHardKeyboardListener; private final AppOpsManager mAppOpsManager; + private final UserManager mUserManager; final InputBindResult mNoBinding = new InputBindResult(null, null, null, -1, -1); @@ -780,6 +781,27 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mService.systemRunning(statusBarService); } } + + @Override + public void onUnlockUser(int userHandle) { + mService.onUnlockUser(userHandle); + } + } + + public void onUnlockUser(int userId) { + synchronized(mMethodMap) { + final int currentUserId = mSettings.getCurrentUserId(); + if (DEBUG) { + Slog.d(TAG, "onUnlockUser: userId=" + userId + " curUserId=" + currentUserId); + } + if (userId != currentUserId) { + return; + } + mSettings.switchCurrentUser(currentUserId, !mSystemReady); + // We need to rebuild IMEs. + buildInputMethodListLocked(false /* resetDefaultEnabledIme */); + updateInputMethodsFromSettingsLocked(true /* enabledChanged */); + } } public InputMethodManagerService(Context context) { @@ -799,6 +821,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } }, true /*asyncHandler*/); mAppOpsManager = mContext.getSystemService(AppOpsManager.class); + mUserManager = mContext.getSystemService(UserManager.class); mHardKeyboardListener = new HardKeyboardListener(); mHasFeature = context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_INPUT_METHODS); @@ -972,8 +995,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // ContentObserver should be registered again when the user is changed mSettingsObserver.registerContentObserverLocked(newUserId); - // If the system is not ready, then we use copy-on-write settings. - final boolean useCopyOnWriteSettings = !mSystemReady; + // If the system is not ready or the device is not yed unlocked by the user, then we use + // copy-on-write settings. + final boolean useCopyOnWriteSettings = + !mSystemReady || !mUserManager.isUserUnlocked(newUserId); mSettings.switchCurrentUser(newUserId, useCopyOnWriteSettings); updateCurrentProfileIds(); // InputMethodFileManager should be reset when the user is changed @@ -1002,8 +1027,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } void updateCurrentProfileIds() { - List<UserInfo> profiles = mContext.getSystemService(UserManager.class) - .getProfiles(mSettings.getCurrentUserId()); + List<UserInfo> profiles = mUserManager.getProfiles(mSettings.getCurrentUserId()); int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null for (int i = 0; i < currentProfileIds.length; i++) { currentProfileIds[i] = profiles.get(i).id; @@ -1034,7 +1058,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (!mSystemReady) { mSystemReady = true; final int currentUserId = mSettings.getCurrentUserId(); - mSettings.switchCurrentUser(currentUserId, false /* copyOnWrite */); + mSettings.switchCurrentUser(currentUserId, + !mUserManager.isUserUnlocked(currentUserId)); mKeyguardManager = mContext.getSystemService(KeyguardManager.class); mNotificationManager = mContext.getSystemService(NotificationManager.class); mStatusBar = statusBar; @@ -2918,6 +2943,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // Use for queryIntentServicesAsUser final PackageManager pm = mContext.getPackageManager(); + // Note: We do not specify PackageManager.MATCH_ENCRYPTION_* flags here because the default + // behavior of PackageManager is exactly what we want. It by default picks up appropriate + // services depending on the unlock state for the specified user. final List<ResolveInfo> services = pm.queryIntentServicesAsUser( new Intent(InputMethod.SERVICE_INTERFACE), PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 14ddc363f392..9884a70a2ca9 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -214,7 +214,7 @@ public class LocationManagerService extends ILocationManager.Stub { private int mCurrentUserId = UserHandle.USER_SYSTEM; private int[] mCurrentUserProfiles = new int[] { UserHandle.USER_SYSTEM }; - private GnssLocationProvider.GpsSystemInfoProvider mGpsSystemInfoProvider; + private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider; public LocationManagerService(Context context) { super(); @@ -462,7 +462,7 @@ public class LocationManagerService extends ILocationManager.Stub { // Create a gps location provider GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this, mLocationHandler.getLooper()); - mGpsSystemInfoProvider = gnssProvider.getGpsSystemInfoProvider(); + mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider(); mGnssStatusProvider = gnssProvider.getGnssStatusProvider(); mNetInitiatedListener = gnssProvider.getNetInitiatedListener(); addProviderLocked(gnssProvider); @@ -990,12 +990,12 @@ public class LocationManagerService extends ILocationManager.Stub { } /** - * Returns the system information of the GPS hardware. + * Returns the system information of the GNSS hardware. */ @Override - public int getGpsYearOfHardware() { + public int getGnssYearOfHardware() { if (mGnssNavigationMessageProvider != null) { - return mGpsSystemInfoProvider.getGpsYearOfHardware(); + return mGnssSystemInfoProvider.getGnssYearOfHardware(); } else { return 0; } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 337f74905756..8c04fbc17e05 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -273,6 +273,7 @@ import static android.provider.Settings.Global.DEBUG_APP; import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT; import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES; import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RTL; +import static android.provider.Settings.Global.LENIENT_BACKGROUND_CHECK; import static android.provider.Settings.Global.WAIT_FOR_DEBUGGER; import static android.provider.Settings.System.FONT_SCALE; import static com.android.internal.util.XmlUtils.readBooleanAttribute; @@ -1290,6 +1291,7 @@ public final class ActivityManagerService extends ActivityManagerNative String mOrigDebugApp = null; boolean mOrigWaitForDebugger = false; boolean mAlwaysFinishActivities = false; + boolean mLenientBackgroundCheck = false; boolean mForceResizableActivities; boolean mSupportsFreeformWindowManagement; boolean mSupportsPictureInPicture; @@ -7490,7 +7492,16 @@ public final class ActivityManagerService extends ActivityManagerNative int checkAllowBackgroundLocked(int uid, String packageName, int callingPid) { UidRecord uidRec = mActiveUids.get(uid); - if (uidRec == null || uidRec.idle) { + if (!mLenientBackgroundCheck) { + if (uidRec == null + || uidRec.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) { + if (mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND, uid, + packageName) != AppOpsManager.MODE_ALLOWED) { + return ActivityManager.APP_START_MODE_DELAYED; + } + } + + } else if (uidRec == null || uidRec.idle) { if (callingPid >= 0) { ProcessRecord proc; synchronized (mPidsSelfLocked) { @@ -11376,12 +11387,36 @@ public final class ActivityManagerService extends ActivityManagerNative enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH, "setAlwaysFinish()"); - Settings.Global.putInt( - mContext.getContentResolver(), - Settings.Global.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0); + long ident = Binder.clearCallingIdentity(); + try { + Settings.Global.putInt( + mContext.getContentResolver(), + Settings.Global.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0); - synchronized (this) { - mAlwaysFinishActivities = enabled; + synchronized (this) { + mAlwaysFinishActivities = enabled; + } + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override + public void setLenientBackgroundCheck(boolean enabled) { + enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT, + "setLenientBackgroundCheck()"); + + long ident = Binder.clearCallingIdentity(); + try { + Settings.Global.putInt( + mContext.getContentResolver(), + Settings.Global.LENIENT_BACKGROUND_CHECK, enabled ? 1 : 0); + + synchronized (this) { + mLenientBackgroundCheck = enabled; + } + } finally { + Binder.restoreCallingIdentity(ident); } } @@ -12278,6 +12313,8 @@ public final class ActivityManagerService extends ActivityManagerNative final boolean waitForDebugger = Settings.Global.getInt(resolver, WAIT_FOR_DEBUGGER, 0) != 0; final boolean alwaysFinishActivities = Settings.Global.getInt(resolver, ALWAYS_FINISH_ACTIVITIES, 0) != 0; + final boolean lenientBackgroundCheck = + Settings.Global.getInt(resolver, LENIENT_BACKGROUND_CHECK, 0) != 0; final boolean forceRtl = Settings.Global.getInt(resolver, DEVELOPMENT_FORCE_RTL, 0) != 0; final boolean forceResizable = Settings.Global.getInt( resolver, DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0; @@ -12295,6 +12332,7 @@ public final class ActivityManagerService extends ActivityManagerNative mDebugApp = mOrigDebugApp = debugApp; mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger; mAlwaysFinishActivities = alwaysFinishActivities; + mLenientBackgroundCheck = lenientBackgroundCheck; mForceResizableActivities = forceResizable; mWindowManager.setForceResizableTasks(mForceResizableActivities); mSupportsFreeformWindowManagement = freeformWindowManagement || forceResizable; @@ -14074,8 +14112,9 @@ public final class ActivityManagerService extends ActivityManagerNative } } if (dumpPackage == null) { - if (mAlwaysFinishActivities || mController != null) { + if (mAlwaysFinishActivities || mLenientBackgroundCheck || mController != null) { pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities + + " mLenientBackgroundCheck=" + mLenientBackgroundCheck + " mController=" + mController); } if (dumpAll) { @@ -16960,7 +16999,6 @@ public final class ActivityManagerService extends ActivityManagerNative case Process.ROOT_UID: case Process.SYSTEM_UID: case Process.PHONE_UID: - case Process.SHELL_UID: case Process.BLUETOOTH_UID: case Process.NFC_UID: isCallerSystem = true; diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 8c997395da46..02539766ed59 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -62,6 +62,8 @@ class ActivityManagerShellCommand extends ShellCommand { return runUntrackAssociations(pw); case "is-user-stopped": return runIsUserStopped(pw); + case "lenient-background-check": + return runLenientBackgroundCheck(pw); default: return handleDefaultCommands(cmd); } @@ -152,6 +154,22 @@ class ActivityManagerShellCommand extends ShellCommand { return 0; } + int runLenientBackgroundCheck(PrintWriter pw) throws RemoteException { + String arg = getNextArg(); + if (arg != null) { + boolean state = Boolean.valueOf(arg) || "1".equals(arg); + mInterface.setLenientBackgroundCheck(state); + } + synchronized (mInternal) { + if (mInternal.mLenientBackgroundCheck) { + pw.println("Lenient background check enabled"); + } else { + pw.println("Lenient background check disabled"); + } + } + return 0; + } + @Override public void onHelp() { PrintWriter pw = getOutPrintWriter(); @@ -203,6 +221,8 @@ class ActivityManagerShellCommand extends ShellCommand { pw.println(" Disable and clear association tracking."); pw.println(" is-user-stopped <USER_ID>"); pw.println(" returns whether <USER_ID> has been stopped or not"); + pw.println(" lenient-background-check [<true|false>]"); + pw.println(" optionally controls lenient background check mode, returns current mode."); } } } diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 509b1bbbac1a..acde10fa29e2 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -1434,10 +1434,12 @@ final class ActivityStack { if (mStackId == DOCKED_STACK_ID) { // Docked stack is always visible, except in the case where the top running activity - // task in the focus stack doesn't support any form of resizing. + // task in the focus stack doesn't support any form of resizing but we show it for the + // home task even though it's not resizable. final ActivityRecord r = focusedStack.topRunningActivityLocked(); final TaskRecord task = r != null ? r.task : null; - return task == null || task.canGoInDockedStack() ? STACK_VISIBLE : STACK_INVISIBLE; + return task == null || task.canGoInDockedStack() || task.isHomeTask() ? STACK_VISIBLE + : STACK_INVISIBLE; } // Find the first stack below focused stack that actually got something visible. diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index c143474ce0c8..9562f94f5015 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -400,7 +400,7 @@ public final class ActivityStackSupervisor implements DisplayListener { // The default minimal size that will be used if the activity doesn't specify its minimal size. // It will be calculated when the default display gets added. - private int mDefaultMinimalSizeOfResizeableTask = -1; + int mDefaultMinimalSizeOfResizeableTask = -1; // Whether tasks have moved and we need to rank the tasks before next OOM scoring private boolean mTaskLayersChanged = true; @@ -2039,8 +2039,6 @@ public final class ActivityStackSupervisor implements DisplayListener { return true; } - adjustForMinimalTaskDimensions(task, bounds); - // If this is a forced resize, let it go through even if the bounds is not changing, // as we might need a relayout due to surface size change (to/from fullscreen). final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0; @@ -2074,7 +2072,7 @@ public final class ActivityStackSupervisor implements DisplayListener { // to be relaunched due to configuration change. boolean kept = true; if (overrideConfig != null) { - ActivityRecord r = task.topRunningActivityLocked(); + final ActivityRecord r = task.topRunningActivityLocked(); if (r != null) { final ActivityStack stack = task.stack; kept = stack.ensureActivityConfigurationLocked(r, 0, preserveWindow); @@ -2085,44 +2083,12 @@ public final class ActivityStackSupervisor implements DisplayListener { } } } - mWindowManager.resizeTask(task.taskId, bounds, task.mOverrideConfig, kept, forced); + mWindowManager.resizeTask(task.taskId, task.mBounds, task.mOverrideConfig, kept, forced); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); return kept; } - private void adjustForMinimalTaskDimensions(TaskRecord task, Rect bounds) { - if (bounds == null) { - return; - } - int minimalSize = task.mMinimalSize == -1 ? mDefaultMinimalSizeOfResizeableTask - : task.mMinimalSize; - final boolean adjustWidth = minimalSize > bounds.width(); - final boolean adjustHeight = minimalSize > bounds.height(); - if (!(adjustWidth || adjustHeight)) { - return; - } - Rect taskBounds = task.mBounds; - if (adjustWidth) { - if (taskBounds != null && bounds.right == taskBounds.right) { - bounds.left = bounds.right - minimalSize; - } else { - // Either left bounds match, or neither match, or the previous bounds were - // fullscreen and we default to keeping left. - bounds.right = bounds.left + minimalSize; - } - } - if (adjustHeight) { - if (taskBounds != null && bounds.bottom == taskBounds.bottom) { - bounds.top = bounds.bottom - minimalSize; - } else { - // Either top bounds match, or neither match, or the previous bounds were - // fullscreen and we default to keeping top. - bounds.bottom = bounds.top + minimalSize; - } - } - } - ActivityStack createStackOnDisplay(int stackId, int displayId, boolean onTop) { ActivityDisplay activityDisplay = mActivityDisplays.get(displayId); if (activityDisplay == null) { diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 16fd909b329a..37a549a960a7 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -243,6 +243,8 @@ final class TaskRecord { // Bounds of the Task. null for fullscreen tasks. Rect mBounds = null; + private final Rect mTmpStableBounds = new Rect(); + private final Rect mTmpNonDecorBounds = new Rect(); private final Rect mTmpRect = new Rect(); private final Rect mTmpRect2 = new Rect(); @@ -1313,6 +1315,38 @@ final class TaskRecord { return task; } + private void adjustForMinimalTaskDimensions(Rect bounds) { + if (bounds == null) { + return; + } + final int minimalSize = mMinimalSize == -1 + ? mService.mStackSupervisor.mDefaultMinimalSizeOfResizeableTask : mMinimalSize; + final boolean adjustWidth = minimalSize > bounds.width(); + final boolean adjustHeight = minimalSize > bounds.height(); + if (!(adjustWidth || adjustHeight)) { + return; + } + + if (adjustWidth) { + if (mBounds != null && bounds.right == mBounds.right) { + bounds.left = bounds.right - minimalSize; + } else { + // Either left bounds match, or neither match, or the previous bounds were + // fullscreen and we default to keeping left. + bounds.right = bounds.left + minimalSize; + } + } + if (adjustHeight) { + if (mBounds != null && bounds.bottom == mBounds.bottom) { + bounds.top = bounds.bottom - minimalSize; + } else { + // Either top bounds match, or neither match, or the previous bounds were + // fullscreen and we default to keeping top. + bounds.bottom = bounds.top + minimalSize; + } + } + } + /** * Update task's override configuration based on the bounds. * @param bounds The bounds of the task. @@ -1345,20 +1379,17 @@ final class TaskRecord { mBounds = null; mOverrideConfig = Configuration.EMPTY; } else { + mTmpRect.set(bounds); + adjustForMinimalTaskDimensions(mTmpRect); if (mBounds == null) { - mBounds = new Rect(bounds); + mBounds = new Rect(mTmpRect); } else { - mBounds.set(bounds); + mBounds.set(mTmpRect); } if (stack == null || StackId.persistTaskBounds(stack.mStackId)) { mLastNonFullscreenBounds = mBounds; } - - // Stable insets need to be subtracted because we also subtract it in the fullscreen - // configuration. - mTmpRect.set(bounds); - subtractStableInsets(mTmpRect, insetBounds != null ? insetBounds : mTmpRect); - mOverrideConfig = calculateOverrideConfig(mTmpRect); + mOverrideConfig = calculateOverrideConfig(mTmpRect, insetBounds); } if (mFullscreen != oldFullscreen) { @@ -1368,6 +1399,16 @@ final class TaskRecord { return !mOverrideConfig.equals(oldConfig) ? mOverrideConfig : null; } + private void subtractNonDecorInsets(Rect inOutBounds, Rect inInsetBounds) { + mTmpRect2.set(inInsetBounds); + mService.mWindowManager.subtractNonDecorInsets(mTmpRect2); + int leftInset = mTmpRect2.left - inInsetBounds.left; + int topInset = mTmpRect2.top - inInsetBounds.top; + int rightInset = inInsetBounds.right - mTmpRect2.right; + int bottomInset = inInsetBounds.bottom - mTmpRect2.bottom; + inOutBounds.inset(leftInset, topInset, rightInset, bottomInset); + } + private void subtractStableInsets(Rect inOutBounds, Rect inInsetBounds) { mTmpRect2.set(inInsetBounds); mService.mWindowManager.subtractStableInsets(mTmpRect2); @@ -1378,23 +1419,39 @@ final class TaskRecord { inOutBounds.inset(leftInset, topInset, rightInset, bottomInset); } - Configuration calculateOverrideConfig(Rect bounds) { + private Configuration calculateOverrideConfig(Rect bounds, Rect insetBounds) { + mTmpNonDecorBounds.set(bounds); + mTmpStableBounds.set(bounds); + subtractNonDecorInsets( + mTmpNonDecorBounds, insetBounds != null ? insetBounds : bounds); + subtractStableInsets( + mTmpStableBounds, insetBounds != null ? insetBounds : bounds); + + // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen area, + // i.e. the screen area without the system bars. final Configuration serviceConfig = mService.mConfiguration; final Configuration config = new Configuration(Configuration.EMPTY); // TODO(multidisplay): Update Dp to that of display stack is on. final float density = serviceConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; config.screenWidthDp = - Math.min((int)(bounds.width() / density), serviceConfig.screenWidthDp); + Math.min((int)(mTmpStableBounds.width() / density), serviceConfig.screenWidthDp); config.screenHeightDp = - Math.min((int)(bounds.height() / density), serviceConfig.screenHeightDp); - config.smallestScreenWidthDp = - Math.min(config.screenWidthDp, config.screenHeightDp); + Math.min((int)(mTmpStableBounds.height() / density), serviceConfig.screenHeightDp); + config.smallestScreenWidthDp = Math.min(config.screenWidthDp, config.screenHeightDp); + + // TODO: Orientation? config.orientation = (config.screenWidthDp <= config.screenHeightDp) ? Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE; + + // For calculating screen layout, we need to use the non-decor inset screen area for the + // calculation for compatibility reasons, i.e. screen area without system bars that could + // never go away in Honeycomb. + final int compatScreenWidthDp = (int)(mTmpNonDecorBounds.width() / density); + final int compatScreenHeightDp = (int)(mTmpNonDecorBounds.height() / density); final int sl = Configuration.resetScreenLayout(serviceConfig.screenLayout); - int longSize = Math.max(config.screenWidthDp, config.screenHeightDp); - int shortSize = Math.min(config.screenWidthDp, config.screenHeightDp); + final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp); + final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp); config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize); return config; } diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java index cefaa8ddd831..05aabf1f17b3 100644 --- a/services/core/java/com/android/server/content/SyncStorageEngine.java +++ b/services/core/java/com/android/server/content/SyncStorageEngine.java @@ -1500,6 +1500,9 @@ public class SyncStorageEngine extends Handler { if (authority.ident > highestAuthorityId) { highestAuthorityId = authority.ident; } + } else { + EventLog.writeEvent(0x534e4554, "26513719", -1, + "Malformed authority"); } } else if (XML_TAG_LISTEN_FOR_TICKLES.equals(tagName)) { parseListenForTickles(parser); diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java index 1908f72dfd51..5c80d04da10e 100644 --- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java +++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java @@ -60,22 +60,8 @@ class AutomaticBrightnessController { // non-zero, which in turn ensures that the total weight is non-zero. private static final long AMBIENT_LIGHT_PREDICTION_TIME_MILLIS = 100; - // If true, enables the use of the current time as an auto-brightness adjustment. - // The basic idea here is to expand the dynamic range of auto-brightness - // when it is especially dark outside. The light sensor tends to perform - // poorly at low light levels so we compensate for it by making an - // assumption about the environment. - private static final boolean USE_TWILIGHT_ADJUSTMENT = - PowerManager.useTwilightAdjustmentFeature(); - // Specifies the maximum magnitude of the time of day adjustment. - private static final float TWILIGHT_ADJUSTMENT_MAX_GAMMA = 1.5f; - - // The amount of time after or before sunrise over which to start adjusting - // the gamma. We want the change to happen gradually so that it is below the - // threshold of perceptibility and so that the adjustment has maximum effect - // well after dusk. - private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils.HOUR_IN_MILLIS * 2; + private static final float TWILIGHT_ADJUSTMENT_MAX_GAMMA = 1f; // Debounce for sampling user-initiated changes in display brightness to ensure // the user is satisfied with the result before storing the sample. @@ -193,6 +179,8 @@ class AutomaticBrightnessController { private int mBrightnessAdjustmentSampleOldBrightness; private float mBrightnessAdjustmentSampleOldGamma; + private boolean mUseTwilight; + public AutomaticBrightnessController(Callbacks callbacks, Looper looper, SensorManager sensorManager, Spline autoBrightnessSpline, int lightSensorWarmUpTime, int brightnessMin, int brightnessMax, float dozeScaleFactor, @@ -221,10 +209,6 @@ class AutomaticBrightnessController { if (!DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) { mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); } - - if (USE_TWILIGHT_ADJUSTMENT) { - mTwilight.registerListener(mTwilightListener, mHandler); - } } public int getAutomaticScreenBrightness() { @@ -235,7 +219,7 @@ class AutomaticBrightnessController { } public void configure(boolean enable, float adjustment, boolean dozing, - boolean userInitiatedChange) { + boolean userInitiatedChange, boolean useTwilight) { // While dozing, the application processor may be suspended which will prevent us from // receiving new information from the light sensor. On some devices, we may be able to // switch to a wake-up light sensor instead but for now we will simply disable the sensor @@ -244,6 +228,7 @@ class AutomaticBrightnessController { mDozing = dozing; boolean changed = setLightSensorEnabled(enable && !dozing); changed |= setScreenAutoBrightnessAdjustment(adjustment); + changed |= setUseTwilight(useTwilight); if (changed) { updateAutoBrightness(false /*sendUpdate*/); } @@ -252,6 +237,17 @@ class AutomaticBrightnessController { } } + private boolean setUseTwilight(boolean useTwilight) { + if (mUseTwilight == useTwilight) return false; + if (useTwilight) { + mTwilight.registerListener(mTwilightListener, mHandler); + } else { + mTwilight.unregisterListener(mTwilightListener); + } + mUseTwilight = useTwilight; + return true; + } + public void dump(PrintWriter pw) { pw.println(); pw.println("Automatic Brightness Controller Configuration:"); @@ -484,18 +480,13 @@ class AutomaticBrightnessController { } } - if (USE_TWILIGHT_ADJUSTMENT) { + if (mUseTwilight) { TwilightState state = mTwilight.getCurrentState(); if (state != null && state.isNight()) { final long now = System.currentTimeMillis(); - final float earlyGamma = - getTwilightGamma(now, state.getYesterdaySunset(), state.getTodaySunrise()); - final float lateGamma = - getTwilightGamma(now, state.getTodaySunset(), state.getTomorrowSunrise()); - gamma *= earlyGamma * lateGamma; + gamma *= 1 + state.getAmount() * TWILIGHT_ADJUSTMENT_MAX_GAMMA; if (DEBUG) { - Slog.d(TAG, "updateAutoBrightness: earlyGamma=" + earlyGamma - + ", lateGamma=" + lateGamma); + Slog.d(TAG, "updateAutoBrightness: twilight amount=" + state.getAmount()); } } } @@ -579,25 +570,6 @@ class AutomaticBrightnessController { } } - private static float getTwilightGamma(long now, long lastSunset, long nextSunrise) { - if (lastSunset < 0 || nextSunrise < 0 - || now < lastSunset || now > nextSunrise) { - return 1.0f; - } - - if (now < lastSunset + TWILIGHT_ADJUSTMENT_TIME) { - return MathUtils.lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA, - (float)(now - lastSunset) / TWILIGHT_ADJUSTMENT_TIME); - } - - if (now > nextSunrise - TWILIGHT_ADJUSTMENT_TIME) { - return MathUtils.lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA, - (float)(nextSunrise - now) / TWILIGHT_ADJUSTMENT_TIME); - } - - return TWILIGHT_ADJUSTMENT_MAX_GAMMA; - } - private final class AutomaticBrightnessHandler extends Handler { public AutomaticBrightnessHandler(Looper looper) { super(looper, null, true /*async*/); diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 1038d975ef55..1ed7070d2586 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -615,7 +615,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call && mPowerRequest.brightnessSetByUser; mAutomaticBrightnessController.configure(autoBrightnessEnabled, mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON, - userInitiatedChange); + userInitiatedChange, mPowerRequest.useTwilight); } // Apply brightness boost. diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index 57cede8e7d09..811c94720a36 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -78,13 +78,15 @@ import com.android.server.job.controllers.TimeController; * Any function with the suffix 'Locked' also needs to lock on {@link #mJobs}. * @hide */ -public class JobSchedulerService extends com.android.server.SystemService +public final class JobSchedulerService extends com.android.server.SystemService implements StateChangedListener, JobCompletedListener { public static final boolean DEBUG = false; /** The number of concurrent jobs we run at one time. */ private static final int MAX_JOB_CONTEXTS_COUNT = ActivityManager.isLowRamDeviceStatic() ? 3 : 6; static final String TAG = "JobSchedulerService"; + /** Global local for all job scheduler state. */ + final Object mLock = new Object(); /** Master list of jobs. */ final JobStore mJobs; @@ -207,6 +209,10 @@ public class JobSchedulerService extends com.android.server.SystemService } }; + public Object getLock() { + return mLock; + } + @Override public void onStartUser(int userHandle) { mStartedUsers.add(userHandle); @@ -231,7 +237,7 @@ public class JobSchedulerService extends com.android.server.SystemService } public int scheduleAsPackage(JobInfo job, int uId, String packageName, int userId) { - JobStatus jobStatus = new JobStatus(job, uId, packageName, userId); + JobStatus jobStatus = JobStatus.createFromJobInfo(job, uId, packageName, userId); try { if (ActivityManagerNative.getDefault().getAppStartMode(uId, job.getService().getPackageName()) == ActivityManager.APP_START_MODE_DISABLED) { @@ -243,7 +249,7 @@ public class JobSchedulerService extends com.android.server.SystemService } if (DEBUG) Slog.d(TAG, "SCHEDULE: " + jobStatus.toShortString()); JobStatus toCancel; - synchronized (mJobs) { + synchronized (mLock) { toCancel = mJobs.getJobByUidAndJobId(uId, job.getId()); } startTrackingJob(jobStatus, toCancel); @@ -256,7 +262,7 @@ public class JobSchedulerService extends com.android.server.SystemService public List<JobInfo> getPendingJobs(int uid) { ArrayList<JobInfo> outList = new ArrayList<JobInfo>(); - synchronized (mJobs) { + synchronized (mLock) { ArraySet<JobStatus> jobs = mJobs.getJobs(); for (int i=0; i<jobs.size(); i++) { JobStatus job = jobs.valueAt(i); @@ -270,7 +276,7 @@ public class JobSchedulerService extends com.android.server.SystemService void cancelJobsForUser(int userHandle) { List<JobStatus> jobsForUser; - synchronized (mJobs) { + synchronized (mLock) { jobsForUser = mJobs.getJobsByUser(userHandle); } for (int i=0; i<jobsForUser.size(); i++) { @@ -289,7 +295,7 @@ public class JobSchedulerService extends com.android.server.SystemService */ public void cancelJobsForUid(int uid, boolean forceAll) { List<JobStatus> jobsForUid; - synchronized (mJobs) { + synchronized (mLock) { jobsForUid = mJobs.getJobsByUid(uid); } for (int i=0; i<jobsForUid.size(); i++) { @@ -317,7 +323,7 @@ public class JobSchedulerService extends com.android.server.SystemService */ public void cancelJob(int uid, int jobId) { JobStatus toCancel; - synchronized (mJobs) { + synchronized (mLock) { toCancel = mJobs.getJobByUidAndJobId(uid, jobId); } if (toCancel != null) { @@ -328,7 +334,7 @@ public class JobSchedulerService extends com.android.server.SystemService private void cancelJobImpl(JobStatus cancelled) { if (DEBUG) Slog.d(TAG, "CANCEL: " + cancelled.toShortString()); stopTrackingJob(cancelled, true /* writeBack */); - synchronized (mJobs) { + synchronized (mLock) { // Remove from pending queue. mPendingJobs.remove(cancelled); // Cancel if running. @@ -340,7 +346,7 @@ public class JobSchedulerService extends com.android.server.SystemService void updateIdleMode(boolean enabled) { boolean changed = false; boolean rocking; - synchronized (mJobs) { + synchronized (mLock) { if (mDeviceIdleMode != enabled) { changed = true; } @@ -352,7 +358,7 @@ public class JobSchedulerService extends com.android.server.SystemService mControllers.get(i).deviceIdleModeChanged(enabled); } } - synchronized (mJobs) { + synchronized (mLock) { mDeviceIdleMode = enabled; if (enabled) { // When becoming idle, make sure no jobs are actively running. @@ -451,7 +457,7 @@ public class JobSchedulerService extends com.android.server.SystemService // ignored; both services live in system_server } } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { - synchronized (mJobs) { + synchronized (mLock) { // Let's go! mReadyToRock = true; mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService( @@ -470,7 +476,7 @@ public class JobSchedulerService extends com.android.server.SystemService JobStatus job = jobs.valueAt(i); for (int controller=0; controller<mControllers.size(); controller++) { mControllers.get(controller).deviceIdleModeChanged(mDeviceIdleMode); - mControllers.get(controller).maybeStartTrackingJob(job, null); + mControllers.get(controller).maybeStartTrackingJobLocked(job, null); } } // GO GO GO! @@ -485,19 +491,16 @@ public class JobSchedulerService extends com.android.server.SystemService * about. */ private void startTrackingJob(JobStatus jobStatus, JobStatus lastJob) { - boolean update; - boolean rocking; - synchronized (mJobs) { - update = mJobs.add(jobStatus); - rocking = mReadyToRock; - } - if (rocking) { - for (int i=0; i<mControllers.size(); i++) { - StateController controller = mControllers.get(i); - if (update) { - controller.maybeStopTrackingJob(jobStatus, true); + synchronized (mLock) { + final boolean update = mJobs.add(jobStatus); + if (mReadyToRock) { + for (int i = 0; i < mControllers.size(); i++) { + StateController controller = mControllers.get(i); + if (update) { + controller.maybeStopTrackingJobLocked(jobStatus, true); + } + controller.maybeStartTrackingJobLocked(jobStatus, lastJob); } - controller.maybeStartTrackingJob(jobStatus, lastJob); } } } @@ -507,20 +510,17 @@ public class JobSchedulerService extends com.android.server.SystemService * object removed. */ private boolean stopTrackingJob(JobStatus jobStatus, boolean writeBack) { - boolean removed; - boolean rocking; - synchronized (mJobs) { + synchronized (mLock) { // Remove from store as well as controllers. - removed = mJobs.remove(jobStatus, writeBack); - rocking = mReadyToRock; - } - if (removed && rocking) { - for (int i=0; i<mControllers.size(); i++) { - StateController controller = mControllers.get(i); - controller.maybeStopTrackingJob(jobStatus, false); + final boolean removed = mJobs.remove(jobStatus, writeBack); + if (removed && mReadyToRock) { + for (int i=0; i<mControllers.size(); i++) { + StateController controller = mControllers.get(i); + controller.maybeStopTrackingJobLocked(jobStatus, false); + } } + return removed; } - return removed; } private boolean stopJobOnServiceContextLocked(JobStatus job, int reason) { @@ -693,14 +693,14 @@ public class JobSchedulerService extends com.android.server.SystemService @Override public void handleMessage(Message message) { - synchronized (mJobs) { + synchronized (mLock) { if (!mReadyToRock) { return; } } switch (message.what) { case MSG_JOB_EXPIRED: - synchronized (mJobs) { + synchronized (mLock) { JobStatus runNow = (JobStatus) message.obj; // runNow can be null, which is a controller's way of indicating that its // state is such that all ready jobs should be run immediately. @@ -712,7 +712,7 @@ public class JobSchedulerService extends com.android.server.SystemService } break; case MSG_CHECK_JOB: - synchronized (mJobs) { + synchronized (mLock) { if (mReportedActive) { // if jobs are currently being run, queue all ready jobs for execution. queueReadyJobsForExecutionLockedH(); @@ -723,7 +723,7 @@ public class JobSchedulerService extends com.android.server.SystemService } break; case MSG_CHECK_JOB_GREEDY: - synchronized (mJobs) { + synchronized (mLock) { queueReadyJobsForExecutionLockedH(); } break; @@ -753,7 +753,7 @@ public class JobSchedulerService extends com.android.server.SystemService Slog.d(TAG, " queued " + job.toShortString()); } mPendingJobs.add(job); - } else if (areJobConstraintsNotSatisfied(job)) { + } else if (areJobConstraintsNotSatisfiedLocked(job)) { stopJobOnServiceContextLocked(job, JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED); } @@ -820,7 +820,7 @@ public class JobSchedulerService extends com.android.server.SystemService runnableJobs = new ArrayList<>(); } runnableJobs.add(job); - } else if (areJobConstraintsNotSatisfied(job)) { + } else if (areJobConstraintsNotSatisfiedLocked(job)) { stopJobOnServiceContextLocked(job, JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED); } @@ -869,7 +869,7 @@ public class JobSchedulerService extends com.android.server.SystemService * - It's not ready * - It's running on a JSC. */ - private boolean areJobConstraintsNotSatisfied(JobStatus job) { + private boolean areJobConstraintsNotSatisfiedLocked(JobStatus job) { return !job.isReady() && isCurrentlyActiveLocked(job); } @@ -879,7 +879,7 @@ public class JobSchedulerService extends com.android.server.SystemService * here is where we decide whether to actually execute it. */ private void maybeRunPendingJobsH() { - synchronized (mJobs) { + synchronized (mLock) { if (mDeviceIdleMode) { // If device is idle, we will not schedule jobs to run. return; @@ -887,7 +887,7 @@ public class JobSchedulerService extends com.android.server.SystemService if (DEBUG) { Slog.d(TAG, "pending queue: " + mPendingJobs.size() + " jobs."); } - assignJobsToContextsH(); + assignJobsToContextsLocked(); reportActive(); } } @@ -899,7 +899,7 @@ public class JobSchedulerService extends com.android.server.SystemService * run higher priority ones. * Lock on mJobs before calling this function. */ - private void assignJobsToContextsH() { + private void assignJobsToContextsLocked() { if (DEBUG) { Slog.d(TAG, printPendingQueue()); } @@ -984,7 +984,7 @@ public class JobSchedulerService extends com.android.server.SystemService } for (int ic=0; ic<mControllers.size(); ic++) { StateController controller = mControllers.get(ic); - controller.prepareForExecution(contextIdToJobMap[i]); + controller.prepareForExecutionLocked(contextIdToJobMap[i]); } if (!mActiveServices.get(i).executeRunnableJob(contextIdToJobMap[i])) { Slog.d(TAG, "Error executing " + contextIdToJobMap[i]); @@ -1185,7 +1185,7 @@ public class JobSchedulerService extends com.android.server.SystemService void dumpInternal(PrintWriter pw) { final long now = SystemClock.elapsedRealtime(); - synchronized (mJobs) { + synchronized (mLock) { pw.print("Started users: "); for (int i=0; i<mStartedUsers.size(); i++) { pw.print("u" + mStartedUsers.get(i) + " "); @@ -1216,7 +1216,7 @@ public class JobSchedulerService extends com.android.server.SystemService } for (int i=0; i<mControllers.size(); i++) { pw.println(); - mControllers.get(i).dumpControllerState(pw); + mControllers.get(i).dumpControllerStateLocked(pw); } pw.println(); pw.println(printPendingQueue()); diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java index b249739811a6..48549ce5a113 100644 --- a/services/core/java/com/android/server/job/JobServiceContext.java +++ b/services/core/java/com/android/server/job/JobServiceContext.java @@ -103,6 +103,7 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne private final JobCompletedListener mCompletedListener; /** Used for service binding, etc. */ private final Context mContext; + private final Object mLock; private final IBatteryStats mBatteryStats; private PowerManager.WakeLock mWakeLock; @@ -124,7 +125,6 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne private int mPreferredUid; IJobService service; - private final Object mLock = new Object(); /** * Whether this context is free. This is set to false at the start of execution, and reset to * true when execution is complete. @@ -137,13 +137,14 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne private long mTimeoutElapsed; JobServiceContext(JobSchedulerService service, IBatteryStats batteryStats, Looper looper) { - this(service.getContext(), batteryStats, service, looper); + this(service.getContext(), service.getLock(), batteryStats, service, looper); } @VisibleForTesting - JobServiceContext(Context context, IBatteryStats batteryStats, + JobServiceContext(Context context, Object lock, IBatteryStats batteryStats, JobCompletedListener completedListener, Looper looper) { mContext = context; + mLock = lock; mBatteryStats = batteryStats; mCallbackHandler = new JobServiceHandler(looper); mCompletedListener = completedListener; diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java index 3565fc1d98d5..6020247c3df1 100644 --- a/services/core/java/com/android/server/job/JobStore.java +++ b/services/core/java/com/android/server/job/JobStore.java @@ -44,7 +44,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.Set; @@ -70,6 +69,7 @@ public class JobStore { /** Threshold to adjust how often we want to write to the db. */ private static final int MAX_OPS_BEFORE_WRITE = 1; final ArraySet<JobStatus> mJobSet; + final Object mLock; final Context mContext; private int mDirtyOperations; @@ -85,7 +85,7 @@ public class JobStore { synchronized (sSingletonLock) { if (sSingleton == null) { sSingleton = new JobStore(jobManagerService.getContext(), - Environment.getDataDirectory()); + jobManagerService.getLock(), Environment.getDataDirectory()); } return sSingleton; } @@ -96,7 +96,7 @@ public class JobStore { */ @VisibleForTesting public static JobStore initAndGetForTesting(Context context, File dataDir) { - JobStore jobStoreUnderTest = new JobStore(context, dataDir); + JobStore jobStoreUnderTest = new JobStore(context, new Object(), dataDir); jobStoreUnderTest.clear(); return jobStoreUnderTest; } @@ -104,7 +104,8 @@ public class JobStore { /** * Construct the instance of the job store. This results in a blocking read from disk. */ - private JobStore(Context context, File dataDir) { + private JobStore(Context context, Object lock, File dataDir) { + mLock = lock; mContext = context; mDirtyOperations = 0; @@ -266,14 +267,14 @@ public class JobStore { /** * Runnable that writes {@link #mJobSet} out to xml. - * NOTE: This Runnable locks on JobStore.this + * NOTE: This Runnable locks on mLock */ private class WriteJobsMapToDiskRunnable implements Runnable { @Override public void run() { final long startElapsed = SystemClock.elapsedRealtime(); List<JobStatus> mStoreCopy = new ArrayList<JobStatus>(); - synchronized (JobStore.this) { + synchronized (mLock) { // Copy over the jobs so we can release the lock before writing. for (int i=0; i<mJobSet.size(); i++) { JobStatus jobStatus = mJobSet.valueAt(i); @@ -454,7 +455,7 @@ public class JobStore { try { List<JobStatus> jobs; FileInputStream fis = mJobsFile.openRead(); - synchronized (JobStore.this) { + synchronized (mLock) { jobs = readJobMapImpl(fis); if (jobs != null) { for (int i=0; i<jobs.size(); i++) { @@ -678,8 +679,8 @@ public class JobStore { parser.nextTag(); // Consume </extras> JobStatus js = new JobStatus( - jobBuilder.build(), uid, sourcePackageName, sourceUserId, elapsedRuntimes.first, - elapsedRuntimes.second); + jobBuilder.build(), uid, sourcePackageName, sourceUserId, + elapsedRuntimes.first, elapsedRuntimes.second); return js; } diff --git a/services/core/java/com/android/server/job/controllers/AppIdleController.java b/services/core/java/com/android/server/job/controllers/AppIdleController.java index 5f3da7577a5d..f0c579f1ae98 100644 --- a/services/core/java/com/android/server/job/controllers/AppIdleController.java +++ b/services/core/java/com/android/server/job/controllers/AppIdleController.java @@ -48,59 +48,56 @@ public class AppIdleController extends StateController { public static AppIdleController get(JobSchedulerService service) { synchronized (sCreationLock) { if (sController == null) { - sController = new AppIdleController(service, service.getContext()); + sController = new AppIdleController(service, service.getContext(), + service.getLock()); } return sController; } } - private AppIdleController(StateChangedListener stateChangedListener, Context context) { - super(stateChangedListener, context); + private AppIdleController(StateChangedListener stateChangedListener, Context context, + Object lock) { + super(stateChangedListener, context, lock); mUsageStatsInternal = LocalServices.getService(UsageStatsManagerInternal.class); mAppIdleParoleOn = mUsageStatsInternal.isAppIdleParoleOn(); mUsageStatsInternal.addAppIdleStateChangeListener(new AppIdleStateChangeListener()); } @Override - public void maybeStartTrackingJob(JobStatus jobStatus, JobStatus lastJob) { - synchronized (mTrackedTasks) { - mTrackedTasks.add(jobStatus); - String packageName = jobStatus.getSourcePackageName(); - final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName, - jobStatus.getSourceUid(), jobStatus.getSourceUserId()); - if (DEBUG) { - Slog.d(LOG_TAG, "Start tracking, setting idle state of " - + packageName + " to " + appIdle); - } - jobStatus.appNotIdleConstraintSatisfied.set(!appIdle); + public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) { + mTrackedTasks.add(jobStatus); + String packageName = jobStatus.getSourcePackageName(); + final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName, + jobStatus.getSourceUid(), jobStatus.getSourceUserId()); + if (DEBUG) { + Slog.d(LOG_TAG, "Start tracking, setting idle state of " + + packageName + " to " + appIdle); } + jobStatus.setAppNotIdleConstraintSatisfied(!appIdle); } @Override - public void maybeStopTrackingJob(JobStatus jobStatus, boolean forUpdate) { - synchronized (mTrackedTasks) { - mTrackedTasks.remove(jobStatus); - } + public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) { + mTrackedTasks.remove(jobStatus); } @Override - public void dumpControllerState(PrintWriter pw) { + public void dumpControllerStateLocked(PrintWriter pw) { pw.println("AppIdle"); pw.println("Parole On: " + mAppIdleParoleOn); - synchronized (mTrackedTasks) { - for (JobStatus task : mTrackedTasks) { - pw.print(task.getSourcePackageName()); - pw.print(":idle=" + !task.appNotIdleConstraintSatisfied.get()); - pw.print(", "); - } - pw.println(); + for (JobStatus task : mTrackedTasks) { + pw.print(task.getSourcePackageName()); + pw.print(":idle=" + + ((task.satisfiedConstraints&JobStatus.CONSTRAINT_APP_NOT_IDLE) != 0)); + pw.print(", "); } + pw.println(); } void setAppIdleParoleOn(boolean isAppIdleParoleOn) { // Flag if any app's idle state has changed boolean changed = false; - synchronized (mTrackedTasks) { + synchronized (mLock) { if (mAppIdleParoleOn == isAppIdleParoleOn) { return; } @@ -112,8 +109,7 @@ public class AppIdleController extends StateController { if (DEBUG) { Slog.d(LOG_TAG, "Setting idle state of " + packageName + " to " + appIdle); } - if (task.appNotIdleConstraintSatisfied.get() == appIdle) { - task.appNotIdleConstraintSatisfied.set(!appIdle); + if (task.setAppNotIdleConstraintSatisfied(!appIdle)) { changed = true; } } @@ -128,19 +124,18 @@ public class AppIdleController extends StateController { @Override public void onAppIdleStateChanged(String packageName, int userId, boolean idle) { boolean changed = false; - synchronized (mTrackedTasks) { + synchronized (mLock) { if (mAppIdleParoleOn) { return; } for (JobStatus task : mTrackedTasks) { if (task.getSourcePackageName().equals(packageName) && task.getSourceUserId() == userId) { - if (task.appNotIdleConstraintSatisfied.get() != !idle) { + if (task.setAppNotIdleConstraintSatisfied(!idle)) { if (DEBUG) { Slog.d(LOG_TAG, "App Idle state changed, setting idle state of " + packageName + " to " + idle); } - task.appNotIdleConstraintSatisfied.set(!idle); changed = true; } } diff --git a/services/core/java/com/android/server/job/controllers/BatteryController.java b/services/core/java/com/android/server/job/controllers/BatteryController.java index b322a3e96c14..ac9f42520195 100644 --- a/services/core/java/com/android/server/job/controllers/BatteryController.java +++ b/services/core/java/com/android/server/job/controllers/BatteryController.java @@ -53,7 +53,7 @@ public class BatteryController extends StateController { synchronized (sCreationLock) { if (sController == null) { sController = new BatteryController(taskManagerService, - taskManagerService.getContext()); + taskManagerService.getContext(), taskManagerService.getLock()); } } return sController; @@ -67,32 +67,29 @@ public class BatteryController extends StateController { @VisibleForTesting public static BatteryController getForTesting(StateChangedListener stateChangedListener, Context context) { - return new BatteryController(stateChangedListener, context); + return new BatteryController(stateChangedListener, context, new Object()); } - private BatteryController(StateChangedListener stateChangedListener, Context context) { - super(stateChangedListener, context); + private BatteryController(StateChangedListener stateChangedListener, Context context, + Object lock) { + super(stateChangedListener, context, lock); mChargeTracker = new ChargingTracker(); mChargeTracker.startTracking(); } @Override - public void maybeStartTrackingJob(JobStatus taskStatus, JobStatus lastJob) { + public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) { final boolean isOnStablePower = mChargeTracker.isOnStablePower(); if (taskStatus.hasChargingConstraint()) { - synchronized (mTrackedTasks) { - mTrackedTasks.add(taskStatus); - taskStatus.chargingConstraintSatisfied.set(isOnStablePower); - } + mTrackedTasks.add(taskStatus); + taskStatus.setChargingConstraintSatisfied(isOnStablePower); } } @Override - public void maybeStopTrackingJob(JobStatus taskStatus, boolean forUpdate) { + public void maybeStopTrackingJobLocked(JobStatus taskStatus, boolean forUpdate) { if (taskStatus.hasChargingConstraint()) { - synchronized (mTrackedTasks) { - mTrackedTasks.remove(taskStatus); - } + mTrackedTasks.remove(taskStatus); } } @@ -102,9 +99,9 @@ public class BatteryController extends StateController { Slog.d(TAG, "maybeReportNewChargingState: " + stablePower); } boolean reportChange = false; - synchronized (mTrackedTasks) { + synchronized (mLock) { for (JobStatus ts : mTrackedTasks) { - boolean previous = ts.chargingConstraintSatisfied.getAndSet(stablePower); + boolean previous = ts.setChargingConstraintSatisfied(stablePower); if (previous != stablePower) { reportChange = true; } @@ -197,18 +194,16 @@ public class BatteryController extends StateController { } @Override - public void dumpControllerState(PrintWriter pw) { + public void dumpControllerStateLocked(PrintWriter pw) { pw.println("Batt."); pw.println("Stable power: " + mChargeTracker.isOnStablePower()); - synchronized (mTrackedTasks) { - Iterator<JobStatus> it = mTrackedTasks.iterator(); - if (it.hasNext()) { - pw.print(String.valueOf(it.next().hashCode())); - } - while (it.hasNext()) { - pw.print("," + String.valueOf(it.next().hashCode())); - } - pw.println(); + Iterator<JobStatus> it = mTrackedTasks.iterator(); + if (it.hasNext()) { + pw.print(String.valueOf(it.next().hashCode())); + } + while (it.hasNext()) { + pw.print("," + String.valueOf(it.next().hashCode())); } + pw.println(); } } diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java index b84658a7db96..bd06645b2b16 100644 --- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java +++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java @@ -58,14 +58,15 @@ public class ConnectivityController extends StateController implements public static ConnectivityController get(JobSchedulerService jms) { synchronized (sCreationLock) { if (mSingleton == null) { - mSingleton = new ConnectivityController(jms, jms.getContext()); + mSingleton = new ConnectivityController(jms, jms.getContext(), jms.getLock()); } return mSingleton; } } - private ConnectivityController(StateChangedListener stateChangedListener, Context context) { - super(stateChangedListener, context); + private ConnectivityController(StateChangedListener stateChangedListener, Context context, + Object lock) { + super(stateChangedListener, context, lock); // Register connectivity changed BR. IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); @@ -82,22 +83,18 @@ public class ConnectivityController extends StateController implements } @Override - public void maybeStartTrackingJob(JobStatus jobStatus, JobStatus lastJob) { + public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) { if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()) { - synchronized (mTrackedJobs) { - jobStatus.connectivityConstraintSatisfied.set(mNetworkConnected); - jobStatus.unmeteredConstraintSatisfied.set(mNetworkUnmetered); - mTrackedJobs.add(jobStatus); - } + jobStatus.setConnectivityConstraintSatisfied(mNetworkConnected); + jobStatus.setUnmeteredConstraintSatisfied(mNetworkUnmetered); + mTrackedJobs.add(jobStatus); } } @Override - public void maybeStopTrackingJob(JobStatus jobStatus, boolean forUpdate) { + public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) { if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()) { - synchronized (mTrackedJobs) { - mTrackedJobs.remove(jobStatus); - } + mTrackedJobs.remove(jobStatus); } } @@ -105,18 +102,14 @@ public class ConnectivityController extends StateController implements * @param userId Id of the user for whom we are updating the connectivity state. */ private void updateTrackedJobs(int userId) { - synchronized (mTrackedJobs) { + synchronized (mLock) { boolean changed = false; for (JobStatus js : mTrackedJobs) { if (js.getUserId() != userId) { continue; } - boolean prevIsConnected = - js.connectivityConstraintSatisfied.getAndSet(mNetworkConnected); - boolean prevIsMetered = js.unmeteredConstraintSatisfied.getAndSet(mNetworkUnmetered); - if (prevIsConnected != mNetworkConnected || prevIsMetered != mNetworkUnmetered) { - changed = true; - } + changed |= js.setConnectivityConstraintSatisfied(mNetworkConnected); + changed |= js.setUnmeteredConstraintSatisfied(mNetworkUnmetered); } if (changed) { mStateChangedListener.onControllerStateChanged(); @@ -128,7 +121,7 @@ public class ConnectivityController extends StateController implements * We know the network has just come up. We want to run any jobs that are ready. */ public synchronized void onNetworkActive() { - synchronized (mTrackedJobs) { + synchronized (mLock) { for (JobStatus js : mTrackedJobs) { if (js.isReady()) { if (DEBUG) { @@ -188,7 +181,7 @@ public class ConnectivityController extends StateController implements }; @Override - public void dumpControllerState(PrintWriter pw) { + public void dumpControllerStateLocked(PrintWriter pw) { pw.println("Conn."); pw.println("connected: " + mNetworkConnected + " unmetered: " + mNetworkUnmetered); for (JobStatus js: mTrackedJobs) { diff --git a/services/core/java/com/android/server/job/controllers/ContentObserverController.java b/services/core/java/com/android/server/job/controllers/ContentObserverController.java index 212cc949364d..c5cf30f4739d 100644 --- a/services/core/java/com/android/server/job/controllers/ContentObserverController.java +++ b/services/core/java/com/android/server/job/controllers/ContentObserverController.java @@ -57,7 +57,7 @@ public class ContentObserverController extends StateController { synchronized (sCreationLock) { if (sController == null) { sController = new ContentObserverController(taskManagerService, - taskManagerService.getContext()); + taskManagerService.getContext(), taskManagerService.getLock()); } } return sController; @@ -66,95 +66,90 @@ public class ContentObserverController extends StateController { @VisibleForTesting public static ContentObserverController getForTesting(StateChangedListener stateChangedListener, Context context) { - return new ContentObserverController(stateChangedListener, context); + return new ContentObserverController(stateChangedListener, context, new Object()); } - private ContentObserverController(StateChangedListener stateChangedListener, Context context) { - super(stateChangedListener, context); + private ContentObserverController(StateChangedListener stateChangedListener, Context context, + Object lock) { + super(stateChangedListener, context, lock); } @Override - public void maybeStartTrackingJob(JobStatus taskStatus, JobStatus lastJob) { + public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) { if (taskStatus.hasContentTriggerConstraint()) { - synchronized (mTrackedTasks) { - if (taskStatus.contentObserverJobInstance == null) { - taskStatus.contentObserverJobInstance = new JobInstance(taskStatus); - } - mTrackedTasks.add(taskStatus); - boolean havePendingUris = false; - // If there is a previous job associated with the new job, propagate over - // any pending content URI trigger reports. - if (lastJob != null && lastJob.contentObserverJobInstance != null - && lastJob.contentObserverJobInstance - != taskStatus.contentObserverJobInstance - && lastJob.contentObserverJobInstance.mChangedAuthorities != null) { - havePendingUris = true; + if (taskStatus.contentObserverJobInstance == null) { + taskStatus.contentObserverJobInstance = new JobInstance(taskStatus); + } + mTrackedTasks.add(taskStatus); + boolean havePendingUris = false; + // If there is a previous job associated with the new job, propagate over + // any pending content URI trigger reports. + if (lastJob != null && lastJob.contentObserverJobInstance != null + && lastJob.contentObserverJobInstance + != taskStatus.contentObserverJobInstance + && lastJob.contentObserverJobInstance.mChangedAuthorities != null) { + havePendingUris = true; + taskStatus.contentObserverJobInstance.mChangedAuthorities + = lastJob.contentObserverJobInstance.mChangedAuthorities; + taskStatus.contentObserverJobInstance.mChangedUris + = lastJob.contentObserverJobInstance.mChangedUris; + lastJob.contentObserverJobInstance.mChangedAuthorities = null; + lastJob.contentObserverJobInstance.mChangedUris = null; + } + // If we have previously reported changed authorities/uris, then we failed + // to complete the job with them so will re-record them to report again. + if (taskStatus.changedAuthorities != null) { + havePendingUris = true; + if (taskStatus.contentObserverJobInstance.mChangedAuthorities == null) { taskStatus.contentObserverJobInstance.mChangedAuthorities - = lastJob.contentObserverJobInstance.mChangedAuthorities; - taskStatus.contentObserverJobInstance.mChangedUris - = lastJob.contentObserverJobInstance.mChangedUris; - lastJob.contentObserverJobInstance.mChangedAuthorities = null; - lastJob.contentObserverJobInstance.mChangedUris = null; + = new ArraySet<>(); } - // If we have previously reported changed authorities/uris, then we failed - // to complete the job with them so will re-record them to report again. - if (taskStatus.changedAuthorities != null) { - havePendingUris = true; - if (taskStatus.contentObserverJobInstance.mChangedAuthorities == null) { - taskStatus.contentObserverJobInstance.mChangedAuthorities - = new ArraySet<>(); + for (String auth : taskStatus.changedAuthorities) { + taskStatus.contentObserverJobInstance.mChangedAuthorities.add(auth); + } + if (taskStatus.changedUris != null) { + if (taskStatus.contentObserverJobInstance.mChangedUris == null) { + taskStatus.contentObserverJobInstance.mChangedUris = new ArraySet<>(); } - for (String auth : taskStatus.changedAuthorities) { - taskStatus.contentObserverJobInstance.mChangedAuthorities.add(auth); + for (Uri uri : taskStatus.changedUris) { + taskStatus.contentObserverJobInstance.mChangedUris.add(uri); } - if (taskStatus.changedUris != null) { - if (taskStatus.contentObserverJobInstance.mChangedUris == null) { - taskStatus.contentObserverJobInstance.mChangedUris = new ArraySet<>(); - } - for (Uri uri : taskStatus.changedUris) { - taskStatus.contentObserverJobInstance.mChangedUris.add(uri); - } - } - taskStatus.changedAuthorities = null; - taskStatus.changedUris = null; } taskStatus.changedAuthorities = null; taskStatus.changedUris = null; - taskStatus.contentTriggerConstraintSatisfied.set(havePendingUris); } + taskStatus.changedAuthorities = null; + taskStatus.changedUris = null; + taskStatus.setContentTriggerConstraintSatisfied(havePendingUris); } } @Override - public void prepareForExecution(JobStatus taskStatus) { + public void prepareForExecutionLocked(JobStatus taskStatus) { if (taskStatus.hasContentTriggerConstraint()) { - synchronized (mTrackedTasks) { - if (taskStatus.contentObserverJobInstance != null) { - taskStatus.changedUris = taskStatus.contentObserverJobInstance.mChangedUris; - taskStatus.changedAuthorities - = taskStatus.contentObserverJobInstance.mChangedAuthorities; - taskStatus.contentObserverJobInstance.mChangedUris = null; - taskStatus.contentObserverJobInstance.mChangedAuthorities = null; - } + if (taskStatus.contentObserverJobInstance != null) { + taskStatus.changedUris = taskStatus.contentObserverJobInstance.mChangedUris; + taskStatus.changedAuthorities + = taskStatus.contentObserverJobInstance.mChangedAuthorities; + taskStatus.contentObserverJobInstance.mChangedUris = null; + taskStatus.contentObserverJobInstance.mChangedAuthorities = null; } } } @Override - public void maybeStopTrackingJob(JobStatus taskStatus, boolean forUpdate) { + public void maybeStopTrackingJobLocked(JobStatus taskStatus, boolean forUpdate) { if (taskStatus.hasContentTriggerConstraint()) { - synchronized (mTrackedTasks) { - if (!forUpdate) { - // We won't do this reset if being called for an update, because - // we know it will be immediately followed by maybeStartTrackingJob... - // and we don't want to lose any content changes in-between. - if (taskStatus.contentObserverJobInstance != null) { - taskStatus.contentObserverJobInstance.detach(); - taskStatus.contentObserverJobInstance = null; - } + if (!forUpdate) { + // We won't do this reset if being called for an update, because + // we know it will be immediately followed by maybeStartTrackingJobLocked... + // and we don't want to lose any content changes in-between. + if (taskStatus.contentObserverJobInstance != null) { + taskStatus.contentObserverJobInstance.detach(); + taskStatus.contentObserverJobInstance = null; } - mTrackedTasks.remove(taskStatus); } + mTrackedTasks.remove(taskStatus); } } @@ -162,7 +157,7 @@ public class ContentObserverController extends StateController { public void rescheduleForFailure(JobStatus newJob, JobStatus failureToReschedule) { if (failureToReschedule.hasContentTriggerConstraint() && newJob.hasContentTriggerConstraint()) { - synchronized (mTrackedTasks) { + synchronized (mLock) { // Our job has failed, and we are scheduling a new job for it. // Copy the last reported content changes in to the new job, so when // we schedule the new one we will pick them up and report them again. @@ -184,7 +179,7 @@ public class ContentObserverController extends StateController { @Override public void onChange(boolean selfChange, Uri uri) { boolean reportChange = false; - synchronized (mTrackedTasks) { + synchronized (mLock) { final int N = mJobs.size(); for (int i=0; i<N; i++) { JobInstance inst = mJobs.get(i); @@ -198,9 +193,7 @@ public class ContentObserverController extends StateController { inst.mChangedAuthorities = new ArraySet<>(); } inst.mChangedAuthorities.add(uri.getAuthority()); - boolean previous - = inst.mJobStatus.contentTriggerConstraintSatisfied.getAndSet(true); - if (!previous) { + if (inst.mJobStatus.setContentTriggerConstraintSatisfied(true)) { reportChange = true; } } @@ -254,50 +247,48 @@ public class ContentObserverController extends StateController { } @Override - public void dumpControllerState(PrintWriter pw) { + public void dumpControllerStateLocked(PrintWriter pw) { pw.println("Content."); - synchronized (mTrackedTasks) { - Iterator<JobStatus> it = mTrackedTasks.iterator(); - if (it.hasNext()) { - pw.print(String.valueOf(it.next().hashCode())); - } - while (it.hasNext()) { - pw.print("," + String.valueOf(it.next().hashCode())); - } - pw.println(); - int N = mObservers.size(); - if (N > 0) { - pw.println("URIs:"); - for (int i = 0; i < N; i++) { - ObserverInstance obs = mObservers.valueAt(i); - pw.print(" "); - pw.print(mObservers.keyAt(i)); - pw.println(":"); - pw.print(" "); - pw.println(obs); - pw.println(" Jobs:"); - int M = obs.mJobs.size(); - for (int j=0; j<M; j++) { - JobInstance inst = obs.mJobs.get(j); - pw.print(" "); - pw.print(inst.hashCode()); - if (inst.mChangedAuthorities != null) { - pw.println(":"); - pw.println(" Changed Authorities:"); - for (int k=0; k<inst.mChangedAuthorities.size(); k++) { + Iterator<JobStatus> it = mTrackedTasks.iterator(); + if (it.hasNext()) { + pw.print(String.valueOf(it.next().hashCode())); + } + while (it.hasNext()) { + pw.print("," + String.valueOf(it.next().hashCode())); + } + pw.println(); + int N = mObservers.size(); + if (N > 0) { + pw.println("URIs:"); + for (int i = 0; i < N; i++) { + ObserverInstance obs = mObservers.valueAt(i); + pw.print(" "); + pw.print(mObservers.keyAt(i)); + pw.println(":"); + pw.print(" "); + pw.println(obs); + pw.println(" Jobs:"); + int M = obs.mJobs.size(); + for (int j=0; j<M; j++) { + JobInstance inst = obs.mJobs.get(j); + pw.print(" "); + pw.print(inst.hashCode()); + if (inst.mChangedAuthorities != null) { + pw.println(":"); + pw.println(" Changed Authorities:"); + for (int k=0; k<inst.mChangedAuthorities.size(); k++) { + pw.print(" "); + pw.println(inst.mChangedAuthorities.valueAt(k)); + } + if (inst.mChangedUris != null) { + pw.println(" Changed URIs:"); + for (int k = 0; k<inst.mChangedUris.size(); k++) { pw.print(" "); - pw.println(inst.mChangedAuthorities.valueAt(k)); - } - if (inst.mChangedUris != null) { - pw.println(" Changed URIs:"); - for (int k = 0; k<inst.mChangedUris.size(); k++) { - pw.print(" "); - pw.println(inst.mChangedUris.valueAt(k)); - } + pw.println(inst.mChangedUris.valueAt(k)); } - } else { - pw.println(); } + } else { + pw.println(); } } } diff --git a/services/core/java/com/android/server/job/controllers/IdleController.java b/services/core/java/com/android/server/job/controllers/IdleController.java index 9f4cdef0e5f7..7638494eccb2 100644 --- a/services/core/java/com/android/server/job/controllers/IdleController.java +++ b/services/core/java/com/android/server/job/controllers/IdleController.java @@ -51,14 +51,15 @@ public class IdleController extends StateController { public static IdleController get(JobSchedulerService service) { synchronized (sCreationLock) { if (sController == null) { - sController = new IdleController(service, service.getContext()); + sController = new IdleController(service, service.getContext(), service.getLock()); } return sController; } } - private IdleController(StateChangedListener stateChangedListener, Context context) { - super(stateChangedListener, context); + private IdleController(StateChangedListener stateChangedListener, Context context, + Object lock) { + super(stateChangedListener, context, lock); initIdleStateTracking(); } @@ -66,29 +67,25 @@ public class IdleController extends StateController { * StateController interface */ @Override - public void maybeStartTrackingJob(JobStatus taskStatus, JobStatus lastJob) { + public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) { if (taskStatus.hasIdleConstraint()) { - synchronized (mTrackedTasks) { - mTrackedTasks.add(taskStatus); - taskStatus.idleConstraintSatisfied.set(mIdleTracker.isIdle()); - } + mTrackedTasks.add(taskStatus); + taskStatus.setIdleConstraintSatisfied(mIdleTracker.isIdle()); } } @Override - public void maybeStopTrackingJob(JobStatus taskStatus, boolean forUpdate) { - synchronized (mTrackedTasks) { - mTrackedTasks.remove(taskStatus); - } + public void maybeStopTrackingJobLocked(JobStatus taskStatus, boolean forUpdate) { + mTrackedTasks.remove(taskStatus); } /** * Interaction with the task manager service */ void reportNewIdleState(boolean isIdle) { - synchronized (mTrackedTasks) { + synchronized (mLock) { for (JobStatus task : mTrackedTasks) { - task.idleConstraintSatisfied.set(isIdle); + task.setIdleConstraintSatisfied(isIdle); } } mStateChangedListener.onControllerStateChanged(); @@ -193,17 +190,15 @@ public class IdleController extends StateController { } @Override - public void dumpControllerState(PrintWriter pw) { - synchronized (mTrackedTasks) { - pw.print("Idle: "); - pw.println(mIdleTracker.isIdle() ? "true" : "false"); - pw.println(mTrackedTasks.size()); - for (int i = 0; i < mTrackedTasks.size(); i++) { - final JobStatus js = mTrackedTasks.get(i); - pw.print(" "); - pw.print(String.valueOf(js.hashCode()).substring(0, 3)); - pw.println(".."); - } + public void dumpControllerStateLocked(PrintWriter pw) { + pw.print("Idle: "); + pw.println(mIdleTracker.isIdle() ? "true" : "false"); + pw.println(mTrackedTasks.size()); + for (int i = 0; i < mTrackedTasks.size(); i++) { + final JobStatus js = mTrackedTasks.get(i); + pw.print(" "); + pw.print(String.valueOf(js.hashCode()).substring(0, 3)); + pw.println(".."); } } } diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java index c4d564c4e577..f83506909bd6 100644 --- a/services/core/java/com/android/server/job/controllers/JobStatus.java +++ b/services/core/java/com/android/server/job/controllers/JobStatus.java @@ -42,10 +42,19 @@ import java.util.concurrent.atomic.AtomicBoolean; * but we don't enforce that so this is safer. * @hide */ -public class JobStatus { +public final class JobStatus { public static final long NO_LATEST_RUNTIME = Long.MAX_VALUE; public static final long NO_EARLIEST_RUNTIME = 0L; + static final int CONSTRAINT_CHARGING = 1<<0; + static final int CONSTRAINT_TIMING_DELAY = 1<<1; + static final int CONSTRAINT_DEADLINE = 1<<2; + static final int CONSTRAINT_IDLE = 1<<3; + static final int CONSTRAINT_UNMETERED = 1<<4; + static final int CONSTRAINT_CONNECTIVITY = 1<<5; + static final int CONSTRAINT_APP_NOT_IDLE = 1<<6; + static final int CONSTRAINT_CONTENT_TRIGGER = 1<<7; + final JobInfo job; /** Uid of the package requesting this job. */ final int callingUid; @@ -56,15 +65,23 @@ public class JobStatus { final int sourceUserId; final int sourceUid; + /** + * Earliest point in the future at which this job will be eligible to run. A value of 0 + * indicates there is no delay constraint. See {@link #hasTimingDelayConstraint()}. + */ + private final long earliestRunTimeElapsedMillis; + /** + * Latest point in the future at which this job must be run. A value of {@link Long#MAX_VALUE} + * indicates there is no deadline constraint. See {@link #hasDeadlineConstraint()}. + */ + private final long latestRunTimeElapsedMillis; + + /** How many times this job has failed, used to compute back-off. */ + private final int numFailures; + // Constraints. - final AtomicBoolean chargingConstraintSatisfied = new AtomicBoolean(); - final AtomicBoolean timeDelayConstraintSatisfied = new AtomicBoolean(); - final AtomicBoolean deadlineConstraintSatisfied = new AtomicBoolean(); - final AtomicBoolean idleConstraintSatisfied = new AtomicBoolean(); - final AtomicBoolean unmeteredConstraintSatisfied = new AtomicBoolean(); - final AtomicBoolean connectivityConstraintSatisfied = new AtomicBoolean(); - final AtomicBoolean appNotIdleConstraintSatisfied = new AtomicBoolean(); - final AtomicBoolean contentTriggerConstraintSatisfied = new AtomicBoolean(); + final int requiredConstraints; + int satisfiedConstraints = 0; // These are filled in by controllers when preparing for execution. public ArraySet<Uri> changedUris; @@ -76,31 +93,18 @@ public class JobStatus { */ ContentObserverController.JobInstance contentObserverJobInstance; - /** - * Earliest point in the future at which this job will be eligible to run. A value of 0 - * indicates there is no delay constraint. See {@link #hasTimingDelayConstraint()}. - */ - private long earliestRunTimeElapsedMillis; - /** - * Latest point in the future at which this job must be run. A value of {@link Long#MAX_VALUE} - * indicates there is no deadline constraint. See {@link #hasDeadlineConstraint()}. - */ - private long latestRunTimeElapsedMillis; - /** How many times this job has failed, used to compute back-off. */ - private final int numFailures; - /** Provide a handle to the service that this job will be run on. */ public int getServiceToken() { return callingUid; } - private JobStatus(JobInfo job, int callingUid, String sourcePackageName, int sourceUserId, - int numFailures) { + private JobStatus(JobInfo job, int callingUid, String sourcePackageName, + int sourceUserId, int numFailures, long earliestRunTimeElapsedMillis, + long latestRunTimeElapsedMillis) { this.job = job; this.callingUid = callingUid; this.name = job.getService().flattenToShortString(); this.tag = "*job*/" + this.name; - this.numFailures = numFailures; int tempSourceUid = -1; if (sourceUserId != -1 && sourcePackageName != null) { @@ -120,14 +124,64 @@ public class JobStatus { this.sourceUserId = sourceUserId; this.sourcePackageName = sourcePackageName; } + + this.earliestRunTimeElapsedMillis = earliestRunTimeElapsedMillis; + this.latestRunTimeElapsedMillis = latestRunTimeElapsedMillis; + this.numFailures = numFailures; + + int requiredConstraints = 0; + if (job.getNetworkType() == JobInfo.NETWORK_TYPE_ANY) { + requiredConstraints |= CONSTRAINT_CONNECTIVITY; + } + if (job.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED) { + requiredConstraints |= CONSTRAINT_UNMETERED; + } + if (job.isRequireCharging()) { + requiredConstraints |= CONSTRAINT_CHARGING; + } + if (earliestRunTimeElapsedMillis != NO_EARLIEST_RUNTIME) { + requiredConstraints |= CONSTRAINT_TIMING_DELAY; + } + if (latestRunTimeElapsedMillis != NO_LATEST_RUNTIME) { + requiredConstraints |= CONSTRAINT_DEADLINE; + } + if (job.isRequireDeviceIdle()) { + requiredConstraints |= CONSTRAINT_IDLE; + } + if (job.getTriggerContentUris() != null) { + requiredConstraints |= CONSTRAINT_CONTENT_TRIGGER; + } + this.requiredConstraints = requiredConstraints; } /** Copy constructor. */ public JobStatus(JobStatus jobStatus) { - this(jobStatus.getJob(), jobStatus.getUid(), jobStatus.getSourcePackageName(), - jobStatus.getSourceUserId(), jobStatus.getNumFailures()); - this.earliestRunTimeElapsedMillis = jobStatus.getEarliestRunTime(); - this.latestRunTimeElapsedMillis = jobStatus.getLatestRunTimeElapsed(); + this(jobStatus.getJob(), jobStatus.getUid(), + jobStatus.getSourcePackageName(), jobStatus.getSourceUserId(), + jobStatus.getNumFailures(), jobStatus.getEarliestRunTime(), + jobStatus.getLatestRunTimeElapsed()); + } + + /** + * Create a new JobStatus that was loaded from disk. We ignore the provided + * {@link android.app.job.JobInfo} time criteria because we can load a persisted periodic job + * from the {@link com.android.server.job.JobStore} and still want to respect its + * wallclock runtime rather than resetting it on every boot. + * We consider a freshly loaded job to no longer be in back-off. + */ + public JobStatus(JobInfo job, int callingUid, String sourcePackageName, + int sourceUserId, long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis) { + this(job, callingUid, sourcePackageName, sourceUserId, 0, earliestRunTimeElapsedMillis, + latestRunTimeElapsedMillis); + } + + /** Create a new job to be rescheduled with the provided parameters. */ + public JobStatus(JobStatus rescheduling, long newEarliestRuntimeElapsedMillis, + long newLatestRuntimeElapsedMillis, int backoffAttempt) { + this(rescheduling.job, rescheduling.getUid(), + rescheduling.getSourcePackageName(), + rescheduling.getSourceUserId(), backoffAttempt, newEarliestRuntimeElapsedMillis, + newLatestRuntimeElapsedMillis); } /** @@ -136,13 +190,11 @@ public class JobStatus { * @param sourcePackageName Package name on whose behalf this job is scheduled. Null indicates * the calling package is the source. * @param sourceUserId User id for whom this job is scheduled. -1 indicates this is same as the - * calling userId. */ - public JobStatus(JobInfo job, int callingUid, String sourcePackageName, int sourceUserId) { - this(job, callingUid, sourcePackageName, sourceUserId, 0); - + public static JobStatus createFromJobInfo(JobInfo job, int callingUid, String sourcePackageName, + int sourceUserId) { final long elapsedNow = SystemClock.elapsedRealtime(); - + final long earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis; if (job.isPeriodic()) { latestRunTimeElapsedMillis = elapsedNow + job.getIntervalMillis(); earliestRunTimeElapsedMillis = latestRunTimeElapsedMillis - job.getFlexMillis(); @@ -152,31 +204,8 @@ public class JobStatus { latestRunTimeElapsedMillis = job.hasLateConstraint() ? elapsedNow + job.getMaxExecutionDelayMillis() : NO_LATEST_RUNTIME; } - } - - /** - * Create a new JobStatus that was loaded from disk. We ignore the provided - * {@link android.app.job.JobInfo} time criteria because we can load a persisted periodic job - * from the {@link com.android.server.job.JobStore} and still want to respect its - * wallclock runtime rather than resetting it on every boot. - * We consider a freshly loaded job to no longer be in back-off. - */ - public JobStatus(JobInfo job, int callingUid, String sourcePackageName, int sourceUserId, - long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis) { - this(job, callingUid, sourcePackageName, sourceUserId, 0); - - this.earliestRunTimeElapsedMillis = earliestRunTimeElapsedMillis; - this.latestRunTimeElapsedMillis = latestRunTimeElapsedMillis; - } - - /** Create a new job to be rescheduled with the provided parameters. */ - public JobStatus(JobStatus rescheduling, long newEarliestRuntimeElapsedMillis, - long newLatestRuntimeElapsedMillis, int backoffAttempt) { - this(rescheduling.job, rescheduling.getUid(), rescheduling.getSourcePackageName(), - rescheduling.getSourceUserId(), backoffAttempt); - - earliestRunTimeElapsedMillis = newEarliestRuntimeElapsedMillis; - latestRunTimeElapsedMillis = newLatestRuntimeElapsedMillis; + return new JobStatus(job, callingUid, sourcePackageName, sourceUserId, 0, + earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis); } public JobInfo getJob() { @@ -232,31 +261,31 @@ public class JobStatus { } public boolean hasConnectivityConstraint() { - return job.getNetworkType() == JobInfo.NETWORK_TYPE_ANY; + return (requiredConstraints&CONSTRAINT_CONNECTIVITY) != 0; } public boolean hasUnmeteredConstraint() { - return job.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED; + return (requiredConstraints&CONSTRAINT_UNMETERED) != 0; } public boolean hasChargingConstraint() { - return job.isRequireCharging(); + return (requiredConstraints&CONSTRAINT_CHARGING) != 0; } public boolean hasTimingDelayConstraint() { - return earliestRunTimeElapsedMillis != NO_EARLIEST_RUNTIME; + return (requiredConstraints&CONSTRAINT_TIMING_DELAY) != 0; } public boolean hasDeadlineConstraint() { - return latestRunTimeElapsedMillis != NO_LATEST_RUNTIME; + return (requiredConstraints&CONSTRAINT_DEADLINE) != 0; } public boolean hasIdleConstraint() { - return job.isRequireDeviceIdle(); + return (requiredConstraints&CONSTRAINT_IDLE) != 0; } public boolean hasContentTriggerConstraint() { - return job.getTriggerContentUris() != null; + return (requiredConstraints&CONSTRAINT_CONTENT_TRIGGER) != 0; } public boolean isPersisted() { @@ -271,31 +300,74 @@ public class JobStatus { return latestRunTimeElapsedMillis; } + boolean setChargingConstraintSatisfied(boolean state) { + return setConstraintSatisfied(CONSTRAINT_CHARGING, state); + } + + boolean setTimingDelayConstraintSatisfied(boolean state) { + return setConstraintSatisfied(CONSTRAINT_TIMING_DELAY, state); + } + + boolean setDeadlineConstraintSatisfied(boolean state) { + return setConstraintSatisfied(CONSTRAINT_DEADLINE, state); + } + + boolean setIdleConstraintSatisfied(boolean state) { + return setConstraintSatisfied(CONSTRAINT_IDLE, state); + } + + boolean setUnmeteredConstraintSatisfied(boolean state) { + return setConstraintSatisfied(CONSTRAINT_UNMETERED, state); + } + + boolean setConnectivityConstraintSatisfied(boolean state) { + return setConstraintSatisfied(CONSTRAINT_CONNECTIVITY, state); + } + + boolean setAppNotIdleConstraintSatisfied(boolean state) { + return setConstraintSatisfied(CONSTRAINT_APP_NOT_IDLE, state); + } + + boolean setContentTriggerConstraintSatisfied(boolean state) { + return setConstraintSatisfied(CONSTRAINT_CONTENT_TRIGGER, state); + } + + boolean setConstraintSatisfied(int constraint, boolean state) { + boolean old = (satisfiedConstraints&constraint) != 0; + if (old == state) { + return false; + } + satisfiedConstraints = (satisfiedConstraints&~constraint) | (state ? constraint : 0); + return true; + } + /** * @return Whether or not this job is ready to run, based on its requirements. This is true if * the constraints are satisfied <strong>or</strong> the deadline on the job has expired. */ - public synchronized boolean isReady() { + public boolean isReady() { // Deadline constraint trumps other constraints (except for periodic jobs where deadline // (is an implementation detail. A periodic job should only run if it's constraints are // satisfied). // AppNotIdle implicit constraint trumps all! return (isConstraintsSatisfied() - || (!job.isPeriodic() - && hasDeadlineConstraint() && deadlineConstraintSatisfied.get())) - && appNotIdleConstraintSatisfied.get(); + || (!job.isPeriodic() + && hasDeadlineConstraint() && (satisfiedConstraints&CONSTRAINT_DEADLINE) != 0)) + && (satisfiedConstraints&CONSTRAINT_APP_NOT_IDLE) != 0; } + static final int CONSTRAINTS_OF_INTEREST = + CONSTRAINT_CHARGING | CONSTRAINT_TIMING_DELAY | + CONSTRAINT_CONNECTIVITY | CONSTRAINT_UNMETERED | + CONSTRAINT_IDLE | CONSTRAINT_CONTENT_TRIGGER; + /** * @return Whether the constraints set on this job are satisfied. */ - public synchronized boolean isConstraintsSatisfied() { - return (!hasChargingConstraint() || chargingConstraintSatisfied.get()) - && (!hasTimingDelayConstraint() || timeDelayConstraintSatisfied.get()) - && (!hasConnectivityConstraint() || connectivityConstraintSatisfied.get()) - && (!hasUnmeteredConstraint() || unmeteredConstraintSatisfied.get()) - && (!hasIdleConstraint() || idleConstraintSatisfied.get()) - && (!hasContentTriggerConstraint() || contentTriggerConstraintSatisfied.get()); + public boolean isConstraintsSatisfied() { + final int req = requiredConstraints & CONSTRAINTS_OF_INTEREST; + final int sat = satisfiedConstraints & CONSTRAINTS_OF_INTEREST; + return (sat & req) == req; } public boolean matches(int uid, int jobId) { @@ -314,7 +386,7 @@ public class JobStatus { + ",I=" + job.isRequireDeviceIdle() + ",U=" + (job.getTriggerContentUris() != null) + ",F=" + numFailures + ",P=" + job.isPersisted() - + ",ANI=" + appNotIdleConstraintSatisfied.get() + + ",ANI=" + ((satisfiedConstraints&CONSTRAINT_APP_NOT_IDLE) != 0) + (isReady() ? "(READY)" : "") + "]"; } @@ -349,6 +421,33 @@ public class JobStatus { return sb.toString(); } + void dumpConstraints(PrintWriter pw, int constraints) { + if ((constraints&CONSTRAINT_CHARGING) != 0) { + pw.print(" CHARGING"); + } + if ((constraints&CONSTRAINT_TIMING_DELAY) != 0) { + pw.print(" TIMING_DELAY"); + } + if ((constraints&CONSTRAINT_DEADLINE) != 0) { + pw.print(" DEADLINE"); + } + if ((constraints&CONSTRAINT_IDLE) != 0) { + pw.print(" IDLE"); + } + if ((constraints&CONSTRAINT_UNMETERED) != 0) { + pw.print(" UNMETERED"); + } + if ((constraints&CONSTRAINT_CONNECTIVITY) != 0) { + pw.print(" CONNECTIVITY"); + } + if ((constraints&CONSTRAINT_APP_NOT_IDLE) != 0) { + pw.print(" APP_NOT_IDLE"); + } + if ((constraints&CONSTRAINT_CONTENT_TRIGGER) != 0) { + pw.print(" CONTENT_TRIGGER"); + } + } + // Dumpsys infrastructure public void dump(PrintWriter pw, String prefix) { pw.print(prefix); UserHandle.formatUid(pw, callingUid); @@ -413,39 +512,12 @@ public class JobStatus { if (job.hasLateConstraint()) { pw.print(prefix); pw.println(" Has late constraint"); } - pw.print(prefix); pw.println("Constraints:"); - if (hasChargingConstraint()) { - pw.print(prefix); pw.print(" Charging: "); - pw.println(chargingConstraintSatisfied.get()); - } - if (hasTimingDelayConstraint()) { - pw.print(prefix); pw.print(" Time delay: "); - pw.println(timeDelayConstraintSatisfied.get()); - } - if (hasDeadlineConstraint()) { - pw.print(prefix); pw.print(" Deadline: "); - pw.println(deadlineConstraintSatisfied.get()); - } - if (hasIdleConstraint()) { - pw.print(prefix); pw.print(" System idle: "); - pw.println(idleConstraintSatisfied.get()); - } - if (hasUnmeteredConstraint()) { - pw.print(prefix); pw.print(" Unmetered: "); - pw.println(unmeteredConstraintSatisfied.get()); - } - if (hasConnectivityConstraint()) { - pw.print(prefix); pw.print(" Connectivity: "); - pw.println(connectivityConstraintSatisfied.get()); - } - if (hasIdleConstraint()) { - pw.print(prefix); pw.print(" App not idle: "); - pw.println(appNotIdleConstraintSatisfied.get()); - } - if (hasContentTriggerConstraint()) { - pw.print(prefix); pw.print(" Content trigger: "); - pw.println(contentTriggerConstraintSatisfied.get()); - } + pw.print(prefix); pw.print("Required constraints:"); + dumpConstraints(pw, requiredConstraints); + pw.println(); + pw.print(prefix); pw.print("Satisfied constraints:"); + dumpConstraints(pw, satisfiedConstraints); + pw.println(); if (changedAuthorities != null) { pw.print(prefix); pw.println("Changed authorities:"); for (int i=0; i<changedAuthorities.size(); i++) { diff --git a/services/core/java/com/android/server/job/controllers/StateController.java b/services/core/java/com/android/server/job/controllers/StateController.java index b619ea8cdd5d..7882bc4d86ab 100644 --- a/services/core/java/com/android/server/job/controllers/StateController.java +++ b/services/core/java/com/android/server/job/controllers/StateController.java @@ -30,13 +30,16 @@ import java.io.PrintWriter; */ public abstract class StateController { protected static final boolean DEBUG = JobSchedulerService.DEBUG; - protected Context mContext; - protected StateChangedListener mStateChangedListener; + protected final Context mContext; + protected final Object mLock; + protected final StateChangedListener mStateChangedListener; protected boolean mDeviceIdleMode; - public StateController(StateChangedListener stateChangedListener, Context context) { + public StateController(StateChangedListener stateChangedListener, Context context, + Object lock) { mStateChangedListener = stateChangedListener; mContext = context; + mLock = lock; } public void deviceIdleModeChanged(boolean enabled) { @@ -49,21 +52,21 @@ public abstract class StateController { * Also called when updating a task, so implementing controllers have to be aware of * preexisting tasks. */ - public abstract void maybeStartTrackingJob(JobStatus jobStatus, JobStatus lastJob); + public abstract void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob); /** * Optionally implement logic here to prepare the job to be executed. */ - public void prepareForExecution(JobStatus jobStatus) { + public void prepareForExecutionLocked(JobStatus jobStatus) { } /** * Remove task - this will happen if the task is cancelled, completed, etc. */ - public abstract void maybeStopTrackingJob(JobStatus jobStatus, boolean forUpdate); + public abstract void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate); /** * Called when a new job is being created to reschedule an old failed job. */ public void rescheduleForFailure(JobStatus newJob, JobStatus failureToReschedule) { } - public abstract void dumpControllerState(PrintWriter pw); + public abstract void dumpControllerStateLocked(PrintWriter pw); } diff --git a/services/core/java/com/android/server/job/controllers/TimeController.java b/services/core/java/com/android/server/job/controllers/TimeController.java index a68c3adabb08..620800caaf67 100644 --- a/services/core/java/com/android/server/job/controllers/TimeController.java +++ b/services/core/java/com/android/server/job/controllers/TimeController.java @@ -54,13 +54,14 @@ public class TimeController extends StateController { public static synchronized TimeController get(JobSchedulerService jms) { if (mSingleton == null) { - mSingleton = new TimeController(jms, jms.getContext()); + mSingleton = new TimeController(jms, jms.getContext(), jms.getLock()); } return mSingleton; } - private TimeController(StateChangedListener stateChangedListener, Context context) { - super(stateChangedListener, context); + private TimeController(StateChangedListener stateChangedListener, Context context, + Object lock) { + super(stateChangedListener, context, lock); mNextJobExpiredElapsedMillis = Long.MAX_VALUE; mNextDelayExpiredElapsedMillis = Long.MAX_VALUE; @@ -71,9 +72,9 @@ public class TimeController extends StateController { * list. */ @Override - public synchronized void maybeStartTrackingJob(JobStatus job, JobStatus lastJob) { + public void maybeStartTrackingJobLocked(JobStatus job, JobStatus lastJob) { if (job.hasTimingDelayConstraint() || job.hasDeadlineConstraint()) { - maybeStopTrackingJob(job, false); + maybeStopTrackingJobLocked(job, false); boolean isInsert = false; ListIterator<JobStatus> it = mTrackedJobs.listIterator(mTrackedJobs.size()); while (it.hasPrevious()) { @@ -84,12 +85,11 @@ public class TimeController extends StateController { break; } } - if(isInsert) - { + if (isInsert) { it.next(); } it.add(job); - maybeUpdateAlarms( + maybeUpdateAlarmsLocked( job.hasTimingDelayConstraint() ? job.getEarliestRunTime() : Long.MAX_VALUE, job.hasDeadlineConstraint() ? job.getLatestRunTimeElapsed() : Long.MAX_VALUE); } @@ -101,7 +101,7 @@ public class TimeController extends StateController { * Really an == comparison should be enough, but why play with fate? We'll do <=. */ @Override - public synchronized void maybeStopTrackingJob(JobStatus job, boolean forUpdate) { + public void maybeStopTrackingJobLocked(JobStatus job, boolean forUpdate) { if (mTrackedJobs.remove(job)) { checkExpiredDelaysAndResetAlarm(); checkExpiredDeadlinesAndResetAlarm(); @@ -114,14 +114,14 @@ public class TimeController extends StateController { * the job's deadline is fulfilled - unlike other controllers a time constraint can't toggle * back and forth. */ - private boolean canStopTrackingJob(JobStatus job) { + private boolean canStopTrackingJobLocked(JobStatus job) { return (!job.hasTimingDelayConstraint() || - job.timeDelayConstraintSatisfied.get()) && + (job.satisfiedConstraints&JobStatus.CONSTRAINT_TIMING_DELAY) != 0) && (!job.hasDeadlineConstraint() || - job.deadlineConstraintSatisfied.get()); + (job.satisfiedConstraints&JobStatus.CONSTRAINT_DEADLINE) != 0); } - private void ensureAlarmService() { + private void ensureAlarmServiceLocked() { if (mAlarmService == null) { mAlarmService = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); } @@ -131,71 +131,75 @@ public class TimeController extends StateController { * Checks list of jobs for ones that have an expired deadline, sending them to the JobScheduler * if so, removing them from this list, and updating the alarm for the next expiry time. */ - private synchronized void checkExpiredDeadlinesAndResetAlarm() { - long nextExpiryTime = Long.MAX_VALUE; - final long nowElapsedMillis = SystemClock.elapsedRealtime(); + private void checkExpiredDeadlinesAndResetAlarm() { + synchronized (mLock) { + long nextExpiryTime = Long.MAX_VALUE; + final long nowElapsedMillis = SystemClock.elapsedRealtime(); - Iterator<JobStatus> it = mTrackedJobs.iterator(); - while (it.hasNext()) { - JobStatus job = it.next(); - if (!job.hasDeadlineConstraint()) { - continue; - } - final long jobDeadline = job.getLatestRunTimeElapsed(); + Iterator<JobStatus> it = mTrackedJobs.iterator(); + while (it.hasNext()) { + JobStatus job = it.next(); + if (!job.hasDeadlineConstraint()) { + continue; + } + final long jobDeadline = job.getLatestRunTimeElapsed(); - if (jobDeadline <= nowElapsedMillis) { - job.deadlineConstraintSatisfied.set(true); - mStateChangedListener.onRunJobNow(job); - it.remove(); - } else { // Sorted by expiry time, so take the next one and stop. - nextExpiryTime = jobDeadline; - break; + if (jobDeadline <= nowElapsedMillis) { + job.setDeadlineConstraintSatisfied(true); + mStateChangedListener.onRunJobNow(job); + it.remove(); + } else { // Sorted by expiry time, so take the next one and stop. + nextExpiryTime = jobDeadline; + break; + } } + setDeadlineExpiredAlarmLocked(nextExpiryTime); } - setDeadlineExpiredAlarm(nextExpiryTime); } /** * Handles alarm that notifies us that a job's delay has expired. Iterates through the list of * tracked jobs and marks them as ready as appropriate. */ - private synchronized void checkExpiredDelaysAndResetAlarm() { - final long nowElapsedMillis = SystemClock.elapsedRealtime(); - long nextDelayTime = Long.MAX_VALUE; - boolean ready = false; - Iterator<JobStatus> it = mTrackedJobs.iterator(); - while (it.hasNext()) { - final JobStatus job = it.next(); - if (!job.hasTimingDelayConstraint()) { - continue; - } - final long jobDelayTime = job.getEarliestRunTime(); - if (jobDelayTime <= nowElapsedMillis) { - job.timeDelayConstraintSatisfied.set(true); - if (canStopTrackingJob(job)) { - it.remove(); - } - if (job.isReady()) { - ready = true; + private void checkExpiredDelaysAndResetAlarm() { + synchronized (mLock) { + final long nowElapsedMillis = SystemClock.elapsedRealtime(); + long nextDelayTime = Long.MAX_VALUE; + boolean ready = false; + Iterator<JobStatus> it = mTrackedJobs.iterator(); + while (it.hasNext()) { + final JobStatus job = it.next(); + if (!job.hasTimingDelayConstraint()) { + continue; } - } else { // Keep going through list to get next delay time. - if (nextDelayTime > jobDelayTime) { - nextDelayTime = jobDelayTime; + final long jobDelayTime = job.getEarliestRunTime(); + if (jobDelayTime <= nowElapsedMillis) { + job.setTimingDelayConstraintSatisfied(true); + if (canStopTrackingJobLocked(job)) { + it.remove(); + } + if (job.isReady()) { + ready = true; + } + } else { // Keep going through list to get next delay time. + if (nextDelayTime > jobDelayTime) { + nextDelayTime = jobDelayTime; + } } } + if (ready) { + mStateChangedListener.onControllerStateChanged(); + } + setDelayExpiredAlarmLocked(nextDelayTime); } - if (ready) { - mStateChangedListener.onControllerStateChanged(); - } - setDelayExpiredAlarm(nextDelayTime); } - private void maybeUpdateAlarms(long delayExpiredElapsed, long deadlineExpiredElapsed) { + private void maybeUpdateAlarmsLocked(long delayExpiredElapsed, long deadlineExpiredElapsed) { if (delayExpiredElapsed < mNextDelayExpiredElapsedMillis) { - setDelayExpiredAlarm(delayExpiredElapsed); + setDelayExpiredAlarmLocked(delayExpiredElapsed); } if (deadlineExpiredElapsed < mNextJobExpiredElapsedMillis) { - setDeadlineExpiredAlarm(deadlineExpiredElapsed); + setDeadlineExpiredAlarmLocked(deadlineExpiredElapsed); } } @@ -204,10 +208,11 @@ public class TimeController extends StateController { * delay will expire. * This alarm <b>will</b> wake up the phone. */ - private void setDelayExpiredAlarm(long alarmTimeElapsedMillis) { + private void setDelayExpiredAlarmLocked(long alarmTimeElapsedMillis) { alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis); mNextDelayExpiredElapsedMillis = alarmTimeElapsedMillis; - updateAlarmWithListener(DELAY_TAG, mNextDelayExpiredListener, mNextDelayExpiredElapsedMillis); + updateAlarmWithListenerLocked(DELAY_TAG, mNextDelayExpiredListener, + mNextDelayExpiredElapsedMillis); } /** @@ -215,10 +220,11 @@ public class TimeController extends StateController { * deadline will expire. * This alarm <b>will</b> wake up the phone. */ - private void setDeadlineExpiredAlarm(long alarmTimeElapsedMillis) { + private void setDeadlineExpiredAlarmLocked(long alarmTimeElapsedMillis) { alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis); mNextJobExpiredElapsedMillis = alarmTimeElapsedMillis; - updateAlarmWithListener(DEADLINE_TAG, mDeadlineExpiredListener, mNextJobExpiredElapsedMillis); + updateAlarmWithListenerLocked(DEADLINE_TAG, mDeadlineExpiredListener, + mNextJobExpiredElapsedMillis); } private long maybeAdjustAlarmTime(long proposedAlarmTimeElapsedMillis) { @@ -229,9 +235,9 @@ public class TimeController extends StateController { return proposedAlarmTimeElapsedMillis; } - private void updateAlarmWithListener(String tag, OnAlarmListener listener, + private void updateAlarmWithListenerLocked(String tag, OnAlarmListener listener, long alarmTimeElapsed) { - ensureAlarmService(); + ensureAlarmServiceLocked(); if (alarmTimeElapsed == Long.MAX_VALUE) { mAlarmService.cancel(listener); } else { @@ -266,7 +272,7 @@ public class TimeController extends StateController { }; @Override - public void dumpControllerState(PrintWriter pw) { + public void dumpControllerStateLocked(PrintWriter pw) { final long nowElapsed = SystemClock.elapsedRealtime(); pw.println("Alarms (" + SystemClock.elapsedRealtime() + ")"); pw.println( diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java index c1eb844f09fa..7fb1783e2e03 100644 --- a/services/core/java/com/android/server/location/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/GnssLocationProvider.java @@ -1684,25 +1684,25 @@ public class GnssLocationProvider implements LocationProviderInterface { /** * Called from native code to inform us the hardware information. */ - private void setGpsYearOfHardware(int yearOfHardware) { - if (DEBUG) Log.d(TAG, "setGpsYearOfHardware called with " + yearOfHardware); + private void setGnssYearOfHardware(int yearOfHardware) { + if (DEBUG) Log.d(TAG, "setGnssYearOfHardware called with " + yearOfHardware); mYearOfHardware = yearOfHardware; } - public interface GpsSystemInfoProvider { + public interface GnssSystemInfoProvider { /** * Returns the year of GPS hardware. */ - int getGpsYearOfHardware(); + int getGnssYearOfHardware(); } /** * @hide */ - public GpsSystemInfoProvider getGpsSystemInfoProvider() { - return new GpsSystemInfoProvider() { + public GnssSystemInfoProvider getGnssSystemInfoProvider() { + return new GnssSystemInfoProvider() { @Override - public int getGpsYearOfHardware() { + public int getGnssYearOfHardware() { return mYearOfHardware; } }; diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index 246da2e10de5..862c061c6b9c 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -868,6 +868,38 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } } + public void prepare() { + try { + mCb.onPrepare(); + } catch (RemoteException e) { + Slog.e(TAG, "Remote failure in prepare.", e); + } + } + + public void prepareFromMediaId(String mediaId, Bundle extras) { + try { + mCb.onPrepareFromMediaId(mediaId, extras); + } catch (RemoteException e) { + Slog.e(TAG, "Remote failure in prepareFromMediaId.", e); + } + } + + public void prepareFromSearch(String query, Bundle extras) { + try { + mCb.onPrepareFromSearch(query, extras); + } catch (RemoteException e) { + Slog.e(TAG, "Remote failure in prepareFromSearch.", e); + } + } + + public void prepareFromUri(Uri uri, Bundle extras) { + try { + mCb.onPrepareFromUri(uri, extras); + } catch (RemoteException e) { + Slog.e(TAG, "Remote failure in prepareFromUri.", e); + } + } + public void play() { try { mCb.onPlay(); @@ -880,7 +912,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { try { mCb.onPlayFromMediaId(mediaId, extras); } catch (RemoteException e) { - Slog.e(TAG, "Remote failure in playUri.", e); + Slog.e(TAG, "Remote failure in playFromMediaId.", e); } } @@ -1100,6 +1132,27 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } @Override + public void prepare() throws RemoteException { + mSessionCb.prepare(); + } + + @Override + public void prepareFromMediaId(String mediaId, Bundle extras) + throws RemoteException { + mSessionCb.prepareFromMediaId(mediaId, extras); + } + + @Override + public void prepareFromSearch(String query, Bundle extras) throws RemoteException { + mSessionCb.prepareFromSearch(query, extras); + } + + @Override + public void prepareFromUri(Uri uri, Bundle extras) throws RemoteException { + mSessionCb.prepareFromUri(uri, extras); + } + + @Override public void play() throws RemoteException { mSessionCb.play(); } diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index bc5b56114298..34214332a987 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -1742,13 +1742,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { public void setNetworkPolicies(NetworkPolicy[] policies) { mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); - maybeRefreshTrustedTime(); - synchronized (mRulesLock) { - normalizePoliciesLocked(policies); - updateNetworkEnabledLocked(); - updateNetworkRulesLocked(); - updateNotificationsLocked(); - writePolicyLocked(); + final long token = Binder.clearCallingIdentity(); + try { + maybeRefreshTrustedTime(); + synchronized (mRulesLock) { + normalizePoliciesLocked(policies); + updateNetworkEnabledLocked(); + updateNetworkRulesLocked(); + updateNotificationsLocked(); + writePolicyLocked(); + } + } finally { + Binder.restoreCallingIdentity(token); } } @@ -1851,13 +1856,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { @Override public void setRestrictBackground(boolean restrictBackground) { mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); + final long token = Binder.clearCallingIdentity(); + try { + maybeRefreshTrustedTime(); + synchronized (mRulesLock) { + mRestrictBackground = restrictBackground; + updateRulesForGlobalChangeLocked(true); + updateNotificationsLocked(); + writePolicyLocked(); + } - maybeRefreshTrustedTime(); - synchronized (mRulesLock) { - mRestrictBackground = restrictBackground; - updateRulesForGlobalChangeLocked(true); - updateNotificationsLocked(); - writePolicyLocked(); + } finally { + Binder.restoreCallingIdentity(token); } mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_CHANGED, restrictBackground ? 1 : 0, 0) diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java index 5cd102556fc3..a5dc008d4e6c 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java @@ -211,12 +211,7 @@ class NetworkPolicyManagerShellCommand extends ShellCommand { if (enabled < 0) { return enabled; } - final long token = Binder.clearCallingIdentity(); - try { - mInterface.setRestrictBackground(enabled > 0); - } finally { - Binder.restoreCallingIdentity(token); - } + mInterface.setRestrictBackground(enabled > 0); return 0; } @@ -225,12 +220,7 @@ class NetworkPolicyManagerShellCommand extends ShellCommand { if (uid < 0) { return uid; } - final long token = Binder.clearCallingIdentity(); - try { - mInterface.addRestrictBackgroundWhitelistedUid(uid); - } finally { - Binder.restoreCallingIdentity(token); - } + mInterface.addRestrictBackgroundWhitelistedUid(uid); return 0; } @@ -239,12 +229,7 @@ class NetworkPolicyManagerShellCommand extends ShellCommand { if (uid < 0) { return uid; } - final long token = Binder.clearCallingIdentity(); - try { - mInterface.removeRestrictBackgroundWhitelistedUid(uid); - } finally { - Binder.restoreCallingIdentity(token); - } + mInterface.removeRestrictBackgroundWhitelistedUid(uid); return 0; } diff --git a/services/core/java/com/android/server/notification/TopicImportanceExtractor.java b/services/core/java/com/android/server/notification/ImportanceExtractor.java index c6b3e0fdb0d6..885b9b7919a7 100644 --- a/services/core/java/com/android/server/notification/TopicImportanceExtractor.java +++ b/services/core/java/com/android/server/notification/ImportanceExtractor.java @@ -21,7 +21,7 @@ import android.util.Slog; /** * Determines the importance of the given notification. */ -public class TopicImportanceExtractor implements NotificationSignalExtractor { +public class ImportanceExtractor implements NotificationSignalExtractor { private static final String TAG = "ImportantTopicExtractor"; private static final boolean DBG = false; @@ -42,9 +42,8 @@ public class TopicImportanceExtractor implements NotificationSignalExtractor { return null; } - final int topicImportance = mConfig.getImportance(record.sbn.getPackageName(), - record.sbn.getUid(), record.sbn.getNotification().getTopic()); - record.setTopicImportance(topicImportance); + record.setUserImportance( + mConfig.getImportance(record.sbn.getPackageName(), record.sbn.getUid())); return null; } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index ede1a2f2f457..95198a316d47 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -30,7 +30,6 @@ import static android.service.notification.NotificationAssistantService.REASON_P import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_CHANGED; import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_SUSPENDED; import static android.service.notification.NotificationAssistantService.REASON_PROFILE_TURNED_OFF; -import static android.service.notification.NotificationAssistantService.REASON_TOPIC_BANNED; import static android.service.notification.NotificationAssistantService.REASON_USER_STOPPED; import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS; import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_OFF; @@ -754,7 +753,7 @@ public class NotificationManagerService extends SystemService { for (String pkgName : pkgList) { if (cancelNotifications) { cancelAllNotificationsInt(MY_UID, MY_PID, pkgName, 0, 0, !queryRestart, - changeUserId, reason, null, null); + changeUserId, reason, null); } } } @@ -787,14 +786,14 @@ public class NotificationManagerService extends SystemService { int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); if (userHandle >= 0) { cancelAllNotificationsInt(MY_UID, MY_PID, null, 0, 0, true, userHandle, - REASON_USER_STOPPED, null, null); + REASON_USER_STOPPED, null); } } else if (action.equals(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED)) { boolean inQuietMode = intent.getBooleanExtra(Intent.EXTRA_QUIET_MODE, false); int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); if (inQuietMode && userHandle >= 0) { cancelAllNotificationsInt(MY_UID, MY_PID, null, 0, 0, true, userHandle, - REASON_PROFILE_TURNED_OFF, null, null); + REASON_PROFILE_TURNED_OFF, null); } } else if (action.equals(Intent.ACTION_USER_PRESENT)) { // turn off LED when user passes through lock screen @@ -1086,7 +1085,7 @@ public class NotificationManagerService extends SystemService { // Now, cancel any outstanding notifications that are part of a just-disabled app if (ENABLE_BLOCKED_NOTIFICATIONS && !enabled) { cancelAllNotificationsInt(MY_UID, MY_PID, pkg, 0, 0, true, UserHandle.getUserId(uid), - REASON_PACKAGE_BANNED, null, null); + REASON_PACKAGE_BANNED, null); } } @@ -1250,7 +1249,7 @@ public class NotificationManagerService extends SystemService { // running foreground services. cancelAllNotificationsInt(Binder.getCallingUid(), Binder.getCallingPid(), pkg, 0, Notification.FLAG_FOREGROUND_SERVICE, true, userId, - REASON_APP_CANCEL_ALL, null, null); + REASON_APP_CANCEL_ALL, null); } @Override @@ -1279,79 +1278,50 @@ public class NotificationManagerService extends SystemService { } @Override - public boolean hasBannedTopics(String pkg, int uid) { + public void setPriority(String pkg, int uid, int priority) { checkCallerIsSystem(); - return mRankingHelper.hasBannedTopics(pkg, uid); - } - - @Override - public ParceledListSlice<Notification.Topic> getTopics(String pkg, int uid) { - checkCallerIsSystem(); - return new ParceledListSlice<Notification.Topic>(mRankingHelper.getTopics(pkg, uid)); - } - - @Override - public void setPriority(String pkg, int uid, Notification.Topic topic, int priority) { - checkCallerIsSystem(); - mRankingHelper.setPriority(pkg, uid, topic, priority); + mRankingHelper.setPriority(pkg, uid, priority); savePolicyFile(); } @Override - public int getPriority(String pkg, int uid, Notification.Topic topic) { + public int getPriority(String pkg, int uid) { checkCallerIsSystem(); - return mRankingHelper.getPriority(pkg, uid, topic); + return mRankingHelper.getPriority(pkg, uid); } @Override - public void setVisibilityOverride(String pkg, int uid, Notification.Topic topic, - int visibility) { + public void setVisibilityOverride(String pkg, int uid, int visibility) { checkCallerIsSystem(); - mRankingHelper.setVisibilityOverride(pkg, uid, topic, visibility); + mRankingHelper.setVisibilityOverride(pkg, uid, visibility); savePolicyFile(); } @Override - public int getVisibilityOverride(String pkg, int uid, Notification.Topic topic) { + public int getVisibilityOverride(String pkg, int uid) { checkCallerIsSystem(); - return mRankingHelper.getVisibilityOverride(pkg, uid, topic); + return mRankingHelper.getVisibilityOverride(pkg, uid); } @Override - public void setImportance(String pkg, int uid, Notification.Topic topic, - int importance) { + public void setImportance(String pkg, int uid, int importance) { enforceSystemOrSystemUI("Caller not system or systemui"); - if (topic == null) { - // App wide, potentially store block in app ops. - setNotificationsEnabledForPackageImpl(pkg, uid, - importance != NotificationListenerService.Ranking.IMPORTANCE_NONE); - } else { - if (NotificationListenerService.Ranking.IMPORTANCE_NONE == importance) { - cancelAllNotificationsInt(MY_UID, MY_PID, pkg, 0, 0, true, - UserHandle.getUserId(uid), - REASON_TOPIC_BANNED, topic, null); - } - } - mRankingHelper.setImportance(pkg, uid, topic, importance); + setNotificationsEnabledForPackageImpl(pkg, uid, + importance != NotificationListenerService.Ranking.IMPORTANCE_NONE); + mRankingHelper.setImportance(pkg, uid, importance); savePolicyFile(); } @Override - public int getTopicImportance(String pkg, String topicId) { + public int getPackageImportance(String pkg) { checkCallerIsSystemOrSameApp(pkg); - return mRankingHelper.getImportance(pkg, Binder.getCallingUid(), topicId); + return mRankingHelper.getImportance(pkg, Binder.getCallingUid()); } @Override - public int getImportance(String pkg, int uid, Notification.Topic topic) { + public int getImportance(String pkg, int uid) { checkCallerIsSystem(); - return mRankingHelper.getImportance(pkg, uid, topic); - } - - @Override - public boolean doesUserUseTopics(String pkg, int uid) { - enforceSystemOrSystemUI("Caller not system or systemui"); - return mRankingHelper.doesUserUseTopics(pkg, uid); + return mRankingHelper.getImportance(pkg, uid); } /** @@ -2381,11 +2351,9 @@ public class NotificationManagerService extends SystemService { mRankingHelper.extractSignals(r); - // why is this here? - savePolicyFile(); final boolean isPackageSuspended = isPackageSuspendedForUser(pkg, callingUid); - // blocked apps/topics + // blocked apps if (r.getImportance() == NotificationListenerService.Ranking.IMPORTANCE_NONE || !noteNotificationOp(pkg, callingUid) || isPackageSuspended) { if (!isSystemNotification) { @@ -3182,11 +3150,11 @@ public class NotificationManagerService extends SystemService { } /** - * Cancels all notifications from a given package or topic that have all of the + * Cancels all notifications from a given package that have all of the * {@code mustHaveFlags}. */ boolean cancelAllNotificationsInt(int callingUid, int callingPid, String pkg, int mustHaveFlags, - int mustNotHaveFlags, boolean doit, int userId, int reason, Notification.Topic topic, + int mustNotHaveFlags, boolean doit, int userId, int reason, ManagedServiceInfo listener) { String listenerName = listener == null ? null : listener.component.toShortString(); EventLogTags.writeNotificationCancelAll(callingUid, callingPid, @@ -3214,10 +3182,6 @@ public class NotificationManagerService extends SystemService { if (pkg != null && !r.sbn.getPackageName().equals(pkg)) { continue; } - if (topic != null - && !topic.getId().equals(r.getNotification().getTopic().getId())) { - continue; - } if (canceledNotifications == null) { canceledNotifications = new ArrayList<>(); } diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java index 2ca5534b3310..25d17f60a054 100644 --- a/services/core/java/com/android/server/notification/NotificationRecord.java +++ b/services/core/java/com/android/server/notification/NotificationRecord.java @@ -35,7 +35,6 @@ import android.service.notification.NotificationListenerService; import android.service.notification.StatusBarNotification; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.logging.MetricsLogger; import com.android.server.EventLogTags; import java.io.PrintWriter; @@ -92,12 +91,12 @@ public final class NotificationRecord { private int mAuthoritativeRank; private String mGlobalSortKey; private int mPackageVisibility; - private int mTopicImportance = IMPORTANCE_UNSPECIFIED; + private int mUserImportance = IMPORTANCE_UNSPECIFIED; private int mImportance = IMPORTANCE_UNSPECIFIED; private CharSequence mImportanceExplanation = null; private int mSuppressedVisualEffects = 0; - private String mTopicExplanation; + private String mUserExplanation; private String mPeopleExplanation; @VisibleForTesting @@ -183,7 +182,7 @@ public final class NotificationRecord { mRankingTimeMs = calculateRankingTimeMs(previous.getRankingTimeMs()); mCreationTimeMs = previous.mCreationTimeMs; mVisibleSinceMs = previous.mVisibleSinceMs; - mTopicImportance = previous.mTopicImportance; + mUserImportance = previous.mUserImportance; mImportance = previous.mImportance; mImportanceExplanation = previous.mImportanceExplanation; // Don't copy mGlobalSortKey, recompute it. @@ -275,8 +274,8 @@ public final class NotificationRecord { pw.println(prefix + " mRecentlyIntrusive=" + mRecentlyIntrusive); pw.println(prefix + " mPackagePriority=" + mPackagePriority); pw.println(prefix + " mPackageVisibility=" + mPackageVisibility); - pw.println(prefix + " mTopicImportance=" - + NotificationListenerService.Ranking.importanceToString(mTopicImportance)); + pw.println(prefix + " mUserImportance=" + + NotificationListenerService.Ranking.importanceToString(mUserImportance)); pw.println(prefix + " mImportance=" + NotificationListenerService.Ranking.importanceToString(mImportance)); pw.println(prefix + " mImportanceExplanation=" + mImportanceExplanation); @@ -357,17 +356,17 @@ public final class NotificationRecord { return mPackageVisibility; } - public void setTopicImportance(int importance) { - mTopicImportance = importance; - applyTopicImportance(); + public void setUserImportance(int importance) { + mUserImportance = importance; + applyUserImportance(); } - private String getTopicExplanation() { - if (mTopicExplanation == null) { - mTopicExplanation = - mContext.getString(com.android.internal.R.string.importance_from_topic); + private String getUserExplanation() { + if (mUserExplanation == null) { + mUserExplanation = + mContext.getString(com.android.internal.R.string.importance_from_user); } - return mTopicExplanation; + return mUserExplanation; } private String getPeopleExplanation() { @@ -378,15 +377,15 @@ public final class NotificationRecord { return mPeopleExplanation; } - private void applyTopicImportance() { - if (mTopicImportance != NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED) { - mImportance = mTopicImportance; - mImportanceExplanation = getTopicExplanation(); + private void applyUserImportance() { + if (mUserImportance != NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED) { + mImportance = mUserImportance; + mImportanceExplanation = getUserExplanation(); } } - public int getTopicImportance() { - return mTopicImportance; + public int getUserImportance() { + return mUserImportance; } public void setImportance(int importance, CharSequence explanation) { @@ -394,7 +393,7 @@ public final class NotificationRecord { mImportance = importance; mImportanceExplanation = explanation; } - applyTopicImportance(); + applyUserImportance(); } public int getImportance() { @@ -529,6 +528,6 @@ public final class NotificationRecord { } public boolean isImportanceFromUser() { - return mImportance == mTopicImportance; + return mImportance == mUserImportance; } } diff --git a/services/core/java/com/android/server/notification/TopicPriorityExtractor.java b/services/core/java/com/android/server/notification/PriorityExtractor.java index 1df5c2b5fb2a..6c764761d738 100644 --- a/services/core/java/com/android/server/notification/TopicPriorityExtractor.java +++ b/services/core/java/com/android/server/notification/PriorityExtractor.java @@ -21,7 +21,7 @@ import android.util.Slog; /** * Determines if the given notification can bypass Do Not Disturb. */ -public class TopicPriorityExtractor implements NotificationSignalExtractor { +public class PriorityExtractor implements NotificationSignalExtractor { private static final String TAG = "ImportantTopicExtractor"; private static final boolean DBG = false; @@ -42,9 +42,8 @@ public class TopicPriorityExtractor implements NotificationSignalExtractor { return null; } - final int packagePriority = mConfig.getPriority(record.sbn.getPackageName(), - record.sbn.getUid(), record.sbn.getNotification().getTopic()); - record.setPackagePriority(packagePriority); + record.setPackagePriority( + mConfig.getPriority(record.sbn.getPackageName(), record.sbn.getUid())); return null; } diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java index 9773474c2273..b5cc2efcabc2 100644 --- a/services/core/java/com/android/server/notification/RankingConfig.java +++ b/services/core/java/com/android/server/notification/RankingConfig.java @@ -15,30 +15,17 @@ */ package com.android.server.notification; -import android.app.Notification; - -import java.util.List; - public interface RankingConfig { - List<Notification.Topic> getTopics(String packageName, int uid); - - int getPriority(String packageName, int uid, Notification.Topic topic); - - void setPriority(String packageName, int uid, Notification.Topic topic, int priority); - - int getVisibilityOverride(String packageName, int uid, Notification.Topic topic); - - void setVisibilityOverride(String packageName, int uid, Notification.Topic topic, - int visibility); + int getPriority(String packageName, int uid); - void setImportance(String packageName, int uid, Notification.Topic topic, int importance); + void setPriority(String packageName, int uid, int priority); - int getImportance(String packageName, int uid, Notification.Topic topic); + int getVisibilityOverride(String packageName, int uid); - boolean doesUserUseTopics(String packageName, int uid); + void setVisibilityOverride(String packageName, int uid, int visibility); - boolean hasBannedTopics(String packageName, int uid); + void setImportance(String packageName, int uid, int importance); - int getImportance(String packageName, int uid, String topicId); + int getImportance(String packageName, int uid); } diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index 91eab10e1258..fd96a784122f 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -20,14 +20,11 @@ import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.os.UserHandle; -import android.service.notification.NotificationListenerService; import android.service.notification.NotificationListenerService.Ranking; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Slog; -import com.android.internal.R; - import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -36,8 +33,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; -import java.util.List; -import java.util.Map; public class RankingHelper implements RankingConfig { private static final String TAG = "RankingHelper"; @@ -47,7 +42,6 @@ public class RankingHelper implements RankingConfig { private static final String TAG_RANKING = "ranking"; private static final String TAG_PACKAGE = "package"; private static final String ATT_VERSION = "version"; - private static final String TAG_TOPIC = "topic"; private static final String ATT_NAME = "name"; private static final String ATT_UID = "uid"; @@ -141,8 +135,6 @@ public class RankingHelper implements RankingConfig { if (type == XmlPullParser.START_TAG) { if (TAG_PACKAGE.equals(tag)) { int uid = safeInt(parser, ATT_UID, Record.UNKNOWN_UID); - int priority = safeInt(parser, ATT_PRIORITY, DEFAULT_PRIORITY); - int vis = safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY); String name = parser.getAttributeValue(null, ATT_NAME); if (!TextUtils.isEmpty(name)) { @@ -165,16 +157,8 @@ public class RankingHelper implements RankingConfig { r = getOrCreateRecord(name, uid); } r.importance = safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE); - r.priority = priority; - r.visibility = vis; - - // Migrate package level settings to the default topic. - // Might be overwritten by parseTopics. - Topic defaultTopic = r.topics.get(Notification.TOPIC_DEFAULT); - defaultTopic.priority = priority; - defaultTopic.visibility = vis; - - parseTopics(r, parser); + r.priority = safeInt(parser, ATT_PRIORITY, DEFAULT_PRIORITY); + r.visibility = safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY); } } } @@ -182,42 +166,6 @@ public class RankingHelper implements RankingConfig { throw new IllegalStateException("Failed to reach END_DOCUMENT"); } - public void parseTopics(Record r, XmlPullParser parser) - throws XmlPullParserException, IOException { - final int innerDepth = parser.getDepth(); - int type; - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) { - if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { - continue; - } - - String tagName = parser.getName(); - if (TAG_TOPIC.equals(tagName)) { - int priority = safeInt(parser, ATT_PRIORITY, DEFAULT_PRIORITY); - int vis = safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY); - int importance = safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE); - String id = parser.getAttributeValue(null, ATT_TOPIC_ID); - CharSequence label = parser.getAttributeValue(null, ATT_TOPIC_LABEL); - - if (!TextUtils.isEmpty(id)) { - Topic topic = new Topic(new Notification.Topic(id, label)); - - if (priority != DEFAULT_PRIORITY) { - topic.priority = priority; - } - if (vis != DEFAULT_VISIBILITY) { - topic.visibility = vis; - } - if (importance != DEFAULT_IMPORTANCE) { - topic.importance = importance; - } - r.topics.put(id, topic); - } - } - } - } - private static String recordKey(String pkg, int uid) { return pkg + "|" + uid; } @@ -229,7 +177,6 @@ public class RankingHelper implements RankingConfig { r = new Record(); r.pkg = pkg; r.uid = uid; - r.topics.put(Notification.TOPIC_DEFAULT, new Topic(createDefaultTopic())); mRecords.put(key, r); } return r; @@ -246,44 +193,29 @@ public class RankingHelper implements RankingConfig { if (forBackup && UserHandle.getUserId(r.uid) != UserHandle.USER_SYSTEM) { continue; } - out.startTag(null, TAG_PACKAGE); - out.attribute(null, ATT_NAME, r.pkg); - if (r.importance != DEFAULT_IMPORTANCE) { - out.attribute(null, ATT_IMPORTANCE, Integer.toString(r.importance)); - } - if (r.priority != DEFAULT_PRIORITY) { - out.attribute(null, ATT_PRIORITY, Integer.toString(r.priority)); - } - if (r.visibility != DEFAULT_VISIBILITY) { - out.attribute(null, ATT_VISIBILITY, Integer.toString(r.visibility)); - } - - if (!forBackup) { - out.attribute(null, ATT_UID, Integer.toString(r.uid)); - } + final boolean hasNonDefaultSettings = r.importance != DEFAULT_IMPORTANCE + || r.priority != DEFAULT_PRIORITY || r.visibility != DEFAULT_VISIBILITY; + if (hasNonDefaultSettings) { + out.startTag(null, TAG_PACKAGE); + out.attribute(null, ATT_NAME, r.pkg); + if (r.importance != DEFAULT_IMPORTANCE) { + out.attribute(null, ATT_IMPORTANCE, Integer.toString(r.importance)); + } + if (r.priority != DEFAULT_PRIORITY) { + out.attribute(null, ATT_PRIORITY, Integer.toString(r.priority)); + } + if (r.visibility != DEFAULT_VISIBILITY) { + out.attribute(null, ATT_VISIBILITY, Integer.toString(r.visibility)); + } - writeTopicsXml(out, r); - out.endTag(null, TAG_PACKAGE); - } - out.endTag(null, TAG_RANKING); - } + if (!forBackup) { + out.attribute(null, ATT_UID, Integer.toString(r.uid)); + } - public void writeTopicsXml(XmlSerializer out, Record r) throws IOException { - for (Topic t : r.topics.values()) { - out.startTag(null, TAG_TOPIC); - out.attribute(null, ATT_TOPIC_ID, t.topic.getId()); - out.attribute(null, ATT_TOPIC_LABEL, t.topic.getLabel().toString()); - if (t.priority != DEFAULT_PRIORITY) { - out.attribute(null, ATT_PRIORITY, Integer.toString(t.priority)); - } - if (t.visibility != DEFAULT_VISIBILITY) { - out.attribute(null, ATT_VISIBILITY, Integer.toString(t.visibility)); + out.endTag(null, TAG_PACKAGE); } - if (t.importance != DEFAULT_IMPORTANCE) { - out.attribute(null, ATT_IMPORTANCE, Integer.toString(t.importance)); - } - out.endTag(null, TAG_TOPIC); } + out.endTag(null, TAG_RANKING); } private void updateConfig() { @@ -370,189 +302,62 @@ public class RankingHelper implements RankingConfig { } } - private static boolean safeBool(XmlPullParser parser, String att, boolean defValue) { - final String val = parser.getAttributeValue(null, att); - return tryParseBool(val, defValue); - } - private static boolean tryParseBool(String value, boolean defValue) { if (TextUtils.isEmpty(value)) return defValue; return Boolean.valueOf(value); } - @Override - public List<Notification.Topic> getTopics(String packageName, int uid) { - final Record r = getOrCreateRecord(packageName, uid); - List<Notification.Topic> topics = new ArrayList<>(); - for (Topic t : r.topics.values()) { - topics.add(t.topic); - } - return topics; - } - - @Override - public boolean hasBannedTopics(String packageName, int uid) { - final Record r = getOrCreateRecord(packageName, uid); - for (Topic t : r.topics.values()) { - if (t.importance == Ranking.IMPORTANCE_NONE) { - return true; - } - } - return false; - } - /** - * Gets priority. If a topic is given, returns the priority of that topic. Otherwise, the - * priority of the app. + * Gets priority. */ @Override - public int getPriority(String packageName, int uid, Notification.Topic topic) { - final Record r = getOrCreateRecord(packageName, uid); - if (topic == null) { - return r.priority; - } - return getOrCreateTopic(r, topic).priority; + public int getPriority(String packageName, int uid) { + return getOrCreateRecord(packageName, uid).priority; } /** - * Sets priority. If a topic is given, sets the priority of that topic. If not, - * sets the default priority for all new topics that appear in the future, and resets - * the priority of all current topics. + * Sets priority. */ @Override - public void setPriority(String packageName, int uid, Notification.Topic topic, - int priority) { - final Record r = getOrCreateRecord(packageName, uid); - if (topic == null) { - r.priority = priority; - for (Topic t : r.topics.values()) { - t.priority = priority; - } - } else { - getOrCreateTopic(r, topic).priority = priority; - } + public void setPriority(String packageName, int uid, int priority) { + getOrCreateRecord(packageName, uid).priority = priority; updateConfig(); } /** - * Gets visual override. If a topic is given, returns the override of that topic. Otherwise, the - * override of the app. + * Gets visual override. */ @Override - public int getVisibilityOverride(String packageName, int uid, Notification.Topic topic) { - final Record r = getOrCreateRecord(packageName, uid); - if (topic == null) { - return r.visibility; - } - return getOrCreateTopic(r, topic).visibility; + public int getVisibilityOverride(String packageName, int uid) { + return getOrCreateRecord(packageName, uid).visibility; } /** - * Sets visibility override. If a topic is given, sets the override of that topic. If not, - * sets the default override for all new topics that appear in the future, and resets - * the override of all current topics. + * Sets visibility override. */ @Override - public void setVisibilityOverride(String pkgName, int uid, Notification.Topic topic, - int visibility) { - final Record r = getOrCreateRecord(pkgName, uid); - if (topic == null) { - r.visibility = visibility; - for (Topic t : r.topics.values()) { - t.visibility = visibility; - } - } else { - getOrCreateTopic(r, topic).visibility = visibility; - } + public void setVisibilityOverride(String pkgName, int uid, int visibility) { + getOrCreateRecord(pkgName, uid).visibility = visibility; updateConfig(); } /** - * Gets the importance of a topic. Unlike {@link #getImportance(String, int, String)}, does not - * create package or topic records if they don't exist. - */ - @Override - public int getImportance(String packageName, int uid, String topicId) { - final String key = recordKey(packageName, uid); - Record r = mRecords.get(key); - if (r == null) { - return Ranking.IMPORTANCE_UNSPECIFIED; - } - Topic t = r.topics.get(topicId); - if (t == null) { - return Ranking.IMPORTANCE_UNSPECIFIED; - } - return t.importance; - } - - /** - * Gets importance. If a topic is given, returns the importance of that topic. Otherwise, the - * importance of the app. + * Gets importance. */ @Override - public int getImportance(String packageName, int uid, Notification.Topic topic) { - final Record r = getOrCreateRecord(packageName, uid); - if (topic == null) { - return r.importance; - } - return getOrCreateTopic(r, topic).importance; + public int getImportance(String packageName, int uid) { + return getOrCreateRecord(packageName, uid).importance; } /** - * Sets importance. If a topic is given, sets the importance of that topic. If not, sets the - * default importance for all new topics that appear in the future, and resets - * the importance of all current topics (unless the app is being blocked). + * Sets importance. */ @Override - public void setImportance(String pkgName, int uid, Notification.Topic topic, - int importance) { - final Record r = getOrCreateRecord(pkgName, uid); - if (topic == null) { - r.importance = importance; - if (Ranking.IMPORTANCE_NONE != importance) { - for (Topic t : r.topics.values()) { - t.importance = importance; - } - } - } else { - getOrCreateTopic(r, topic).importance = importance; - } + public void setImportance(String pkgName, int uid, int importance) { + getOrCreateRecord(pkgName, uid).importance = importance; updateConfig(); } - @Override - public boolean doesUserUseTopics(String pkgName, int uid) { - final Record r = getOrCreateRecord(pkgName, uid); - for (Topic topic : r.topics.values()) { - if (topic.importance != Ranking.IMPORTANCE_UNSPECIFIED - && r.importance != topic.importance) - return true; - } - return false; - } - - private Topic getOrCreateTopic(Record r, Notification.Topic topic) { - if (topic == null) { - topic = createDefaultTopic(); - } - Topic t = r.topics.get(topic.getId()); - if (t != null) { - return t; - } else { - t = new Topic(topic); - t.importance = r.importance; - t.priority = r.priority; - t.visibility = r.visibility; - r.topics.put(topic.getId(), t); - return t; - } - } - - private Notification.Topic createDefaultTopic() { - return new Notification.Topic(Notification.TOPIC_DEFAULT, - mContext.getString(R.string.default_notification_topic_label)); - } - public void dump(PrintWriter pw, String prefix, NotificationManagerService.DumpFilter filter) { if (filter == null) { final int N = mSignalExtractors.length; @@ -600,25 +405,6 @@ public class RankingHelper implements RankingConfig { pw.print(Ranking.importanceToString(r.visibility)); } pw.println(); - for (Topic t : r.topics.values()) { - pw.print(prefix); - pw.print(" "); - pw.print(" "); - pw.print(t.topic.getId()); - if (t.priority != DEFAULT_PRIORITY) { - pw.print(" priority="); - pw.print(Notification.priorityToString(t.priority)); - } - if (t.visibility != DEFAULT_VISIBILITY) { - pw.print(" visibility="); - pw.print(Notification.visibilityToString(t.visibility)); - } - if (t.importance != DEFAULT_IMPORTANCE) { - pw.print(" importance="); - pw.print(Ranking.importanceToString(t.importance)); - } - pw.println(); - } } } } @@ -657,17 +443,5 @@ public class RankingHelper implements RankingConfig { int importance = DEFAULT_IMPORTANCE; int priority = DEFAULT_PRIORITY; int visibility = DEFAULT_VISIBILITY; - Map<String, Topic> topics = new ArrayMap<>(); } - - private static class Topic { - Notification.Topic topic; - int priority = DEFAULT_PRIORITY; - int visibility = DEFAULT_VISIBILITY; - int importance = DEFAULT_IMPORTANCE; - - public Topic(Notification.Topic topic) { - this.topic = topic; - } - } } diff --git a/services/core/java/com/android/server/notification/TopicVisibilityExtractor.java b/services/core/java/com/android/server/notification/VisibilityExtractor.java index eaa3ed3623e1..2da2b2f3c264 100644 --- a/services/core/java/com/android/server/notification/TopicVisibilityExtractor.java +++ b/services/core/java/com/android/server/notification/VisibilityExtractor.java @@ -21,8 +21,8 @@ import android.util.Slog; /** * Determines if the given notification can display sensitive content on the lockscreen. */ -public class TopicVisibilityExtractor implements NotificationSignalExtractor { - private static final String TAG = "TopicVisibilityExtractor"; +public class VisibilityExtractor implements NotificationSignalExtractor { + private static final String TAG = "VisibilityExtractor"; private static final boolean DBG = false; private RankingConfig mConfig; @@ -42,10 +42,8 @@ public class TopicVisibilityExtractor implements NotificationSignalExtractor { return null; } - final int packageVisibility = mConfig.getVisibilityOverride( - record.sbn.getPackageName(), record.sbn.getUid(), - record.sbn.getNotification().getTopic()); - record.setPackageVisibilityOverride(packageVisibility); + record.setPackageVisibilityOverride( + mConfig.getVisibilityOverride(record.sbn.getPackageName(), record.sbn.getUid())); return null; } diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index e7465c08832e..d5ed04a94f37 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -41,6 +41,7 @@ import android.os.Debug; import android.os.Environment; import android.os.FileUtils; import android.os.Handler; +import android.os.IBinder; import android.os.IUserManager; import android.os.Message; import android.os.ParcelFileDescriptor; @@ -188,6 +189,8 @@ public class UserManagerService extends IUserManager.Stub { private final File mUsersDir; private final File mUserListFile; + private static final IBinder mUserRestriconToken = new Binder(); + /** * User-related information that is used for persisting to flash. Only UserInfo is * directly exposed to other system apps. @@ -1016,7 +1019,7 @@ public class UserManagerService extends IUserManager.Stub { if (mAppOpsService != null) { // We skip it until system-ready. final long token = Binder.clearCallingIdentity(); try { - mAppOpsService.setUserRestrictions(effective, userId); + mAppOpsService.setUserRestrictions(effective, mUserRestriconToken, userId); } catch (RemoteException e) { Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions"); } finally { diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index e88b72f7366d..716b96fb4791 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -33,6 +33,7 @@ import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT; import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED; import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN; +import android.Manifest; import android.app.ActivityManager; import android.app.ActivityManager.StackId; import android.app.ActivityManagerInternal; @@ -2035,7 +2036,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; } if (permission != null) { - if (permission == android.Manifest.permission.SYSTEM_ALERT_WINDOW) { + if (android.Manifest.permission.SYSTEM_ALERT_WINDOW.equals(permission)) { final int callingUid = Binder.getCallingUid(); // system processes will be automatically allowed privilege to draw if (callingUid == Process.SYSTEM_UID) { @@ -6075,9 +6076,20 @@ public class PhoneWindowManager implements WindowManagerPolicy { public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight, Rect outInsets) { outInsets.setEmpty(); + + // Navigation bar and status bar. + getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets); if (mStatusBar != null) { outInsets.top = mStatusBarHeight; } + } + + @Override + public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight, + Rect outInsets) { + outInsets.setEmpty(); + + // Only navigation bar if (mNavigationBar != null) { if (isNavigationBarOnBottom(displayWidth, displayHeight)) { outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode); diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index a1f24f772c3c..dbaa598fb1b2 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -49,6 +49,7 @@ import android.os.Trace; import android.os.UserHandle; import android.os.WorkSource; import android.provider.Settings; +import android.provider.Settings.Secure; import android.service.dreams.DreamManagerInternal; import android.util.EventLog; import android.util.Slog; @@ -468,6 +469,9 @@ public final class PowerManagerService extends SystemService private final ArrayList<PowerManagerInternal.LowPowerModeListener> mLowPowerModeListeners = new ArrayList<PowerManagerInternal.LowPowerModeListener>(); + // True if brightness should be affected by twilight. + private boolean mBrightnessUseTwilight; + private native void nativeInit(); private static native void nativeAcquireSuspendBlocker(String name); @@ -620,6 +624,9 @@ public final class PowerManagerService extends SystemService resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.DOUBLE_TAP_TO_WAKE), false, mSettingsObserver, UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.Secure.getUriFor( + Secure.BRIGHTNESS_USE_TWILIGHT), + false, mSettingsObserver, UserHandle.USER_ALL); // Go. readConfigurationLocked(); updateSettingsLocked(); @@ -726,6 +733,9 @@ public final class PowerManagerService extends SystemService Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT); + mBrightnessUseTwilight = Settings.Secure.getIntForUser(resolver, + Secure.BRIGHTNESS_USE_TWILIGHT, 0, UserHandle.USER_CURRENT) != 0; + final boolean lowPowerModeEnabled = Settings.Global.getInt(resolver, Settings.Global.LOW_POWER_MODE, 0) != 0; final boolean autoLowPowerModeConfigured = Settings.Global.getInt(resolver, @@ -1997,6 +2007,7 @@ public final class PowerManagerService extends SystemService mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked(); mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled; mDisplayPowerRequest.boostScreenBrightness = mScreenBrightnessBoostInProgress; + mDisplayPowerRequest.useTwilight = mBrightnessUseTwilight; if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) { mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager; diff --git a/services/core/java/com/android/server/twilight/TwilightManager.java b/services/core/java/com/android/server/twilight/TwilightManager.java index b3de58b279af..56137a406757 100644 --- a/services/core/java/com/android/server/twilight/TwilightManager.java +++ b/services/core/java/com/android/server/twilight/TwilightManager.java @@ -20,5 +20,6 @@ import android.os.Handler; public interface TwilightManager { void registerListener(TwilightListener listener, Handler handler); + void unregisterListener(TwilightListener listener); TwilightState getCurrentState(); } diff --git a/services/core/java/com/android/server/twilight/TwilightService.java b/services/core/java/com/android/server/twilight/TwilightService.java index a71961c8fe9b..ac1ab64a1e81 100644 --- a/services/core/java/com/android/server/twilight/TwilightService.java +++ b/services/core/java/com/android/server/twilight/TwilightService.java @@ -19,12 +19,15 @@ package com.android.server.twilight; import com.android.server.SystemService; import com.android.server.TwilightCalculator; +import android.app.ActivityManager; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.database.ContentObserver; import android.location.Criteria; import android.location.Location; import android.location.LocationListener; @@ -33,6 +36,9 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.SystemClock; +import android.os.UserHandle; +import android.provider.Settings; +import android.provider.Settings.Secure; import android.text.format.DateUtils; import android.text.format.Time; import android.util.Slog; @@ -54,6 +60,26 @@ public final class TwilightService extends SystemService { static final String ACTION_UPDATE_TWILIGHT_STATE = "com.android.server.action.UPDATE_TWILIGHT_STATE"; + // The amount of time after or before sunrise over which to start adjusting + // twilight affected things. We want the change to happen gradually so that + // it is below the threshold of perceptibility and so that the adjustment has + // maximum effect well after dusk. + private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils.HOUR_IN_MILLIS * 2; + + // Broadcast when twilight changes. + public static final String ACTION_TWILIGHT_CHANGED = "android.intent.action.TWILIGHT_CHANGED"; + + public static final String EXTRA_IS_NIGHT = "isNight"; + public static final String EXTRA_AMOUNT = "amount"; + + // Amount of time the TwilightService will stay locked in an override state before switching + // back to auto. + private static final long RESET_TIME = DateUtils.HOUR_IN_MILLIS * 2; + private static final String EXTRA_RESET_USER = "user"; + + private static final String ACTION_RESET_TWILIGHT_AUTO = + "com.android.server.action.RESET_TWILIGHT_AUTO"; + final Object mLock = new Object(); AlarmManager mAlarmManager; @@ -65,6 +91,10 @@ public final class TwilightService extends SystemService { TwilightState mTwilightState; + private int mCurrentUser; + private boolean mLocked; + private boolean mBootCompleted; + public TwilightService(Context context) { super(context); } @@ -75,14 +105,93 @@ public final class TwilightService extends SystemService { mLocationManager = (LocationManager) getContext().getSystemService( Context.LOCATION_SERVICE); mLocationHandler = new LocationHandler(); + mCurrentUser = ActivityManager.getCurrentUser(); IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED); filter.addAction(Intent.ACTION_TIME_CHANGED); filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); + filter.addAction(Intent.ACTION_USER_SWITCHED); filter.addAction(ACTION_UPDATE_TWILIGHT_STATE); - getContext().registerReceiver(mUpdateLocationReceiver, filter); + getContext().registerReceiver(mReceiver, filter); publishLocalService(TwilightManager.class, mService); + getContext().getContentResolver().registerContentObserver( + Secure.getUriFor(Secure.TWILIGHT_MODE), false, mContentObserver, mCurrentUser); + mContentObserver.onChange(true); + } + + @Override + public void onBootPhase(int phase) { + if (phase == PHASE_BOOT_COMPLETED) { + mBootCompleted = true; + sendBroadcast(); + } + } + + private void reregisterSettingObserver() { + final ContentResolver contentResolver = getContext().getContentResolver(); + contentResolver.unregisterContentObserver(mContentObserver); + contentResolver.registerContentObserver(Secure.getUriFor(Secure.TWILIGHT_MODE), false, + mContentObserver, mCurrentUser); + mContentObserver.onChange(true); + } + + private void setLockedState(TwilightState state) { + synchronized (mLock) { + // Make sure we aren't locked so we can set the state. + mLocked = false; + setTwilightState(state); + // Make sure we leave the state locked, so it cant be changed. + mLocked = true; + // TODO: Don't bother updating state when locked. + } + } + + private void setTwilightState(TwilightState state) { + synchronized (mLock) { + if (mLocked) { + // State has been locked by secure setting, shouldn't be changed. + return; + } + if (!Objects.equal(mTwilightState, state)) { + if (DEBUG) { + Slog.d(TAG, "Twilight state changed: " + state); + } + + mTwilightState = state; + + final int listenerLen = mListeners.size(); + for (int i = 0; i < listenerLen; i++) { + mListeners.get(i).postUpdate(); + } + } + } + sendBroadcast(); + } + + private void sendBroadcast() { + synchronized (mLock) { + if (mTwilightState == null) { + return; + } + if (mBootCompleted) { + Intent intent = new Intent(ACTION_TWILIGHT_CHANGED); + intent.putExtra(EXTRA_IS_NIGHT, mTwilightState.isNight()); + intent.putExtra(EXTRA_AMOUNT, mTwilightState.getAmount()); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL); + } + } + } + + private void scheduleReset() { + long resetTime = System.currentTimeMillis() + RESET_TIME; + Intent resetIntent = new Intent(ACTION_RESET_TWILIGHT_AUTO); + resetIntent.putExtra(EXTRA_RESET_USER, mCurrentUser); + PendingIntent pendingIntent = PendingIntent.getBroadcast( + getContext(), 0, resetIntent, 0); + mAlarmManager.cancel(pendingIntent); + mAlarmManager.setExact(AlarmManager.RTC, resetTime, pendingIntent); } private static class TwilightListenerRecord implements Runnable { @@ -133,24 +242,22 @@ public final class TwilightService extends SystemService { } } } - }; - private void setTwilightState(TwilightState state) { - synchronized (mLock) { - if (!Objects.equal(mTwilightState, state)) { - if (DEBUG) { - Slog.d(TAG, "Twilight state changed: " + state); + @Override + public void unregisterListener(TwilightListener listener) { + synchronized (mLock) { + for (int i = 0; i < mListeners.size(); i++) { + if (mListeners.get(i).mListener == listener) { + mListeners.remove(i); + } } - mTwilightState = state; - - final int listenerLen = mListeners.size(); - for (int i = 0; i < listenerLen; i++) { - mListeners.get(i).postUpdate(); + if (mListeners.size() == 0) { + mLocationHandler.disableLocationUpdates(); } } } - } + }; // The user has moved if the accuracy circles of the two locations don't overlap. private static boolean hasMoved(Location from, Location to) { @@ -183,6 +290,7 @@ public final class TwilightService extends SystemService { private static final int MSG_GET_NEW_LOCATION_UPDATE = 2; private static final int MSG_PROCESS_NEW_LOCATION = 3; private static final int MSG_DO_TWILIGHT_UPDATE = 4; + private static final int MSG_DISABLE_LOCATION_UPDATES = 5; private static final long LOCATION_UPDATE_MS = 24 * DateUtils.HOUR_IN_MILLIS; private static final long MIN_LOCATION_UPDATE_MS = 30 * DateUtils.MINUTE_IN_MILLIS; @@ -210,6 +318,10 @@ public final class TwilightService extends SystemService { sendEmptyMessage(MSG_ENABLE_LOCATION_UPDATES); } + public void disableLocationUpdates() { + sendEmptyMessage(MSG_DISABLE_LOCATION_UPDATES); + } + public void requestLocationUpdate() { sendEmptyMessage(MSG_GET_NEW_LOCATION_UPDATE); } @@ -311,6 +423,11 @@ public final class TwilightService extends SystemService { } break; + case MSG_DISABLE_LOCATION_UPDATES: + mLocationManager.removeUpdates(mLocationListener); + removeMessages(MSG_ENABLE_LOCATION_UPDATES); + break; + case MSG_DO_TWILIGHT_UPDATE: updateTwilightState(); break; @@ -368,11 +485,6 @@ public final class TwilightService extends SystemService { final long now = System.currentTimeMillis(); - // calculate yesterday's twilight - mTwilightCalculator.calculateTwilight(now - DateUtils.DAY_IN_MILLIS, - mLocation.getLatitude(), mLocation.getLongitude()); - final long yesterdaySunset = mTwilightCalculator.mSunset; - // calculate today's twilight mTwilightCalculator.calculateTwilight(now, mLocation.getLatitude(), mLocation.getLongitude()); @@ -385,9 +497,19 @@ public final class TwilightService extends SystemService { mLocation.getLatitude(), mLocation.getLongitude()); final long tomorrowSunrise = mTwilightCalculator.mSunrise; + float amount = 0; + if (isNight) { + if (todaySunrise == -1 || todaySunset == -1) { + amount = 1; + } else if (now > todaySunset) { + amount = Math.min(1, (now - todaySunset) / (float) TWILIGHT_ADJUSTMENT_TIME); + } else { + amount = Math.max(0, 1 + - (todaySunrise - now) / (float) TWILIGHT_ADJUSTMENT_TIME); + } + } // set twilight state - TwilightState state = new TwilightState(isNight, yesterdaySunset, - todaySunrise, todaySunset, tomorrowSunrise); + TwilightState state = new TwilightState(isNight, amount); if (DEBUG) { Slog.d(TAG, "Updating twilight state: " + state); } @@ -402,12 +524,18 @@ public final class TwilightService extends SystemService { // add some extra time to be on the safe side. nextUpdate += DateUtils.MINUTE_IN_MILLIS; - if (now > todaySunset) { - nextUpdate += tomorrowSunrise; - } else if (now > todaySunrise) { - nextUpdate += todaySunset; + if (amount == 1 || amount == 0) { + if (now > todaySunset) { + nextUpdate += tomorrowSunrise; + } else if (now > todaySunrise) { + nextUpdate += todaySunset; + } else { + nextUpdate += todaySunrise; + } } else { - nextUpdate += todaySunrise; + // This is the update rate while transitioning. + // Leave at 10 min for now (one from above). + nextUpdate += 9 * DateUtils.MINUTE_IN_MILLIS; } } @@ -423,9 +551,37 @@ public final class TwilightService extends SystemService { } } - private final BroadcastReceiver mUpdateLocationReceiver = new BroadcastReceiver() { + private final ContentObserver mContentObserver = new ContentObserver(new Handler()) { + @Override + public void onChange(boolean selfChange) { + super.onChange(selfChange); + int value = Secure.getIntForUser(getContext().getContentResolver(), + Secure.TWILIGHT_MODE, Secure.TWILIGHT_MODE_LOCKED_OFF, mCurrentUser); + if (value == Secure.TWILIGHT_MODE_LOCKED_OFF) { + setLockedState(new TwilightState(false, 0)); + } else if (value == Secure.TWILIGHT_MODE_LOCKED_ON) { + setLockedState(new TwilightState(true, 1)); + } else if (value == Secure.TWILIGHT_MODE_AUTO_OVERRIDE_OFF) { + setLockedState(new TwilightState(false, 0)); + scheduleReset(); + } else if (value == Secure.TWILIGHT_MODE_AUTO_OVERRIDE_ON) { + setLockedState(new TwilightState(true, 1)); + scheduleReset(); + } else { + mLocked = false; + mLocationHandler.requestTwilightUpdate(); + } + } + }; + + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { + if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) { + mCurrentUser = ActivityManager.getCurrentUser(); + reregisterSettingObserver(); + return; + } if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(intent.getAction()) && !intent.getBooleanExtra("state", false)) { // Airplane mode is now off! @@ -433,6 +589,12 @@ public final class TwilightService extends SystemService { return; } + if (ACTION_RESET_TWILIGHT_AUTO.equals(intent.getAction())) { + int user = intent.getIntExtra(EXTRA_RESET_USER, 0); + Settings.Secure.putIntForUser(getContext().getContentResolver(), + Secure.TWILIGHT_MODE, Secure.TWILIGHT_MODE_AUTO, user); + return; + } // Time zone has changed or alarm expired. mLocationHandler.requestTwilightUpdate(); } diff --git a/services/core/java/com/android/server/twilight/TwilightState.java b/services/core/java/com/android/server/twilight/TwilightState.java index 91e24d7d55bf..81abc132011a 100644 --- a/services/core/java/com/android/server/twilight/TwilightState.java +++ b/services/core/java/com/android/server/twilight/TwilightState.java @@ -25,20 +25,11 @@ import java.util.Date; */ public class TwilightState { private final boolean mIsNight; - private final long mYesterdaySunset; - private final long mTodaySunrise; - private final long mTodaySunset; - private final long mTomorrowSunrise; + private final float mAmount; - TwilightState(boolean isNight, - long yesterdaySunset, - long todaySunrise, long todaySunset, - long tomorrowSunrise) { + TwilightState(boolean isNight, float amount) { mIsNight = isNight; - mYesterdaySunset = yesterdaySunset; - mTodaySunrise = todaySunrise; - mTodaySunset = todaySunset; - mTomorrowSunrise = tomorrowSunrise; + mAmount = amount; } /** @@ -49,35 +40,11 @@ public class TwilightState { } /** - * Returns the time of yesterday's sunset in the System.currentTimeMillis() timebase, - * or -1 if the sun never sets. + * For twilight affects that change gradually over time, this is the amount they + * should currently be in effect. */ - public long getYesterdaySunset() { - return mYesterdaySunset; - } - - /** - * Returns the time of today's sunrise in the System.currentTimeMillis() timebase, - * or -1 if the sun never rises. - */ - public long getTodaySunrise() { - return mTodaySunrise; - } - - /** - * Returns the time of today's sunset in the System.currentTimeMillis() timebase, - * or -1 if the sun never sets. - */ - public long getTodaySunset() { - return mTodaySunset; - } - - /** - * Returns the time of tomorrow's sunrise in the System.currentTimeMillis() timebase, - * or -1 if the sun never rises. - */ - public long getTomorrowSunrise() { - return mTomorrowSunrise; + public float getAmount() { + return mAmount; } @Override @@ -88,10 +55,7 @@ public class TwilightState { public boolean equals(TwilightState other) { return other != null && mIsNight == other.mIsNight - && mYesterdaySunset == other.mYesterdaySunset - && mTodaySunrise == other.mTodaySunrise - && mTodaySunset == other.mTodaySunset - && mTomorrowSunrise == other.mTomorrowSunrise; + && mAmount == other.mAmount; } @Override @@ -103,10 +67,7 @@ public class TwilightState { public String toString() { DateFormat f = DateFormat.getDateTimeInstance(); return "{TwilightState: isNight=" + mIsNight - + ", mYesterdaySunset=" + f.format(new Date(mYesterdaySunset)) - + ", mTodaySunrise=" + f.format(new Date(mTodaySunrise)) - + ", mTodaySunset=" + f.format(new Date(mTodaySunset)) - + ", mTomorrowSunrise=" + f.format(new Date(mTomorrowSunrise)) + + ", mAmount=" + mAmount + "}"; } } diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index a16c8d1b1fd4..7378bded4ce4 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -1072,6 +1072,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { } } + @Override public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb, final int which, Bundle outParams, int wallpaperUserId) { if (wallpaperUserId != UserHandle.getCallingUserId()) { @@ -1086,19 +1087,17 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { } synchronized (mLock) { - WallpaperData wallpaper = null; - if (which == FLAG_SET_LOCK) { - wallpaper = mLockWallpaperMap.get(wallpaperUserId); + final SparseArray<WallpaperData> whichSet = + (which == FLAG_SET_LOCK) ? mLockWallpaperMap : mWallpaperMap; + WallpaperData wallpaper = whichSet.get(wallpaperUserId); + if (wallpaper == null) { + // common case, this is the first lookup post-boot of the system or + // unified lock, so we bring up the saved state lazily now and recheck. + loadSettingsLocked(wallpaperUserId); + wallpaper = whichSet.get(wallpaperUserId); if (wallpaper == null) { - // If you ask for the lock wallpaper specifically and there isn't one, - // we say so rather than returning the system wallpaper as fallback. return null; } - } else { - wallpaper = mWallpaperMap.get(wallpaperUserId); - } - if (wallpaper == null) { - return null; } try { if (outParams != null) { diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index 182148758738..5cb709936bd1 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -46,13 +46,13 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.annotation.Nullable; import android.content.Context; -import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Rect; import android.os.Debug; import android.os.IBinder; import android.os.IRemoteCallback; import android.os.RemoteException; +import android.util.ArraySet; import android.util.Slog; import android.util.SparseArray; import android.view.AppTransitionAnimationSpec; @@ -63,8 +63,6 @@ import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.AnimationUtils; import android.view.animation.ClipRectAnimation; -import android.view.animation.ClipRectLRAnimation; -import android.view.animation.ClipRectTBAnimation; import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; import android.view.animation.ScaleAnimation; @@ -73,10 +71,11 @@ import android.view.animation.TranslateAnimation; import com.android.internal.util.DumpUtils.Dump; import com.android.server.AttributeCache; import com.android.server.wm.WindowManagerService.H; +import com.android.server.wm.animation.ClipRectLRAnimation; +import com.android.server.wm.animation.ClipRectTBAnimation; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.Arrays; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -135,6 +134,16 @@ public class AppTransition implements Dump { private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.5f; static final int DEFAULT_APP_TRANSITION_DURATION = 336; + + /** Interpolator to be used for animations that respond directly to a touch */ + static final Interpolator TOUCH_RESPONSE_INTERPOLATOR = + new PathInterpolator(0.3f, 0f, 0.1f, 1f); + + /** + * Maximum duration for the clip reveal animation. This is used when there is a lot of movement + * involved, to make it more understandable. + */ + private static final int MAX_CLIP_REVEAL_TRANSITION_DURATION = 420; private static final int THUMBNAIL_APP_TRANSITION_DURATION = 336; private static final int THUMBNAIL_APP_TRANSITION_ALPHA_DURATION = 336; private static final long APP_TRANSITION_TIMEOUT_MS = 5000; @@ -199,17 +208,17 @@ public class AppTransition implements Dump { private final Interpolator mFastOutLinearInInterpolator; private final Interpolator mClipHorizontalInterpolator = new PathInterpolator(0, 0, 0.4f, 1f); - /** Interpolator to be used for animations that respond directly to a touch */ - private final Interpolator mTouchResponseInterpolator = - new PathInterpolator(0.3f, 0f, 0.1f, 1f); - private final int mClipRevealTranslationY; private int mCurrentUserId = 0; + private long mLastClipRevealTransitionDuration = DEFAULT_APP_TRANSITION_DURATION; private final ArrayList<AppTransitionListener> mListeners = new ArrayList<>(); private final ExecutorService mDefaultExecutor = Executors.newSingleThreadExecutor(); + private int mLastClipRevealMaxTranslation; + private boolean mLastHadClipReveal; + AppTransition(Context context, WindowManagerService service) { mContext = context; mService = service; @@ -331,19 +340,25 @@ public class AppTransition implements Dump { if (!isRunning()) { mAppTransitionState = APP_STATE_IDLE; notifyAppTransitionPendingLocked(); + mLastHadClipReveal = false; + mLastClipRevealMaxTranslation = 0; + mLastClipRevealTransitionDuration = DEFAULT_APP_TRANSITION_DURATION; return true; } return false; } - void goodToGo(AppWindowAnimator openingAppAnimator, AppWindowAnimator closingAppAnimator) { + void goodToGo(AppWindowAnimator topOpeningAppAnimator, AppWindowAnimator topClosingAppAnimator, + ArraySet<AppWindowToken> openingApps, ArraySet<AppWindowToken> closingApps) { mNextAppTransition = TRANSIT_UNSET; mAppTransitionState = APP_STATE_RUNNING; notifyAppTransitionStartingLocked( - openingAppAnimator != null ? openingAppAnimator.mAppToken.token : null, - closingAppAnimator != null ? closingAppAnimator.mAppToken.token : null, - openingAppAnimator != null ? openingAppAnimator.animation : null, - closingAppAnimator != null ? closingAppAnimator.animation : null); + topOpeningAppAnimator != null ? topOpeningAppAnimator.mAppToken.token : null, + topClosingAppAnimator != null ? topClosingAppAnimator.mAppToken.token : null, + topOpeningAppAnimator != null ? topOpeningAppAnimator.animation : null, + topClosingAppAnimator != null ? topClosingAppAnimator.animation : null); + mService.getDefaultDisplayContentLocked().getDockedDividerController() + .notifyAppTransitionStarting(openingApps, closingApps); } void clear() { @@ -632,50 +647,118 @@ public class AppTransition implements Dump { bitmap, new Rect(left, top, left + width, top + height)); } - private Animation createClipRevealAnimationLocked(int transit, boolean enter, Rect appFrame) { + /** + * @return the duration of the last clip reveal animation + */ + long getLastClipRevealTransitionDuration() { + return mLastClipRevealTransitionDuration; + } + + /** + * @return the maximum distance the app surface is traveling of the last clip reveal animation + */ + int getLastClipRevealMaxTranslation() { + return mLastClipRevealMaxTranslation; + } + + /** + * @return true if in the last app transition had a clip reveal animation, false otherwise + */ + boolean hadClipRevealAnimation() { + return mLastHadClipReveal; + } + + /** + * Calculates the duration for the clip reveal animation. If the clip is "cut off", meaning that + * the start rect is outside of the target rect, and there is a lot of movement going on. + * + * @param cutOff whether the start rect was not fully contained by the end rect + * @param translationX the total translation the surface moves in x direction + * @param translationY the total translation the surfaces moves in y direction + * @param displayFrame our display frame + * + * @return the duration of the clip reveal animation, in milliseconds + */ + private long calculateClipRevealTransitionDuration(boolean cutOff, float translationX, + float translationY, Rect displayFrame) { + if (!cutOff) { + return DEFAULT_APP_TRANSITION_DURATION; + } + final float fraction = Math.max(Math.abs(translationX) / displayFrame.width(), + Math.abs(translationY) / displayFrame.height()); + return (long) (DEFAULT_APP_TRANSITION_DURATION + fraction * + (MAX_CLIP_REVEAL_TRANSITION_DURATION - DEFAULT_APP_TRANSITION_DURATION)); + } + + private Animation createClipRevealAnimationLocked(int transit, boolean enter, Rect appFrame, + Rect displayFrame) { final Animation anim; if (enter) { - // Reveal will expand and move faster in horizontal direction - final int appWidth = appFrame.width(); final int appHeight = appFrame.height(); + // mTmpRect will contain an area around the launcher icon that was pressed. We will // clip reveal from that area in the final area of the app. getDefaultNextAppTransitionStartRect(mTmpRect); float t = 0f; if (appHeight > 0) { - t = (float) mTmpRect.left / appHeight; + t = (float) mTmpRect.top / displayFrame.height(); } - int translationY = mClipRevealTranslationY + (int)(appHeight / 7f * t); - + int translationY = mClipRevealTranslationY + (int)(displayFrame.height() / 7f * t); + int translationX = 0; + int translationYCorrection = translationY; int centerX = mTmpRect.centerX(); int centerY = mTmpRect.centerY(); int halfWidth = mTmpRect.width() / 2; int halfHeight = mTmpRect.height() / 2; + int clipStartX = centerX - halfWidth - appFrame.left; + int clipStartY = centerY - halfHeight - appFrame.top; + boolean cutOff = false; + + // If the starting rectangle is fully or partially outside of the target rectangle, we + // need to start the clipping at the edge and then achieve the rest with translation + // and extending the clip rect from that edge. + if (appFrame.top > centerY - halfHeight) { + translationY = (centerY - halfHeight) - appFrame.top; + translationYCorrection = 0; + clipStartY = 0; + cutOff = true; + } + if (appFrame.left > centerX - halfWidth) { + translationX = (centerX - halfWidth) - appFrame.left; + clipStartX = 0; + cutOff = true; + } + if (appFrame.right < centerX + halfWidth) { + translationX = (centerX + halfWidth) - appFrame.right; + clipStartX = appWidth - mTmpRect.width(); + cutOff = true; + } + final long duration = calculateClipRevealTransitionDuration(cutOff, translationX, + translationY, displayFrame); // Clip third of the from size of launch icon, expand to full width/height Animation clipAnimLR = new ClipRectLRAnimation( - centerX - halfWidth, centerX + halfWidth, 0, appWidth); + clipStartX, clipStartX + mTmpRect.width(), 0, appWidth); clipAnimLR.setInterpolator(mClipHorizontalInterpolator); - clipAnimLR.setDuration((long) (DEFAULT_APP_TRANSITION_DURATION / 2.5f)); - - Animation clipAnimTB = new ClipRectTBAnimation(centerY - halfHeight - translationY, - centerY + halfHeight/ 2 - translationY, 0, appHeight); - clipAnimTB.setInterpolator(mTouchResponseInterpolator); - clipAnimTB.setDuration(DEFAULT_APP_TRANSITION_DURATION); - - // We might be animating entrance of a docked task, so we need the translate to account - // for the app frame in which the window will reside. Every other calculation here - // is performed as if the window started at 0,0. - translationY -= appFrame.top; - TranslateAnimation translate = new TranslateAnimation(-appFrame.left, 0, translationY, - 0); - translate.setInterpolator(mLinearOutSlowInInterpolator); - translate.setDuration(DEFAULT_APP_TRANSITION_DURATION); + clipAnimLR.setDuration((long) (duration / 2.5f)); + + TranslateAnimation translate = new TranslateAnimation(translationX, 0, translationY, 0); + translate.setInterpolator(cutOff ? TOUCH_RESPONSE_INTERPOLATOR + : mLinearOutSlowInInterpolator); + translate.setDuration(duration); + + Animation clipAnimTB = new ClipRectTBAnimation( + clipStartY, clipStartY + mTmpRect.height(), + 0, appHeight, + translationYCorrection, 0, + mLinearOutSlowInInterpolator); + clipAnimTB.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR); + clipAnimTB.setDuration(duration); // Quick fade-in from icon to app window - final int alphaDuration = DEFAULT_APP_TRANSITION_DURATION / 4; + final long alphaDuration = duration / 4; AlphaAnimation alpha = new AlphaAnimation(0.5f, 1); alpha.setDuration(alphaDuration); alpha.setInterpolator(mLinearOutSlowInInterpolator); @@ -688,6 +771,13 @@ public class AppTransition implements Dump { set.setZAdjustment(Animation.ZORDER_TOP); set.initialize(appWidth, appHeight, appWidth, appHeight); anim = set; + mLastHadClipReveal = true; + mLastClipRevealTransitionDuration = duration; + + // If the start rect was full inside the target rect (cutOff == false), we don't need + // to store the translation, because it's only used if cutOff == true. + mLastClipRevealMaxTranslation = cutOff + ? Math.max(Math.abs(translationY), Math.abs(translationX)) : 0; } else { final long duration; switch (transit) { @@ -794,7 +884,7 @@ public class AppTransition implements Dump { // Animation up from the thumbnail to the full screen Animation scale = new ScaleAnimation(1f, scaleW, 1f, scaleW, mTmpRect.left + (thumbWidth / 2f), mTmpRect.top + (thumbHeight / 2f)); - scale.setInterpolator(mTouchResponseInterpolator); + scale.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR); scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION); Animation alpha = new AlphaAnimation(1f, 0f); alpha.setInterpolator(mThumbnailFadeOutInterpolator); @@ -802,7 +892,7 @@ public class AppTransition implements Dump { final float toX = appRect.left + appRect.width() / 2 - (mTmpRect.left + thumbWidth / 2); Animation translate = new TranslateAnimation(0, toX, 0, toY); - translate.setInterpolator(mTouchResponseInterpolator); + translate.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR); translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION); // This AnimationSet uses the Interpolators assigned above. @@ -815,7 +905,7 @@ public class AppTransition implements Dump { // Animation down from the full screen to the thumbnail Animation scale = new ScaleAnimation(scaleW, 1f, scaleW, 1f, mTmpRect.left + (thumbWidth / 2f), mTmpRect.top + (thumbHeight / 2f)); - scale.setInterpolator(mTouchResponseInterpolator); + scale.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR); scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION); Animation alpha = new AlphaAnimation(0f, 1f); alpha.setInterpolator(mThumbnailFadeInInterpolator); @@ -823,7 +913,7 @@ public class AppTransition implements Dump { final float toX = appRect.left + appRect.width() / 2 - (mTmpRect.left + thumbWidth / 2); Animation translate = new TranslateAnimation(toX, 0, toY, 0); - translate.setInterpolator(mTouchResponseInterpolator); + translate.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR); translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION); // This AnimationSet uses the Interpolators assigned above. @@ -835,7 +925,7 @@ public class AppTransition implements Dump { } return prepareThumbnailAnimationWithDuration(a, appWidth, appRect.height(), 0, - mTouchResponseInterpolator); + TOUCH_RESPONSE_INTERPOLATOR); } /** @@ -967,7 +1057,7 @@ public class AppTransition implements Dump { int duration = Math.max(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION, THUMBNAIL_APP_TRANSITION_DURATION); return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, duration, - mTouchResponseInterpolator); + TOUCH_RESPONSE_INTERPOLATOR); } private Animation createAspectScaledThumbnailEnterFreeformAnimationLocked(Rect frame, @@ -1219,8 +1309,9 @@ public class AppTransition implements Dump { * bigger. */ Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, - int orientation, Rect frame, Rect insets, @Nullable Rect surfaceInsets, - boolean isVoiceInteraction, boolean freeform, int taskId) { + int orientation, Rect frame, Rect displayFrame, Rect insets, + @Nullable Rect surfaceInsets, boolean isVoiceInteraction, boolean freeform, + int taskId) { Animation a; if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_OPEN || transit == TRANSIT_TASK_OPEN @@ -1265,7 +1356,7 @@ public class AppTransition implements Dump { + " transit=" + appTransitionToString(transit) + " Callers=" + Debug.getCallers(3)); } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL) { - a = createClipRevealAnimationLocked(transit, enter, frame); + a = createClipRevealAnimationLocked(transit, enter, frame, displayFrame); if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation:" + " anim=" + a + " nextAppTransition=ANIM_CLIP_REVEAL" diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 2a091badd1bf..12c62bdc93bf 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -254,7 +254,7 @@ class AppWindowToken extends WindowToken { // In cases where there are multiple windows, we prefer the non-exiting window. This // happens for example when replacing windows during an activity relaunch. When // constructing the animation, we want the new window, not the exiting one. - if (win.mExiting) { + if (win.mAnimatingExit) { candidate = win; } else { return win; @@ -307,11 +307,11 @@ class AppWindowToken extends WindowToken { // If the app already requested to remove its window, we don't modify // its exiting state. Otherwise the stale window won't get removed on // exit and could cause focus to be given to the wrong window. - if (!(win.mRemoveOnExit && win.mExiting)) { - win.mExiting = exiting; + if (!(win.mRemoveOnExit && win.mAnimatingExit)) { + win.mAnimatingExit = exiting; } // If we're no longer exiting, remove the window from destroying list - if (!win.mExiting && win.mDestroying) { + if (!win.mAnimatingExit && win.mDestroying) { win.mDestroying = false; service.mDestroySurface.remove(win); } @@ -330,13 +330,13 @@ class AppWindowToken extends WindowToken { continue; } - if (!mAppStopped && !win.mClientRemoveRequested) { + if (!(mAppStopped || win.mWindowRemovalAllowed)) { continue; } win.destroyOrSaveSurface(); if (win.mRemoveOnExit) { - win.mExiting = false; + win.mAnimatingExit = false; service.removeWindowInnerLocked(win); } final DisplayContent displayContent = win.getDisplayContent(); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 144d7ac127d0..73cea52adb0f 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -127,7 +127,7 @@ class DisplayContent { isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY; mService = service; initializeDisplayBaseInfo(); - mDividerControllerLocked = new DockedStackDividerController(service.mContext, this); + mDividerControllerLocked = new DockedStackDividerController(service, this); mDimLayerController = new DimLayerController(this); } @@ -606,12 +606,24 @@ class DisplayContent { return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mStacks; } + /** + * @return The docked stack, but only if it is visible, and {@code null} otherwise. + */ TaskStack getDockedStackLocked() { final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID); return (stack != null && stack.isVisibleLocked()) ? stack : null; } /** + * Like {@link #getDockedStackLocked}, but also returns the docked stack if it's currently not + * visible, as long as it's not hidden because the current user doesn't have any tasks there. + */ + TaskStack getDockedStackVisibleForUserLocked() { + final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID); + return (stack != null && stack.isVisibleForUserLocked()) ? stack : null; + } + + /** * Find the visible, touch-deliverable window under the given point */ WindowState getTouchableWinAtPointLocked(float xf, float yf) { diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java index 75c06ff32274..b6aa3f2ed4b0 100644 --- a/services/core/java/com/android/server/wm/DockedStackDividerController.java +++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java @@ -20,10 +20,13 @@ import android.content.Context; import android.graphics.Rect; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.util.ArraySet; import android.util.Slog; import android.view.DisplayInfo; import android.view.IDockedStackListener; import android.view.SurfaceControl; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; import com.android.server.wm.DimLayer.DimLayerUser; @@ -35,6 +38,8 @@ import static android.view.WindowManager.DOCKED_BOTTOM; import static android.view.WindowManager.DOCKED_LEFT; import static android.view.WindowManager.DOCKED_RIGHT; import static android.view.WindowManager.DOCKED_TOP; +import static com.android.server.wm.AppTransition.DEFAULT_APP_TRANSITION_DURATION; +import static com.android.server.wm.AppTransition.TOUCH_RESPONSE_INTERPOLATOR; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; @@ -45,25 +50,65 @@ public class DockedStackDividerController implements DimLayerUser { private static final String TAG = TAG_WITH_CLASS_NAME ? "DockedStackDividerController" : TAG_WM; + /** + * The fraction during the maximize/clip reveal animation the divider meets the edge of the clip + * revealing surface at the earliest. + */ + private static final float CLIP_REVEAL_MEET_EARLIEST = 0.6f; + + /** + * The fraction during the maximize/clip reveal animation the divider meets the edge of the clip + * revealing surface at the latest. + */ + private static final float CLIP_REVEAL_MEET_LAST = 1f; + + /** + * If the app translates at least CLIP_REVEAL_MEET_FRACTION_MIN * minimize distance, we start + * meet somewhere between {@link #CLIP_REVEAL_MEET_LAST} and {@link #CLIP_REVEAL_MEET_EARLIEST}. + */ + private static final float CLIP_REVEAL_MEET_FRACTION_MIN = 0.4f; + + /** + * If the app translates equals or more than CLIP_REVEAL_MEET_FRACTION_MIN * minimize distance, + * we meet at {@link #CLIP_REVEAL_MEET_EARLIEST}. + */ + private static final float CLIP_REVEAL_MEET_FRACTION_MAX = 0.8f; + + private final WindowManagerService mService; private final DisplayContent mDisplayContent; private final int mDividerWindowWidth; private final int mDividerInsets; private boolean mResizing; private WindowState mWindow; private final Rect mTmpRect = new Rect(); + private final Rect mTmpRect2 = new Rect(); private final Rect mLastRect = new Rect(); private boolean mLastVisibility = false; private final RemoteCallbackList<IDockedStackListener> mDockedStackListeners = new RemoteCallbackList<>(); private final DimLayer mDimLayer; - DockedStackDividerController(Context context, DisplayContent displayContent) { + private boolean mMinimizedDock; + private boolean mAnimating; + private boolean mAnimationStarted; + private long mAnimationStartTime; + private float mAnimationStart; + private float mAnimationTarget; + private long mAnimationDuration; + private final Interpolator mMinimizedDockInterpolator; + private float mMaximizeMeetFraction; + + DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) { + mService = service; mDisplayContent = displayContent; + final Context context = service.mContext; mDividerWindowWidth = context.getResources().getDimensionPixelSize( com.android.internal.R.dimen.docked_stack_divider_thickness); mDividerInsets = context.getResources().getDimensionPixelSize( com.android.internal.R.dimen.docked_stack_divider_insets); mDimLayer = new DimLayer(displayContent.mService, this, displayContent.getDisplayId()); + mMinimizedDockInterpolator = AnimationUtils.loadInterpolator( + context, android.R.interpolator.fast_out_slow_in); } boolean isResizing() { @@ -180,6 +225,19 @@ public class DockedStackDividerController implements DimLayerUser { mDockedStackListeners.finishBroadcast(); } + void notifyDockedStackMinimizedChanged(boolean minimizedDock, long animDuration) { + final int size = mDockedStackListeners.beginBroadcast(); + for (int i = 0; i < size; ++i) { + final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i); + try { + listener.onDockedStackMinimizedChanged(minimizedDock, animDuration); + } catch (RemoteException e) { + Slog.e(TAG_WM, "Error delivering minimized dock changed event.", e); + } + } + mDockedStackListeners.finishBroadcast(); + } + void registerDockedStackListener(IDockedStackListener listener) { mDockedStackListeners.register(listener); notifyDockedDividerVisibilityChanged(wasVisible()); @@ -207,6 +265,183 @@ public class DockedStackDividerController implements DimLayerUser { SurfaceControl.closeTransaction(); } + /** + * Notifies the docked stack divider controller of a visibility change that happens without + * an animation. + */ + void notifyAppVisibilityChanged(AppWindowToken wtoken, boolean visible) { + final Task task = wtoken.mTask; + if (!task.isHomeTask() || !task.isVisibleForUser()) { + return; + } + + // If the stack is completely offscreen, this might just be an intermediate state when + // docking a task/launching recents at the same time, but home doesn't actually get + // visible after the state settles in. + if (isWithinDisplay(task) + && mDisplayContent.getDockedStackVisibleForUserLocked() != null) { + setMinimizedDockedStack(visible, false /* animate */); + } + } + + void notifyAppTransitionStarting(ArraySet<AppWindowToken> openingApps, + ArraySet<AppWindowToken> closingApps) { + if (containsHomeTaskWithinDisplay(openingApps)) { + setMinimizedDockedStack(true /* minimized */, true /* animate */); + } else if (containsHomeTaskWithinDisplay(closingApps)) { + setMinimizedDockedStack(false /* minimized */, true /* animate */); + } + } + + private boolean containsHomeTaskWithinDisplay(ArraySet<AppWindowToken> apps) { + for (int i = apps.size() - 1; i >= 0; i--) { + final Task task = apps.valueAt(i).mTask; + if (task != null && task.isHomeTask()) { + return isWithinDisplay(task); + } + } + return false; + } + + private boolean isWithinDisplay(Task task) { + task.mStack.getBounds(mTmpRect); + mDisplayContent.getLogicalDisplayRect(mTmpRect2); + return mTmpRect.intersect(mTmpRect2); + } + + /** + * Sets whether the docked stack is currently in a minimized state, i.e. all the tasks in the + * docked stack are heavily clipped so you can only see a minimal peek state. + * + * @param minimizedDock Whether the docked stack is currently minimized. + * @param animate Whether to animate the change. + */ + private void setMinimizedDockedStack(boolean minimizedDock, boolean animate) { + if (minimizedDock == mMinimizedDock + || mDisplayContent.getDockedStackVisibleForUserLocked() == null) { + return; + } + + mMinimizedDock = minimizedDock; + if (minimizedDock) { + if (animate) { + startAdjustAnimation(0f, 1f); + } else { + setMinimizedDockedStack(true); + } + } else { + if (animate) { + startAdjustAnimation(1f, 0f); + } else { + setMinimizedDockedStack(false); + } + } + } + + private void startAdjustAnimation(float from, float to) { + mAnimating = true; + mAnimationStarted = false; + mAnimationStart = from; + mAnimationTarget = to; + } + + private void setMinimizedDockedStack(boolean minimized) { + final TaskStack stack = mDisplayContent.getDockedStackVisibleForUserLocked(); + if (stack == null) { + return; + } + if (stack.setAdjustedForMinimizedDock(minimized ? 1f : 0f)) { + mService.mWindowPlacerLocked.performSurfacePlacement(); + } + notifyDockedStackMinimizedChanged(minimized, 0); + } + + private boolean isAnimationMaximizing() { + return mAnimationTarget == 0f; + } + + public boolean animate(long now) { + if (!mAnimating) { + return false; + } + + final TaskStack stack = mDisplayContent.getDockedStackVisibleForUserLocked(); + if (!mAnimationStarted) { + mAnimationStarted = true; + mAnimationStartTime = now; + final long transitionDuration = isAnimationMaximizing() + ? mService.mAppTransition.getLastClipRevealTransitionDuration() + : DEFAULT_APP_TRANSITION_DURATION; + mAnimationDuration = (long) + (transitionDuration * mService.getTransitionAnimationScaleLocked()); + mMaximizeMeetFraction = getClipRevealMeetFraction(stack); + notifyDockedStackMinimizedChanged(mMinimizedDock, + (long) (mAnimationDuration * mMaximizeMeetFraction)); + } + float t = Math.min(1f, (float) (now - mAnimationStartTime) / mAnimationDuration); + t = (isAnimationMaximizing() ? TOUCH_RESPONSE_INTERPOLATOR : mMinimizedDockInterpolator) + .getInterpolation(t); + if (stack != null) { + if (stack.setAdjustedForMinimizedDock(getMinimizeAmount(stack, t))) { + mService.mWindowPlacerLocked.performSurfacePlacement(); + } + } + if (t >= 1.0f) { + mAnimating = false; + return false; + } else { + return true; + } + } + + /** + * Gets the amount how much to minimize a stack depending on the interpolated fraction t. + */ + private float getMinimizeAmount(TaskStack stack, float t) { + final float naturalAmount = t * mAnimationTarget + (1 - t) * mAnimationStart; + if (isAnimationMaximizing()) { + return adjustMaximizeAmount(stack, t, naturalAmount); + } else { + return naturalAmount; + } + } + + /** + * When maximizing the stack during a clip reveal transition, this adjusts the minimize amount + * during the transition such that the edge of the clip reveal rect is met earlier in the + * transition so we don't create a visible "hole", but only if both the clip reveal and the + * docked stack divider start from about the same portion on the screen. + */ + private float adjustMaximizeAmount(TaskStack stack, float t, float naturalAmount) { + if (mMaximizeMeetFraction == 1f) { + return naturalAmount; + } + final int minimizeDistance = stack.getMinimizeDistance(); + float startPrime = mService.mAppTransition.getLastClipRevealMaxTranslation() + / (float) minimizeDistance; + final float amountPrime = t * mAnimationTarget + (1 - t) * startPrime; + final float t2 = Math.min(t / mMaximizeMeetFraction, 1); + return amountPrime * t2 + naturalAmount * (1 - t2); + } + + /** + * Retrieves the animation fraction at which the docked stack has to meet the clip reveal + * edge. See {@link #adjustMaximizeAmount}. + */ + private float getClipRevealMeetFraction(TaskStack stack) { + if (!isAnimationMaximizing() || stack == null || + !mService.mAppTransition.hadClipRevealAnimation()) { + return 1f; + } + final int minimizeDistance = stack.getMinimizeDistance(); + final float fraction = Math.abs(mService.mAppTransition.getLastClipRevealMaxTranslation()) + / (float) minimizeDistance; + final float t = Math.max(0, Math.min(1, (fraction - CLIP_REVEAL_MEET_FRACTION_MIN) + / (CLIP_REVEAL_MEET_FRACTION_MAX - CLIP_REVEAL_MEET_FRACTION_MIN))); + return CLIP_REVEAL_MEET_EARLIEST + + (1 - t) * (CLIP_REVEAL_MEET_LAST - CLIP_REVEAL_MEET_EARLIEST); + } + @Override public boolean isFullscreen() { return false; diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index fe55e80d76f7..325005bb2206 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -357,6 +357,10 @@ class Task implements DimLayer.DimLayerUser { return !mHomeTask && (isResizeable() || mResizeMode == RESIZE_MODE_CROP_WINDOWS); } + boolean isHomeTask() { + return mHomeTask; + } + private boolean inCropWindowsResizeMode() { return !mHomeTask && !isResizeable() && mResizeMode == RESIZE_MODE_CROP_WINDOWS; } @@ -639,6 +643,19 @@ class Task implements DimLayer.DimLayerUser { return (tokensCount != 0) && mAppTokens.get(tokensCount - 1).showForAllUsers; } + boolean isVisibleForUser() { + for (int i = mAppTokens.size() - 1; i >= 0; i--) { + final AppWindowToken appToken = mAppTokens.get(i); + for (int j = appToken.allAppWindows.size() - 1; j >= 0; j--) { + WindowState window = appToken.allAppWindows.get(j); + if (!window.isHiddenFromUserLocked()) { + return true; + } + } + } + return false; + } + boolean inHomeStack() { return mStack != null && mStack.mStackId == HOME_STACK_ID; } diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 8409058ccf8b..06e5ac5d440e 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -75,9 +75,6 @@ public class TaskStack implements DimLayer.DimLayerUser, /** Content limits relative to the DisplayContent this sits in. */ private Rect mBounds = new Rect(); - /** Screen content area excluding IM windows, etc. */ - private final Rect mContentBounds = new Rect(); - /** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */ private final Rect mAdjustedBounds = new Rect(); @@ -98,14 +95,27 @@ public class TaskStack implements DimLayer.DimLayerUser, /** Detach this stack from its display when animation completes. */ boolean mDeferDetach; - private boolean mUpdateBoundsAfterRotation = false; + + // Display rotation as of the last time the display information was updated for this stack. + private int mLastUpdateDisplayInfoRotation = -1; + // Display rotation as of the last time the configuration was updated for this stack. + private int mLastConfigChangedRotation = -1; // Whether the stack and all its tasks is currently being drag-resized private boolean mDragResizing; + private final Rect mLastContentBounds = new Rect(); + private final Rect mTmpAdjustedBounds = new Rect(); + private boolean mAdjustedForIme; + private WindowState mImeWin; + private float mMinimizeAmount; + private final int mDockedStackMinimizeThickness; + TaskStack(WindowManagerService service, int stackId) { mService = service; mStackId = stackId; + mDockedStackMinimizeThickness = service.mContext.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.docked_stack_minimize_thickness); EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId); } @@ -174,7 +184,27 @@ public class TaskStack implements DimLayer.DimLayerUser, return mTmpRect.equals(bounds); } - void alignTasksToAdjustedBounds(final Rect adjustedBounds) { + /** + * Overrides the adjusted bounds, i.e. sets temporary layout bounds which are different from + * the normal task bounds. + * + * @param bounds The adjusted bounds. + * @param keepInsets Whether to keep the insets from the original bounds or to calculate new + * ones depending on the adjusted bounds. + */ + private void setAdjustedBounds(Rect bounds, boolean keepInsets) { + if (mAdjustedBounds.equals(bounds)) { + return; + } + + mAdjustedBounds.set(bounds); + final boolean adjusted = !mAdjustedBounds.isEmpty(); + alignTasksToAdjustedBounds(adjusted ? mAdjustedBounds : mBounds, + adjusted && keepInsets ? mBounds : null); + mDisplayContent.layoutNeeded = true; + } + + private void alignTasksToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds) { if (mFullscreen) { return; } @@ -187,72 +217,15 @@ public class TaskStack implements DimLayer.DimLayerUser, task.resizeLocked(null, null, false /* forced */); task.getBounds(mTmpRect2); task.scrollLocked(mTmpRect2); - } else if (task.isResizeable()) { + } else if (task.isResizeable() && task.mOverrideConfig != Configuration.EMPTY) { task.getBounds(mTmpRect2); mTmpRect2.offsetTo(adjustedBounds.left, adjustedBounds.top); + task.setTempInsetBounds(tempInsetBounds); task.resizeLocked(mTmpRect2, task.mOverrideConfig, false /* forced */); } } } - void adjustForIME(final WindowState imeWin) { - final int dockedSide = getDockSide(); - final boolean dockedTopOrBottom = dockedSide == DOCKED_TOP || dockedSide == DOCKED_BOTTOM; - final Rect adjustedBounds = mAdjustedBounds; - if (imeWin == null || !dockedTopOrBottom) { - // If mContentBounds is already empty, it means we're not applying - // any adjustments, so nothing to do; otherwise clear any adjustments. - if (!mContentBounds.isEmpty()) { - mContentBounds.setEmpty(); - adjustedBounds.set(mBounds); - alignTasksToAdjustedBounds(adjustedBounds); - } - return; - } - - final Rect displayContentRect = mTmpRect; - final Rect contentBounds = mTmpRect2; - - // Calculate the content bounds excluding the area occupied by IME - mDisplayContent.getContentRect(displayContentRect); - contentBounds.set(displayContentRect); - int imeTop = Math.max(imeWin.getDisplayFrameLw().top, contentBounds.top); - imeTop += imeWin.getGivenContentInsetsLw().top; - if (contentBounds.bottom > imeTop) { - contentBounds.bottom = imeTop; - } - - // If content bounds not changing, nothing to do. - if (mContentBounds.equals(contentBounds)) { - return; - } - - // Content bounds changed, need to apply adjustments depending on dock sides. - mContentBounds.set(contentBounds); - adjustedBounds.set(mBounds); - final int yOffset = displayContentRect.bottom - contentBounds.bottom; - - if (dockedSide == DOCKED_TOP) { - // If this stack is docked on top, we make it smaller so the bottom stack is not - // occluded by IME. We shift its bottom up by the height of the IME (capped by - // the display content rect). Note that we don't change the task bounds. - adjustedBounds.bottom = Math.max( - adjustedBounds.bottom - yOffset, displayContentRect.top); - } else { - // If this stack is docked on bottom, we shift it up so that it's not occluded by - // IME. We try to move it up by the height of the IME window (although the best - // we could do is to make the top stack fully collapsed). - final int dividerWidth = mDisplayContent.mDividerControllerLocked.getContentWidth(); - adjustedBounds.top = Math.max( - adjustedBounds.top - yOffset, displayContentRect.top + dividerWidth); - adjustedBounds.bottom = adjustedBounds.top + mBounds.height(); - - // We also move the member tasks together, taking care not to resize them. - // Resizing might cause relaunch, and IME window may not come back after that. - alignTasksToAdjustedBounds(adjustedBounds); - } - } - private boolean setBounds(Rect bounds) { boolean oldFullscreen = mFullscreen; int rotation = Surface.ROTATION_0; @@ -281,14 +254,7 @@ public class TaskStack implements DimLayer.DimLayerUser, mBounds.set(bounds); mRotation = rotation; - // Clear the adjusted content bounds as they're no longer valid. - // If IME is still visible, these will be re-applied. - // Note that we don't clear mContentBounds here, so that we know the last IME - // adjust we applied. - // If user starts dragging the dock divider while IME is visible, the new bounds - // we received are based on the actual screen location of the divider. It already - // accounted for the IME window, so we don't want to adjust again. - mAdjustedBounds.set(mBounds); + updateAdjustedBounds(); return true; } @@ -314,10 +280,11 @@ public class TaskStack implements DimLayer.DimLayerUser, public void getBounds(Rect out) { if (useCurrentBounds()) { - // If we're currently adjusting for IME, we use the adjusted bounds; otherwise, - // no need to adjust the output bounds if fullscreen or the docked stack is visible - // since it is already what we want to represent to the rest of the system. - if (!mContentBounds.isEmpty()) { + // If we're currently adjusting for IME or minimized docked stack, we use the adjusted + // bounds; otherwise, no need to adjust the output bounds if fullscreen or the docked + // stack is visible since it is already what we want to represent to the rest of the + // system. + if (!mAdjustedBounds.isEmpty()) { out.set(mAdjustedBounds); } else { out.set(mBounds); @@ -338,39 +305,51 @@ public class TaskStack implements DimLayer.DimLayerUser, } void updateDisplayInfo(Rect bounds) { - mUpdateBoundsAfterRotation = false; - if (mDisplayContent != null) { - for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { - mTasks.get(taskNdx).updateDisplayInfo(mDisplayContent); - } - if (bounds != null) { - setBounds(bounds); - } else if (mFullscreen) { - setBounds(null); - } else { - mUpdateBoundsAfterRotation = true; - mTmpRect2.set(mBounds); - final int newRotation = mDisplayContent.getDisplayInfo().rotation; - if (mRotation == newRotation) { - setBounds(mTmpRect2); - } + if (mDisplayContent == null) { + return; + } - // If the rotation changes, we'll handle it in updateBoundsAfterRotation - } + for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { + mTasks.get(taskNdx).updateDisplayInfo(mDisplayContent); + } + if (bounds != null) { + setBounds(bounds); + return; + } else if (mFullscreen) { + setBounds(null); + return; + } + + mTmpRect2.set(mBounds); + final int newRotation = mDisplayContent.getDisplayInfo().rotation; + if (mRotation == newRotation) { + setBounds(mTmpRect2); + } else { + mLastUpdateDisplayInfoRotation = newRotation; + updateBoundsAfterRotation(); } } - /** - * Updates the bounds after rotating the screen. We can't handle it in - * {@link #updateDisplayInfo} because at that point the configuration might not be fully updated - * yet. - */ + void onConfigurationChanged() { + mLastConfigChangedRotation = getDisplayInfo().rotation; + updateBoundsAfterRotation(); + } + void updateBoundsAfterRotation() { - if (!mUpdateBoundsAfterRotation) { + if (mLastConfigChangedRotation != mLastUpdateDisplayInfoRotation) { + // We wait for the rotation values after configuration change and display info. update + // to be equal before updating the bounds due to rotation change otherwise things might + // get out of alignment... return; } - mUpdateBoundsAfterRotation = false; + final int newRotation = getDisplayInfo().rotation; + + if (mRotation == newRotation) { + // Nothing to do here if the rotation didn't change + return; + } + mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2); if (mStackId == DOCKED_STACK_ID) { snapDockedStackAfterRotation(mTmpRect2); @@ -379,8 +358,8 @@ public class TaskStack implements DimLayer.DimLayerUser, // Post message to inform activity manager of the bounds change simulating // a one-way call. We do this to prevent a deadlock between window manager // lock and activity manager lock been held. - mService.mH.sendMessage(mService.mH.obtainMessage( - RESIZE_STACK, mStackId, 0 /*allowResizeInDockedMode*/, mTmpRect2)); + mService.mH.obtainMessage( + RESIZE_STACK, mStackId, 0 /*allowResizeInDockedMode*/, mTmpRect2).sendToTarget(); } /** @@ -420,7 +399,7 @@ public class TaskStack implements DimLayer.DimLayerUser, final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows; for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { final WindowStateAnimator winAnimator = windows.get(winNdx).mWinAnimator; - if (winAnimator.isAnimating() || winAnimator.mWin.mExiting) { + if (winAnimator.isAnimating() || winAnimator.mWin.mAnimatingExit) { return true; } } @@ -691,7 +670,7 @@ public class TaskStack implements DimLayer.DimLayerUser, outBounds.top = dockedBounds.bottom + dockDividerWidth; } } - DockedDividerUtils.sanitizeStackBounds(outBounds); + DockedDividerUtils.sanitizeStackBounds(outBounds, !dockOnTopOrLeft); } /** Resizes all non-docked stacks in the system to either fullscreen or the appropriate size @@ -802,6 +781,158 @@ public class TaskStack implements DimLayer.DimLayerUser, mDisplayContent = null; } + /** + * Adjusts the stack bounds if the IME is visible. + * + * @param imeWin The IME window. + */ + void setAdjustedForIme(WindowState imeWin) { + mAdjustedForIme = true; + mImeWin = imeWin; + updateAdjustedBounds(); + } + + /** + * Resets the adjustment after it got adjusted for the IME. + */ + void resetAdjustedForIme() { + mAdjustedForIme = false; + mImeWin = null; + updateAdjustedBounds(); + } + + /** + * Sets the amount how much we currently minimize our stack. + * + * @param minimizeAmount The amount, between 0 and 1. + * @return Whether the amount has changed and a layout is needed. + */ + boolean setAdjustedForMinimizedDock(float minimizeAmount) { + if (minimizeAmount != mMinimizeAmount) { + mMinimizeAmount = minimizeAmount; + updateAdjustedBounds(); + return isVisibleForUserLocked(); + } else { + return false; + } + } + + private boolean adjustForIME(final WindowState imeWin) { + final int dockedSide = getDockSide(); + final boolean dockedTopOrBottom = dockedSide == DOCKED_TOP || dockedSide == DOCKED_BOTTOM; + final Rect adjustedBounds = mTmpAdjustedBounds; + if (imeWin == null || !dockedTopOrBottom) { + return false; + } + + final Rect displayContentRect = mTmpRect; + final Rect contentBounds = mTmpRect2; + + // Calculate the content bounds excluding the area occupied by IME + getDisplayContent().getContentRect(displayContentRect); + contentBounds.set(displayContentRect); + int imeTop = Math.max(imeWin.getDisplayFrameLw().top, contentBounds.top); + imeTop += imeWin.getGivenContentInsetsLw().top; + if (contentBounds.bottom > imeTop) { + contentBounds.bottom = imeTop; + } + + // If content bounds not changing, nothing to do. + if (mLastContentBounds.equals(contentBounds)) { + return true; + } + + // Content bounds changed, need to apply adjustments depending on dock sides. + mLastContentBounds.set(contentBounds); + adjustedBounds.set(mBounds); + final int yOffset = displayContentRect.bottom - contentBounds.bottom; + + if (dockedSide == DOCKED_TOP) { + // If this stack is docked on top, we make it smaller so the bottom stack is not + // occluded by IME. We shift its bottom up by the height of the IME (capped by + // the display content rect). Note that we don't change the task bounds. + adjustedBounds.bottom = Math.max( + adjustedBounds.bottom - yOffset, displayContentRect.top); + } else { + // If this stack is docked on bottom, we shift it up so that it's not occluded by + // IME. We try to move it up by the height of the IME window (although the best + // we could do is to make the top stack fully collapsed). + final int dividerWidth = getDisplayContent().mDividerControllerLocked + .getContentWidth(); + adjustedBounds.top = Math.max( + adjustedBounds.top - yOffset, displayContentRect.top + dividerWidth); + adjustedBounds.bottom = adjustedBounds.top + mBounds.height(); + } + return true; + } + + private boolean adjustForMinimizedDockedStack(float minimizeAmount) { + final int dockSide = getDockSide(); + if (dockSide == DOCKED_INVALID && !mTmpAdjustedBounds.isEmpty()) { + return false; + } + + if (dockSide == DOCKED_TOP) { + mService.getStableInsetsLocked(mTmpRect); + int topInset = mTmpRect.top; + mTmpAdjustedBounds.set(mBounds); + mTmpAdjustedBounds.bottom = + (int) (minimizeAmount * topInset + (1 - minimizeAmount) * mBounds.bottom); + } else if (dockSide == DOCKED_LEFT) { + mTmpAdjustedBounds.set(mBounds); + mTmpAdjustedBounds.right = + (int) (minimizeAmount * mDockedStackMinimizeThickness + + (1 - minimizeAmount) * mBounds.right); + } else if (dockSide == DOCKED_RIGHT) { + mTmpAdjustedBounds.set(mBounds); + mTmpAdjustedBounds.left = + (int) (minimizeAmount * (mBounds.right - mDockedStackMinimizeThickness) + + (1 - minimizeAmount) * mBounds.left); + } + return true; + } + + /** + * @return the distance in pixels how much the stack gets minimized from it's original size + */ + int getMinimizeDistance() { + final int dockSide = getDockSide(); + if (dockSide == DOCKED_INVALID) { + return 0; + } + + if (dockSide == DOCKED_TOP) { + mService.getStableInsetsLocked(mTmpRect); + int topInset = mTmpRect.top; + return mBounds.bottom - topInset; + } else if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) { + return mBounds.width() - mDockedStackMinimizeThickness; + } else { + return 0; + } + } + + /** + * Updates the adjustment depending on it's current state. + */ + void updateAdjustedBounds() { + boolean adjust = false; + if (mMinimizeAmount != 0f) { + adjust = adjustForMinimizedDockedStack(mMinimizeAmount); + } else if (mAdjustedForIme) { + adjust = adjustForIME(mImeWin); + } + if (!adjust) { + mTmpAdjustedBounds.setEmpty(); + mLastContentBounds.setEmpty(); + } + setAdjustedBounds(mTmpAdjustedBounds, isAdjustedForMinimizedDockedStack()); + } + + boolean isAdjustedForMinimizedDockedStack() { + return mMinimizeAmount != 0f; + } + public void dump(String prefix, PrintWriter pw) { pw.println(prefix + "mStackId=" + mStackId); pw.println(prefix + "mDeferDetach=" + mDeferDetach); @@ -906,13 +1037,28 @@ public class TaskStack implements DimLayer.DimLayerUser, } for (int i = mTasks.size() - 1; i >= 0; i--) { - Task task = mTasks.get(i); + final Task task = mTasks.get(i); for (int j = task.mAppTokens.size() - 1; j >= 0; j--) { if (!task.mAppTokens.get(j).hidden) { return true; } } } + + return false; + } + + /** + * @return true if a the stack is visible for the current in user, ignoring any other visibility + * aspects, and false otherwise + */ + boolean isVisibleForUserLocked() { + for (int i = mTasks.size() - 1; i >= 0; i--) { + final Task task = mTasks.get(i); + if (task.isVisibleForUser()) { + return true; + } + } return false; } @@ -979,4 +1125,4 @@ public class TaskStack implements DimLayer.DimLayerUser, public void getFullScreenBounds(Rect bounds) { getDisplayContent().getContentRect(bounds); } -}
\ No newline at end of file +} diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index f8a4d33d7af1..38d0711e42b3 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -705,7 +705,8 @@ public class WindowAnimator { } orAnimating(mService.getDisplayContentLocked(displayId).animateDimLayers()); - + orAnimating(mService.getDisplayContentLocked(displayId).getDockedDividerController() + .animate(mCurrentTime)); //TODO (multidisplay): Magnification is supported only for the default display. if (mService.mAccessibilityController != null && displayId == Display.DEFAULT_DISPLAY) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index b66178650425..142715e89c6c 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -116,7 +116,7 @@ import android.view.WindowManagerPolicy.PointerEventListener; import android.view.animation.Animation; import android.view.inputmethod.InputMethodManagerInternal; import android.widget.Toast; -import com.android.internal.R; + import com.android.internal.app.IAssistScreenshotReceiver; import com.android.internal.os.IResultReceiver; import com.android.internal.util.FastPrintWriter; @@ -192,6 +192,8 @@ import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY; import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED; import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; +import static android.view.WindowManagerPolicy.TRANSIT_EXIT; +import static android.view.WindowManagerPolicy.TRANSIT_PREVIEW_DONE; import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END; import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; @@ -1354,7 +1356,7 @@ public class WindowManagerService extends IWindowManager.Stub + " policyVis=" + w.mPolicyVisibility + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim + " attachHid=" + w.mAttachedHidden - + " exiting=" + w.mExiting + " destroying=" + w.mDestroying); + + " exiting=" + w.mAnimatingExit + " destroying=" + w.mDestroying); if (w.mAppToken != null) { Slog.i(TAG_WM, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested); } @@ -2057,7 +2059,7 @@ public class WindowManagerService extends IWindowManager.Stub WindowState replacedWindow = null; for (int i = atoken.windows.size() - 1; i >= 0 && replacedWindow == null; i--) { WindowState candidate = atoken.windows.get(i); - if (candidate.mExiting && candidate.mWillReplaceWindow + if (candidate.mAnimatingExit && candidate.mWillReplaceWindow && candidate.mAnimateReplacingWindow) { replacedWindow = candidate; } @@ -2131,19 +2133,12 @@ public class WindowManagerService extends IWindowManager.Stub if (win == null) { return; } - // We set this here instead of removeWindowLocked because we only want it to be - // true when the client has requested we remove the window. In other remove - // cases, we have to wait for activity stop to safely remove the window (as the - // client may still be using the surface). In this case though, the client has - // just dismissed a window (for example a Dialog) and activity stop isn't - // necessarily imminent, so we need to know not to wait for it after our - // hanimation (if applicable) finishes. - win.mClientRemoveRequested = true; removeWindowLocked(win); } } void removeWindowLocked(WindowState win) { + win.mWindowRemovalAllowed = true; final boolean startingWindow = win.mAttrs.type == TYPE_APPLICATION_STARTING; if (startingWindow) { if (DEBUG_STARTING_WINDOW) Slog.d(TAG_WM, "Starting window removed " + win); @@ -2159,23 +2154,25 @@ public class WindowManagerService extends IWindowManager.Stub win.disposeInputChannel(); - if (DEBUG_APP_TRANSITIONS) Slog.v( - TAG_WM, "Remove " + win + ": mSurfaceController=" + win.mWinAnimator.mSurfaceController - + " mExiting=" + win.mExiting + if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, + "Remove " + win + ": mSurfaceController=" + win.mWinAnimator.mSurfaceController + + " mAnimatingExit=" + win.mAnimatingExit + + " mRemoveOnExit=" + win.mRemoveOnExit + + " mHasSurface=" + win.mHasSurface + + " surfaceShowing=" + win.mWinAnimator.getShown() + " isAnimating=" + win.mWinAnimator.isAnimating() + " app-animation=" + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null) - + " mWillReplaceWindow=" - + win.mWillReplaceWindow + + " mWillReplaceWindow=" + win.mWillReplaceWindow + " inPendingTransaction=" + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false) - + " mDisplayFrozen=" + mDisplayFrozen); + + " mDisplayFrozen=" + mDisplayFrozen + + " callers=" + Debug.getCallers(6)); // Visibility of the removed window. Will be used later to update orientation later on. boolean wasVisible = false; - // First, see if we need to run an animation. If we do, we have - // to hold off on removing the window until the animation is done. - // If the display is frozen, just remove immediately, since the - // animation wouldn't be seen. + // First, see if we need to run an animation. If we do, we have to hold off on removing the + // window until the animation is done. If the display is frozen, just remove immediately, + // since the animation wouldn't be seen. if (win.mHasSurface && okToDisplay()) { final AppWindowToken appToken = win.mAppToken; if (win.mWillReplaceWindow) { @@ -2183,13 +2180,16 @@ public class WindowManagerService extends IWindowManager.Stub // gets added, then we will get rid of this one. if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Preserving " + win + " until the new one is " + "added"); - win.mExiting = true; + // TODO: We are overloading mAnimatingExit flag to prevent the window state from + // been removed. We probably need another falg to indicate that window removal + // should be deffered vs. overloading the flag that says we are playing an exit + // animation. + win.mAnimatingExit = true; win.mReplacingRemoveRequested = true; Binder.restoreCallingIdentity(origId); return; } - // If we are not currently running the exit animation, we - // need to see about starting one. + // If we are not currently running the exit animation, we need to see about starting one wasVisible = win.isWinVisibleLw(); if (win.shouldKeepVisibleDeadAppWindow()) { @@ -2209,14 +2209,13 @@ public class WindowManagerService extends IWindowManager.Stub return; } + final WindowStateAnimator winAnimator = win.mWinAnimator; if (wasVisible) { - final int transit = (!startingWindow) - ? WindowManagerPolicy.TRANSIT_EXIT - : WindowManagerPolicy.TRANSIT_PREVIEW_DONE; + final int transit = (!startingWindow) ? TRANSIT_EXIT : TRANSIT_PREVIEW_DONE; // Try starting an animation. - if (win.mWinAnimator.applyAnimationLocked(transit, false)) { - win.mExiting = true; + if (winAnimator.applyAnimationLocked(transit, false)) { + win.mAnimatingExit = true; } //TODO (multidisplay): Magnification is supported only for the default display. if (mAccessibilityController != null @@ -2224,15 +2223,20 @@ public class WindowManagerService extends IWindowManager.Stub mAccessibilityController.onWindowTransitionLocked(win, transit); } } - final boolean isAnimating = win.mWinAnimator.isAnimating() - && !win.mWinAnimator.isDummyAnimation(); - // The starting window is the last window in this app token and it isn't animating. - // Allow it to be removed now as there is no additional window or animation that will - // trigger its removal. - final boolean lastWinStartingNotAnimating = startingWindow && appToken!= null - && appToken.allAppWindows.size() == 1 && !isAnimating; - if (!lastWinStartingNotAnimating && win.mExiting) { - // The exit animation is running... wait for it! + final boolean isAnimating = + winAnimator.isAnimating() && !winAnimator.isDummyAnimation(); + final boolean lastWindowIsStartingWindow = startingWindow && appToken != null + && appToken.allAppWindows.size() == 1; + // We delay the removal of a window if it has a showing surface that can be used to run + // exit animation and it is marked as exiting. + // Also, If isn't the an animating starting window that is the last window in the app. + // We allow the removal of the non-animating starting window now as there is no + // additional window or animation that will trigger its removal. + if (winAnimator.getShown() && win.mAnimatingExit + && (!lastWindowIsStartingWindow || isAnimating)) { + // The exit animation is running or should run... wait for it! + if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, + "Not removing " + win + " due to exit animation "); win.mRemoveOnExit = true; win.setDisplayLayoutNeeded(); final boolean focusChanged = updateFocusedWindowLocked( @@ -2262,13 +2266,14 @@ public class WindowManagerService extends IWindowManager.Stub void removeWindowInnerLocked(WindowState win) { if (win.mRemoved) { // Nothing to do. + if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, + "removeWindowInnerLocked: " + win + " Already removed..."); return; } - for (int i=win.mChildWindows.size()-1; i>=0; i--) { + for (int i = win.mChildWindows.size() - 1; i >= 0; i--) { WindowState cwin = win.mChildWindows.get(i); - Slog.w(TAG_WM, "Force-removing child win " + cwin + " from container " - + win); + Slog.w(TAG_WM, "Force-removing child win " + cwin + " from container " + win); removeWindowInnerLocked(cwin); } @@ -2681,16 +2686,16 @@ public class WindowManagerService extends IWindowManager.Stub final boolean usingSavedSurfaceBeforeVisible = oldVisibility != View.VISIBLE && win.isAnimatingWithSavedSurface(); if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) { - if (winAnimator.hasSurface() && !win.mExiting + if (winAnimator.hasSurface() && !win.mAnimatingExit && usingSavedSurfaceBeforeVisible) { Slog.d(TAG, "Ignoring layout to invisible when using saved surface " + win); } } - if (winAnimator.hasSurface() && !win.mExiting + if (winAnimator.hasSurface() && !win.mAnimatingExit && !usingSavedSurfaceBeforeVisible) { if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Relayout invis " + win - + ": mExiting=" + win.mExiting); + + ": mAnimatingExit=" + win.mAnimatingExit); // If we are not currently running the exit animation, we // need to see about starting one. // We don't want to animate visibility of windows which are pending @@ -2797,16 +2802,16 @@ public class WindowManagerService extends IWindowManager.Stub } if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) { focusMayChange = isDefaultDisplay; - win.mExiting = true; + win.mAnimatingExit = true; } else if (win.mWinAnimator.isAnimating()) { // Currently in a hide animation... turn this into // an exit. - win.mExiting = true; + win.mAnimatingExit = true; } else if (mWallpaperControllerLocked.isWallpaperTarget(win)) { // If the wallpaper is currently behind this // window, we need to change both of them inside // of a transaction to avoid artifacts. - win.mExiting = true; + win.mAnimatingExit = true; win.mWinAnimator.mAnimating = true; } else { if (mInputMethodWindow == win) { @@ -2842,12 +2847,12 @@ public class WindowManagerService extends IWindowManager.Stub private int relayoutVisibleWindow(Configuration outConfig, int result, WindowState win, WindowStateAnimator winAnimator, int attrChanges, int oldVisibility) { result |= !win.isVisibleLw() ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0; - if (win.mExiting) { - Slog.d(TAG, "relayoutVisibleWindow: " + win + " mExiting=true, mRemoveOnExit=" + if (win.mAnimatingExit) { + Slog.d(TAG, "relayoutVisibleWindow: " + win + " mAnimatingExit=true, mRemoveOnExit=" + win.mRemoveOnExit + ", mDestroying=" + win.mDestroying); winAnimator.cancelExitAnimationForNextAnimationLocked(); - win.mExiting = false; + win.mAnimatingExit = false; } if (win.mDestroying) { win.mDestroying = false; @@ -2968,6 +2973,8 @@ public class WindowManagerService extends IWindowManager.Stub // Determine the visible rect to calculate the thumbnail clip final WindowState win = atoken.findMainWindow(); final Rect frame = new Rect(0, 0, width, height); + final Rect displayFrame = new Rect(0, 0, + displayInfo.logicalWidth, displayInfo.logicalHeight); final Rect insets = new Rect(); Rect surfaceInsets = null; final boolean freeform = win != null && win.inFreeformWorkspace(); @@ -2995,8 +3002,8 @@ public class WindowManagerService extends IWindowManager.Stub + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets); Animation a = mAppTransition.loadAnimation(lp, transit, enter, - mCurConfiguration.orientation, frame, insets, surfaceInsets, isVoiceInteraction, - freeform, atoken.mTask.mTaskId); + mCurConfiguration.orientation, frame, displayFrame, insets, surfaceInsets, + isVoiceInteraction, freeform, atoken.mTask.mTaskId); if (a != null) { if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + atoken); final int containingWidth = frame.width(); @@ -3542,23 +3549,20 @@ public class WindowManagerService extends IWindowManager.Stub } synchronized(mWindowMap) { - final boolean orientationChanged = mCurConfiguration.orientation != config.orientation; mCurConfiguration = new Configuration(config); if (mWaitingForConfig) { mWaitingForConfig = false; mLastFinishedFreezeSource = "new-config"; } - if (orientationChanged) { - updateTaskStackBoundsAfterRotation(); - } + onConfigurationChanged(); mWindowPlacerLocked.performSurfacePlacement(); } } - private void updateTaskStackBoundsAfterRotation() { + private void onConfigurationChanged() { for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; stackNdx--) { final TaskStack stack = mStackIdToStack.valueAt(stackNdx); - stack.updateBoundsAfterRotation(); + stack.onConfigurationChanged(); } } @@ -4153,11 +4157,15 @@ public class WindowManagerService extends IWindowManager.Stub } } - if (visibilityChanged && visible && !delayed) { - // The token was made immediately visible, there will be no entrance animation. We need - // to inform the client the enter animation was finished. - wtoken.mEnteringAnimation = true; - mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(wtoken.token); + if (visibilityChanged && !delayed) { + if (visible) { + // The token was made immediately visible, there will be no entrance animation. + // We need to inform the client the enter animation was finished. + wtoken.mEnteringAnimation = true; + mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(wtoken.token); + } + getDefaultDisplayContentLocked().getDockedDividerController() + .notifyAppVisibilityChanged(wtoken, visible); } return delayed; @@ -8124,14 +8132,14 @@ public class WindowManagerService extends IWindowManager.Stub for (int i = stacks.size() - 1; i >= 0; --i) { final TaskStack stack = stacks.get(i); if (stack.isVisibleLocked()) { - stack.adjustForIME(imeWin); + stack.setAdjustedForIme(imeWin); } } } else { final ArrayList<TaskStack> stacks = displayContent.getStacks(); for (int i = stacks.size() - 1; i >= 0; --i) { final TaskStack stack = stacks.get(i); - stack.adjustForIME(null); + stack.resetAdjustedForIme(); } } } @@ -10333,7 +10341,8 @@ public class WindowManagerService extends IWindowManager.Stub @Override public int getDockedStackSide() { synchronized (mWindowMap) { - TaskStack dockedStack = getDefaultDisplayContentLocked().getDockedStackLocked(); + final TaskStack dockedStack = getDefaultDisplayContentLocked() + .getDockedStackVisibleForUserLocked(); return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide(); } } @@ -10417,11 +10426,16 @@ public class WindowManagerService extends IWindowManager.Stub } } - private void getStableInsetsLocked(Rect outInsets) { + void getStableInsetsLocked(Rect outInsets) { final DisplayInfo di = getDefaultDisplayInfoLocked(); mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets); } + private void getNonDecorInsetsLocked(Rect outInsets) { + final DisplayInfo di = getDefaultDisplayInfoLocked(); + mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets); + } + /** * Intersects the specified {@code inOutBounds} with the display frame that excludes the stable * inset areas. @@ -10438,6 +10452,23 @@ public class WindowManagerService extends IWindowManager.Stub } } + /** + * Intersects the specified {@code inOutBounds} with the display frame that excludes + * areas that could never be removed in Honeycomb. See + * {@link WindowManagerPolicy#getNonDecorInsetsLw}. + * + * @param inOutBounds The inOutBounds to subtract the inset areas from. + */ + public void subtractNonDecorInsets(Rect inOutBounds) { + synchronized (mWindowMap) { + getNonDecorInsetsLocked(mTmpRect2); + final DisplayInfo di = getDefaultDisplayInfoLocked(); + mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight); + mTmpRect.inset(mTmpRect2); + inOutBounds.intersect(mTmpRect); + } + } + private MousePositionTracker mMousePositionTracker = new MousePositionTracker(); private static class MousePositionTracker implements PointerEventListener { diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 0958ad21aabd..f30c8d3f751b 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -358,7 +358,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { boolean mLayoutNeeded; /** Currently running an exit animation? */ - boolean mExiting; + boolean mAnimatingExit; /** Currently on the mDestroySurface list? */ boolean mDestroying; @@ -387,11 +387,11 @@ final class WindowState implements WindowManagerPolicy.WindowState { boolean mRemoved; /** - * Has the client requested we remove the window? In this case we know - * that we can dispose of it when we wish without further synchronization - * with the client + * It is save to remove the window and destroy the surface because the client requested removal + * or some other higher level component said so (e.g. activity manager). + * TODO: We should either have different booleans for the removal reason or use a bit-field. */ - boolean mClientRemoveRequested; + boolean mWindowRemovalAllowed; /** * Temp for keeping track of windows that have been removed when @@ -614,7 +614,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { @Override public void computeFrameLw(Rect pf, Rect df, Rect of, Rect cf, Rect vf, Rect dcf, Rect sf, Rect osf) { - if (mWillReplaceWindow && (mExiting || !mReplacingRemoveRequested)) { + if (mWillReplaceWindow && (mAnimatingExit || !mReplacingRemoveRequested)) { // This window is being replaced and either already got information that it's being // removed or we are still waiting for some information. Because of this we don't // want to apply any more changes to it, so it remains in this state until new window @@ -1075,7 +1075,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { */ private boolean isVisibleUnchecked() { return mHasSurface && mPolicyVisibility && !mAttachedHidden - && !mExiting && !mDestroying && (!mIsWallpaper || mWallpaperVisible); + && !mAnimatingExit && !mDestroying && (!mIsWallpaper || mWallpaperVisible); } /** @@ -1100,7 +1100,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { } final AppWindowToken atoken = mAppToken; final boolean animating = atoken != null && atoken.mAppAnimator.animation != null; - return mHasSurface && !mDestroying && !mExiting + return mHasSurface && !mDestroying && !mAnimatingExit && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested) && ((!mAttachedHidden && mViewVisibility == View.VISIBLE && !mRootToken.hidden) || mWinAnimator.mAnimation != null || animating); @@ -1143,7 +1143,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { return (mHasSurface || (!mRelayoutCalled && mViewVisibility == View.VISIBLE)) && mPolicyVisibility && !mAttachedHidden && (atoken == null || !atoken.hiddenRequested) - && !mExiting && !mDestroying; + && !mAnimatingExit && !mDestroying; } /** @@ -1237,7 +1237,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { || (atoken == null && mRootToken.hidden) || (atoken != null && (atoken.hiddenRequested || atoken.hidden)) || mAttachedHidden - || (mExiting && !isAnimatingLw()) + || (mAnimatingExit && !isAnimatingLw()) || mDestroying; } @@ -1283,7 +1283,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { */ boolean hasMoved() { return mHasSurface && (mContentChanged || mMovedByResize) - && !mExiting && !mWinAnimator.mLastHidden && mService.okToDisplay() + && !mAnimatingExit && !mWinAnimator.mLastHidden && mService.okToDisplay() && (mFrame.top != mLastFrame.top || mFrame.left != mLastFrame.left) && (mAttachedWindow == null || !mAttachedWindow.hasMoved()); } @@ -1438,11 +1438,11 @@ final class WindowState implements WindowManagerPolicy.WindowState { return; } - if (!mExiting && mAppDied) { + if (!mAnimatingExit && mAppDied) { // If app died visible, apply a dim over the window to indicate that it's inactive mDisplayContent.mDimLayerController.applyDimAbove(getDimLayerUser(), mWinAnimator); } else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0 - && mDisplayContent != null && !mExiting && isDisplayedLw()) { + && mDisplayContent != null && !mAnimatingExit && isDisplayedLw()) { mDisplayContent.mDimLayerController.applyDimBehind(getDimLayerUser(), mWinAnimator); } } @@ -1467,7 +1467,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { win.mAnimateReplacingWindow = false; win.mReplacingRemoveRequested = false; win.mReplacingWindow = null; - if (win.mExiting) { + if (win.mAnimatingExit) { mService.removeWindowInnerLocked(win); } } @@ -1810,7 +1810,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { } boolean isClosing() { - return mExiting || (mService.mClosingApps.contains(mAppToken)); + return mAnimatingExit || (mService.mClosingApps.contains(mAppToken)); } boolean isAnimatingWithSavedSurface() { @@ -2341,8 +2341,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { } pw.print(prefix); pw.print(mWinAnimator); pw.println(":"); mWinAnimator.dump(pw, prefix + " ", dumpAll); - if (mExiting || mRemoveOnExit || mDestroying || mRemoved) { - pw.print(prefix); pw.print("mExiting="); pw.print(mExiting); + if (mAnimatingExit || mRemoveOnExit || mDestroying || mRemoved) { + pw.print(prefix); pw.print("mAnimatingExit="); pw.print(mAnimatingExit); pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit); pw.print(" mDestroying="); pw.print(mDestroying); pw.print(" mRemoved="); pw.println(mRemoved); @@ -2403,12 +2403,12 @@ final class WindowState implements WindowManagerPolicy.WindowState { @Override public String toString() { final CharSequence title = getWindowTag(); - if (mStringNameCache == null || mLastTitle != title || mWasExiting != mExiting) { + if (mStringNameCache == null || mLastTitle != title || mWasExiting != mAnimatingExit) { mLastTitle = title; - mWasExiting = mExiting; + mWasExiting = mAnimatingExit; mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this)) + " u" + UserHandle.getUserId(mSession.mUid) - + " " + mLastTitle + (mExiting ? " EXITING}" : "}"); + + " " + mLastTitle + (mAnimatingExit ? " EXITING}" : "}"); } return mStringNameCache; } diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 84a2c092d61d..0828417f4103 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -29,7 +29,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_CROP; -import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS; import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC; import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS; @@ -375,7 +374,7 @@ class WindowStateAnimator { // Done animating, clean up. if (DEBUG_ANIM) Slog.v( - TAG, "Animation done in " + this + ": exiting=" + mWin.mExiting + TAG, "Animation done in " + this + ": exiting=" + mWin.mAnimatingExit + ", reportedVisible=" + (mWin.mAppToken != null ? mWin.mAppToken.reportedVisible : false)); @@ -430,7 +429,7 @@ class WindowStateAnimator { void finishExit() { if (DEBUG_ANIM) Slog.v( TAG, "finishExit in " + this - + ": exiting=" + mWin.mExiting + + ": exiting=" + mWin.mAnimatingExit + " remove=" + mWin.mRemoveOnExit + " windowAnimating=" + isWindowAnimating()); @@ -460,7 +459,7 @@ class WindowStateAnimator { } } - if (!mWin.mExiting) { + if (!mWin.mAnimatingExit) { return; } @@ -475,27 +474,27 @@ class WindowStateAnimator { mWin.mDestroying = true; + final boolean hasSurface = hasSurface(); + if (hasSurface) { + hide("finishExit"); + } + // If we have an app token, we ask it to destroy the surface for us, // so that it can take care to ensure the activity has actually stopped // and the surface is not still in use. Otherwise we add the service to // mDestroySurface and allow it to be processed in our next transaction. if (mWin.mAppToken != null) { - if (hasSurface()) { - hide("finishExit"); - } mWin.mAppToken.destroySurfaces(); } else { - if (hasSurface()) { + if (hasSurface) { mService.mDestroySurface.add(mWin); - hide("finishExit"); } - mWin.mExiting = false; if (mWin.mRemoveOnExit) { mService.mPendingRemove.add(mWin); mWin.mRemoveOnExit = false; } } - + mWin.mAnimatingExit = false; mWallpaperControllerLocked.hideWallpapers(mWin); } diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index 4e1b644df368..f705df8ea394 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -7,7 +7,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMA import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_DREAM; import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; -import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION; import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; @@ -676,8 +675,10 @@ class WindowSurfacePlacer { // currently animating... let's do something. final int left = w.mFrame.left; final int top = w.mFrame.top; + final boolean adjustedForMinimizedDockedStack = w.getTask() != null && + w.getTask().mStack.isAdjustedForMinimizedDockedStack(); if ((w.mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0 - && !w.isDragResizing()) { + && !w.isDragResizing() && !adjustedForMinimizedDockedStack) { winAnimator.setMoveAnimation(left, top); } @@ -751,7 +752,7 @@ class WindowSurfacePlacer { } if ((w.isOnScreenIgnoringKeyguard() || winAnimator.mAttrType == TYPE_BASE_APPLICATION) - && !w.mExiting && !w.mDestroying) { + && !w.mAnimatingExit && !w.mDestroying) { if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() @@ -1099,6 +1100,7 @@ class WindowSurfacePlacer { processApplicationsAnimatingInPlace(transit); + mTmpLayerAndToken.token = null; handleClosingApps(transit, animLp, voiceInteraction, mTmpLayerAndToken); final AppWindowToken topClosingApp = mTmpLayerAndToken.token; final int topClosingLayer = mTmpLayerAndToken.layer; @@ -1111,7 +1113,8 @@ class WindowSurfacePlacer { final AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null : topClosingApp.mAppAnimator; - mService.mAppTransition.goodToGo(openingAppAnimator, closingAppAnimator); + mService.mAppTransition.goodToGo(openingAppAnimator, closingAppAnimator, + mService.mOpeningApps, mService.mClosingApps); mService.mAppTransition.postAnimationCallback(); mService.mAppTransition.clear(); @@ -1181,17 +1184,17 @@ class WindowSurfacePlacer { int layer = -1; for (int j = 0; j < wtoken.windows.size(); j++) { final WindowState win = wtoken.windows.get(j); - // Clearing the mExiting flag before entering animation. It will be set to true + // Clearing the mAnimatingExit flag before entering animation. It will be set to true // if app window is removed, or window relayout to invisible. We don't want to // clear it out for windows that get replaced, because the animation depends on // the flag to remove the replaced window. // - // We also don't clear the mExiting flag for windows which have the + // We also don't clear the mAnimatingExit flag for windows which have the // mRemoveOnExit flag. This indicates an explicit remove request has been issued // by the client. We should let animation proceed and not clear this flag or // they won't eventually be removed by WindowStateAnimator#finishExit. if (!win.mWillReplaceWindow && !win.mRemoveOnExit) { - win.mExiting = false; + win.mAnimatingExit = false; } if (win.mWinAnimator.mAnimLayer > layer) { layer = win.mWinAnimator.mAnimLayer; @@ -1230,7 +1233,7 @@ class WindowSurfacePlacer { wtoken.deferClearAllDrawn = false; // Ensure that apps that are mid-starting are also scheduled to have their // starting windows removed after the animation is complete - if (wtoken.startingWindow != null && !wtoken.startingWindow.mExiting) { + if (wtoken.startingWindow != null && !wtoken.startingWindow.mAnimatingExit) { mService.scheduleRemoveStartingWindowLocked(wtoken); } mService.mAnimator.mAppWindowAnimating |= appAnimator.isAnimating(); diff --git a/core/java/android/view/animation/ClipRectLRAnimation.java b/services/core/java/com/android/server/wm/animation/ClipRectLRAnimation.java index 8993cd3a2753..0db4c70e2761 100644 --- a/core/java/android/view/animation/ClipRectLRAnimation.java +++ b/services/core/java/com/android/server/wm/animation/ClipRectLRAnimation.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The Android Open Source Project + * Copyright (C) 2016 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. @@ -11,12 +11,14 @@ * 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. + * limitations under the License */ -package android.view.animation; +package com.android.server.wm.animation; import android.graphics.Rect; +import android.view.animation.ClipRectAnimation; +import android.view.animation.Transformation; /** * Special case of ClipRectAnimation that animates only the left/right diff --git a/services/core/java/com/android/server/wm/animation/ClipRectTBAnimation.java b/services/core/java/com/android/server/wm/animation/ClipRectTBAnimation.java new file mode 100644 index 000000000000..1f5b1a3f9660 --- /dev/null +++ b/services/core/java/com/android/server/wm/animation/ClipRectTBAnimation.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2016 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.wm.animation; + +import android.graphics.Rect; +import android.view.animation.ClipRectAnimation; +import android.view.animation.Interpolator; +import android.view.animation.Transformation; +import android.view.animation.TranslateAnimation; + +/** + * Special case of ClipRectAnimation that animates only the top/bottom + * dimensions of the clip, picking up the other dimensions from whatever is + * set on the transform already. In addition to that, information about a vertical translation + * animation can be specified so this animation simulates as the clip would be applied after instead + * of before applying the translation. + */ +public class ClipRectTBAnimation extends ClipRectAnimation { + + private final int mFromTranslateY; + private final int mToTranslateY; + private final Interpolator mTranslateInterpolator; + private float mNormalizedTime; + + /** + * Constructor. Passes in 0 for Left/Right parameters of ClipRectAnimation + */ + public ClipRectTBAnimation(int fromT, int fromB, int toT, int toB, + int fromTranslateY, int toTranslateY, Interpolator translateInterpolator) { + super(0, fromT, 0, fromB, 0, toT, 0, toB); + mFromTranslateY = fromTranslateY; + mToTranslateY = toTranslateY; + mTranslateInterpolator = translateInterpolator; + } + + @Override + public boolean getTransformation(long currentTime, Transformation outTransformation) { + + // Hack: Because translation animation has a different interpolator, we need to duplicate + // code from Animation here and use it to calculate/store the uninterpolated normalized + // time. + final long startOffset = getStartOffset(); + final long duration = getDuration(); + float normalizedTime; + if (duration != 0) { + normalizedTime = ((float) (currentTime - (getStartTime() + startOffset))) / + (float) duration; + } else { + // time is a step-change with a zero duration + normalizedTime = currentTime < getStartTime() ? 0.0f : 1.0f; + } + mNormalizedTime = normalizedTime; + return super.getTransformation(currentTime, outTransformation); + } + + /** + * Calculates and sets clip rect on given transformation. It uses existing values + * on the Transformation for Left/Right clip parameters. + */ + @Override + protected void applyTransformation(float it, Transformation tr) { + float translationT = mTranslateInterpolator.getInterpolation(mNormalizedTime); + int translation = + (int) (mFromTranslateY + (mToTranslateY - mFromTranslateY) * translationT); + Rect oldClipRect = tr.getClipRect(); + tr.setClipRect(oldClipRect.left, + mFromRect.top - translation + (int) ((mToRect.top - mFromRect.top) * it), + oldClipRect.right, + mFromRect.bottom - translation + (int) ((mToRect.bottom - mFromRect.bottom) * it)); + } + +} diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk index bb571c3d0631..5e5c6d9321e3 100644 --- a/services/core/jni/Android.mk +++ b/services/core/jni/Android.mk @@ -17,6 +17,7 @@ LOCAL_SRC_FILES += \ $(LOCAL_REL_DIR)/com_android_server_AssetAtlasService.cpp \ $(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \ $(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \ + $(LOCAL_REL_DIR)/com_android_server_HardwarePropertiesManagerService.cpp \ $(LOCAL_REL_DIR)/com_android_server_hdmi_HdmiCecController.cpp \ $(LOCAL_REL_DIR)/com_android_server_input_InputApplicationHandle.cpp \ $(LOCAL_REL_DIR)/com_android_server_input_InputManagerService.cpp \ diff --git a/core/jni/android_os_HardwarePropertiesManager.cpp b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp index dc1ba48097b8..214d9882c499 100644 --- a/core/jni/android_os_HardwarePropertiesManager.cpp +++ b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define LOG_TAG "HardwarePropertiesManager-JNI" +#define LOG_TAG "HardwarePropertiesManagerService-JNI" #include "JNIHelp.h" #include "jni.h" @@ -137,7 +137,7 @@ static jobjectArray nativeGetCpuUsages(JNIEnv *env, jclass /* clazz */) { // ---------------------------------------------------------------------------- -static const JNINativeMethod gHardwarePropertiesManagerMethods[] = { +static const JNINativeMethod gHardwarePropertiesManagerServiceMethods[] = { /* name, signature, funcPtr */ { "nativeInit", "()V", (void*) nativeInit }, @@ -149,11 +149,11 @@ static const JNINativeMethod gHardwarePropertiesManagerMethods[] = { (void*) nativeGetCpuUsages } }; -int register_android_os_HardwarePropertiesManager(JNIEnv* env) { +int register_android_server_HardwarePropertiesManagerService(JNIEnv* env) { gHardwarePropertiesModule = nullptr; - int res = jniRegisterNativeMethods(env, "android/os/HardwarePropertiesManager", - gHardwarePropertiesManagerMethods, - NELEM(gHardwarePropertiesManagerMethods)); + int res = jniRegisterNativeMethods(env, "com/android/server/HardwarePropertiesManagerService", + gHardwarePropertiesManagerServiceMethods, + NELEM(gHardwarePropertiesManagerServiceMethods)); jclass clazz = env->FindClass("android/os/CpuUsageInfo"); gCpuUsageInfoClassInfo.clazz = MakeGlobalRefOrDie(env, clazz); gCpuUsageInfoClassInfo.initMethod = GetMethodIDOrDie(env, gCpuUsageInfoClassInfo.clazz, diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp index cdd551936511..e39445af78d3 100644 --- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp @@ -42,7 +42,7 @@ static jmethodID method_reportSvStatus; static jmethodID method_reportAGpsStatus; static jmethodID method_reportNmea; static jmethodID method_setEngineCapabilities; -static jmethodID method_setGpsYearOfHardware; +static jmethodID method_setGnssYearOfHardware; static jmethodID method_xtraDownloadRequest; static jmethodID method_reportNiNotification; static jmethodID method_requestRefLocation; @@ -133,11 +133,10 @@ static void sv_status_callback(GpsSvStatus* sv_status) for (size_t i = 0; i < sGnssSvListSize; i++) { GnssSvInfo& info = sGnssSvList[i]; info.svid = sv_status->sv_list[i].prn; - // TODO: implement the correct logic to derive the constellation type - // based on PRN ranges. if (info.svid >=1 && info.svid <= 32) { info.constellation = GNSS_CONSTELLATION_GPS; } else { + ALOGD("Unknown constellation type with Svid = %d.", info.svid); info.constellation = GNSS_CONSTELLATION_UNKNOWN; } info.snr = sv_status->sv_list[i].snr; @@ -198,10 +197,10 @@ static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length) checkAndClearExceptionFromCallback(env, __FUNCTION__); } -static void set_system_info_callback(const GpsSystemInfo* info) { +static void set_system_info_callback(const GnssSystemInfo* info) { ALOGD("set_system_info_callback: year_of_hw=%d\n", info->year_of_hw); JNIEnv* env = AndroidRuntime::getJNIEnv(); - env->CallVoidMethod(mCallbacksObj, method_setGpsYearOfHardware, + env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware, info->year_of_hw); checkAndClearExceptionFromCallback(env, __FUNCTION__); } @@ -536,7 +535,7 @@ static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V"); method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V"); method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V"); - method_setGpsYearOfHardware = env->GetMethodID(clazz, "setGpsYearOfHardware", "(I)V"); + method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V"); method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V"); method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification", "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V"); @@ -1074,7 +1073,9 @@ const char *const JavaMethodHelper<int16_t>::signature_ = "(S)V"; template<> const char *const JavaMethodHelper<uint16_t>::signature_ = "(S)V"; template<> -const char *const JavaMethodHelper<int>::signature_ = "(I)V"; +const char *const JavaMethodHelper<int32_t>::signature_ = "(I)V"; +template<> +const char *const JavaMethodHelper<uint32_t>::signature_ = "(I)V"; template<> const char *const JavaMethodHelper<int64_t>::signature_ = "(J)V"; template<> @@ -1092,36 +1093,22 @@ static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) { JavaObject object(env, "android/location/GnssClock"); GpsClockFlags flags = clock->flags; - SET_IF(GPS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second); + SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second); SET(Type, clock->type); SET(TimeInNs, clock->time_ns); - SET_IF(GPS_CLOCK_HAS_TIME_UNCERTAINTY, + SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY, TimeUncertaintyInNs, clock->time_uncertainty_ns); - SET_IF(GPS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns); - SET_IF(GPS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns); - SET_IF(GPS_CLOCK_HAS_BIAS_UNCERTAINTY, + SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns); + SET_IF(GNSS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns); + SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY, BiasUncertaintyInNs, clock->bias_uncertainty_ns); - SET_IF(GPS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps); - SET_IF(GPS_CLOCK_HAS_DRIFT_UNCERTAINTY, + SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps); + SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY, DriftUncertaintyInNsPerSec, clock->drift_uncertainty_nsps); - /* - if (flags & GPS_CLOCK_TYPE_LOCAL_HW_TIME) { - if (size == sizeof(GnssClock)) { - jmethodID setterMethod = - env->GetMethodID(gpsClockClass, - "setTimeOfLastHwClockDiscontinuityInNs", - longSignature); - env->CallVoidMethod(gpsClockObject, - setterMethod, - reinterpret_cast<GnssClock*>(clock)->time_of_last_hw_clock_discontinuity_ns); - } - } - */ - return object.get(); } @@ -1129,25 +1116,23 @@ static jobject translate_gnss_clock(JNIEnv* env, GnssClock* clock) { JavaObject object(env, "android/location/GnssClock"); GpsClockFlags flags = clock->flags; - SET_IF(GPS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second); - SET(Type, clock->type); + SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second); + SET(Type, static_cast<uint8_t>(GPS_CLOCK_TYPE_LOCAL_HW_TIME)); SET(TimeInNs, clock->time_ns); - SET_IF(GPS_CLOCK_HAS_TIME_UNCERTAINTY, + SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY, TimeUncertaintyInNs, clock->time_uncertainty_ns); - SET_IF(GPS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns); - SET_IF(GPS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns); - SET_IF(GPS_CLOCK_HAS_BIAS_UNCERTAINTY, + SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns); + SET_IF(GNSS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns); + SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY, BiasUncertaintyInNs, clock->bias_uncertainty_ns); - SET_IF(GPS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps); - SET_IF(GPS_CLOCK_HAS_DRIFT_UNCERTAINTY, + SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps); + SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY, DriftUncertaintyInNsPerSec, clock->drift_uncertainty_nsps); - SET_IF(GPS_CLOCK_TYPE_LOCAL_HW_TIME, - TimeOfLastHwClockDiscontinuityInNs, - clock->time_of_last_hw_clock_discontinuity_ns); + SET(HardwareClockDiscontinuityCount, clock->hw_clock_discontinuity_count); return object.get(); } @@ -1156,12 +1141,18 @@ static jobject translate_gps_measurement(JNIEnv* env, GpsMeasurement* measurement) { JavaObject object(env, "android/location/GnssMeasurement"); GpsMeasurementFlags flags = measurement->flags; - SET(Svid, static_cast<int16_t>(measurement->prn)); + if (measurement->prn >= 1 || measurement->prn <= 32) { + SET(ConstellationType, static_cast<uint8_t>(GNSS_CONSTELLATION_GPS)); + } else { + ALOGD("Unknown constellation type with Svid = %d.", measurement->prn); + SET(ConstellationType, + static_cast<uint8_t>(GNSS_CONSTELLATION_UNKNOWN)); + } SET(TimeOffsetInNs, measurement->time_offset_ns); SET(State, measurement->state); - SET(ReceivedGpsTowInNs, measurement->received_gps_tow_ns); - SET(ReceivedGpsTowUncertaintyInNs, + SET(ReceivedSvTimeInNs, measurement->received_gps_tow_ns); + SET(ReceivedSvTimeUncertaintyInNs, measurement->received_gps_tow_uncertainty_ns); SET(Cn0InDbHz, measurement->c_n0_dbhz); SET(PseudorangeRateInMetersPerSec, measurement->pseudorange_rate_mps); @@ -1171,57 +1162,57 @@ static jobject translate_gps_measurement(JNIEnv* env, SET(AccumulatedDeltaRangeInMeters, measurement->accumulated_delta_range_m); SET(AccumulatedDeltaRangeUncertaintyInMeters, measurement->accumulated_delta_range_uncertainty_m); - SET_IF(GPS_MEASUREMENT_HAS_PSEUDORANGE, + SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE, PseudorangeInMeters, measurement->pseudorange_m); - SET_IF(GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY, + SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY, PseudorangeUncertaintyInMeters, measurement->pseudorange_uncertainty_m); - SET_IF(GPS_MEASUREMENT_HAS_CODE_PHASE, + SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE, CodePhaseInChips, measurement->code_phase_chips); - SET_IF(GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY, + SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY, CodePhaseUncertaintyInChips, measurement->code_phase_uncertainty_chips); - SET_IF(GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY, + SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY, CarrierFrequencyInHz, measurement->carrier_frequency_hz); - SET_IF(GPS_MEASUREMENT_HAS_CARRIER_CYCLES, + SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES, CarrierCycles, measurement->carrier_cycles); - SET_IF(GPS_MEASUREMENT_HAS_CARRIER_PHASE, + SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE, CarrierPhase, measurement->carrier_phase); - SET_IF(GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY, + SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY, CarrierPhaseUncertainty, measurement->carrier_phase_uncertainty); SET(LossOfLock, measurement->loss_of_lock); - SET_IF(GPS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number); - SET_IF(GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT, + SET_IF(GNSS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number); + SET_IF(GNSS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT, TimeFromLastBitInMs, measurement->time_from_last_bit_ms); - SET_IF(GPS_MEASUREMENT_HAS_DOPPLER_SHIFT, + SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT, DopplerShiftInHz, measurement->doppler_shift_hz); - SET_IF(GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY, + SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY, DopplerShiftUncertaintyInHz, measurement->doppler_shift_uncertainty_hz); SET(MultipathIndicator, measurement->multipath_indicator); - SET_IF(GPS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db); - SET_IF(GPS_MEASUREMENT_HAS_ELEVATION, + SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db); + SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION, ElevationInDeg, measurement->elevation_deg); - SET_IF(GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY, + SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY, ElevationUncertaintyInDeg, measurement->elevation_uncertainty_deg); - SET_IF(GPS_MEASUREMENT_HAS_AZIMUTH, + SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH, AzimuthInDeg, measurement->azimuth_deg); - SET_IF(GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY, + SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY, AzimuthUncertaintyInDeg, measurement->azimuth_uncertainty_deg); SET(UsedInFix, - (flags & GPS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix); + (flags & GNSS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix); return object.get(); } @@ -1232,11 +1223,12 @@ static jobject translate_gnss_measurement(JNIEnv* env, GpsMeasurementFlags flags = measurement->flags; SET(Svid, measurement->svid); + SET(ConstellationType, measurement->constellation); SET(TimeOffsetInNs, measurement->time_offset_ns); SET(State, measurement->state); - SET(ReceivedGpsTowInNs, measurement->received_gps_tow_ns); - SET(ReceivedGpsTowUncertaintyInNs, - measurement->received_gps_tow_uncertainty_ns); + SET(ReceivedSvTimeInNs, measurement->received_sv_time_in_ns); + SET(ReceivedSvTimeUncertaintyInNs, + measurement->received_sv_time_uncertainty_in_ns); SET(Cn0InDbHz, measurement->c_n0_dbhz); SET(PseudorangeRateInMetersPerSec, measurement->pseudorange_rate_mps); SET(PseudorangeRateUncertaintyInMetersPerSec, @@ -1245,62 +1237,56 @@ static jobject translate_gnss_measurement(JNIEnv* env, SET(AccumulatedDeltaRangeInMeters, measurement->accumulated_delta_range_m); SET(AccumulatedDeltaRangeUncertaintyInMeters, measurement->accumulated_delta_range_uncertainty_m); - SET_IF(GPS_MEASUREMENT_HAS_PSEUDORANGE, + SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE, PseudorangeInMeters, measurement->pseudorange_m); - SET_IF(GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY, + SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY, PseudorangeUncertaintyInMeters, measurement->pseudorange_uncertainty_m); - SET_IF(GPS_MEASUREMENT_HAS_CODE_PHASE, + SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE, CodePhaseInChips, measurement->code_phase_chips); - SET_IF(GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY, + SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY, CodePhaseUncertaintyInChips, measurement->code_phase_uncertainty_chips); - SET_IF(GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY, + SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY, CarrierFrequencyInHz, measurement->carrier_frequency_hz); - SET_IF(GPS_MEASUREMENT_HAS_CARRIER_CYCLES, + SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES, CarrierCycles, measurement->carrier_cycles); - SET_IF(GPS_MEASUREMENT_HAS_CARRIER_PHASE, + SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE, CarrierPhase, measurement->carrier_phase); - SET_IF(GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY, + SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY, CarrierPhaseUncertainty, measurement->carrier_phase_uncertainty); - SET(LossOfLock, measurement->loss_of_lock); - SET_IF(GPS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number); - SET_IF(GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT, + SET_IF(GNSS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number); + SET_IF(GNSS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT, TimeFromLastBitInMs, measurement->time_from_last_bit_ms); - SET_IF(GPS_MEASUREMENT_HAS_DOPPLER_SHIFT, + SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT, DopplerShiftInHz, measurement->doppler_shift_hz); - SET_IF(GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY, + SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY, DopplerShiftUncertaintyInHz, measurement->doppler_shift_uncertainty_hz); SET(MultipathIndicator, measurement->multipath_indicator); - SET_IF(GPS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db); - SET_IF(GPS_MEASUREMENT_HAS_ELEVATION, + SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db); + SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION, ElevationInDeg, measurement->elevation_deg); - SET_IF(GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY, + SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY, ElevationUncertaintyInDeg, measurement->elevation_uncertainty_deg); - SET_IF(GPS_MEASUREMENT_HAS_AZIMUTH, + SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH, AzimuthInDeg, measurement->azimuth_deg); - SET_IF(GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY, + SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY, AzimuthUncertaintyInDeg, measurement->azimuth_uncertainty_deg); SET(UsedInFix, - (flags & GPS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix); - - SET(PseudorangeRateCarrierInMetersPerSec, - measurement->pseudorange_rate_carrier_mps); - SET(PseudorangeRateCarrierUncertaintyInMetersPerSec, - measurement->pseudorange_rate_carrier_uncertainty_mps); + (flags & GNSS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix); return object.get(); } @@ -1480,8 +1466,18 @@ static jobject translate_gps_navigation_message(JNIEnv* env, GpsNavigationMessag return NULL; } JavaObject object(env, "android/location/GnssNavigationMessage"); - SET(Type, message->type); SET(Svid, static_cast<int16_t>(message->prn)); + if (message->prn >=1 && message->prn <= 32) { + SET(ConstellationType, static_cast<uint8_t>(GNSS_CONSTELLATION_GPS)); + // Legacy driver doesn't set the higher byte to constellation type + // correctly. Set the higher byte to 'GPS'. + SET(Type, static_cast<int16_t>(message->type | 0x0100)); + } else { + ALOGD("Unknown constellation type with Svid = %d.", message->prn); + SET(ConstellationType, + static_cast<uint8_t>(GNSS_CONSTELLATION_UNKNOWN)); + SET(Type, static_cast<int16_t>(GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN)); + } SET(MessageId, message->message_id); SET(SubmessageId, message->submessage_id); object.callSetter("setData", data, dataLength); diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index ef5c56c1bcfa..be99673a4cb5 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -44,6 +44,7 @@ int register_android_server_hdmi_HdmiCecController(JNIEnv* env); int register_android_server_tv_TvInputHal(JNIEnv* env); int register_android_server_PersistentDataBlockService(JNIEnv* env); int register_android_server_Watchdog(JNIEnv* env); +int register_android_server_HardwarePropertiesManagerService(JNIEnv* env); }; using namespace android; @@ -83,6 +84,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_tv_TvInputHal(env); register_android_server_PersistentDataBlockService(env); register_android_server_Watchdog(env); + register_android_server_HardwarePropertiesManagerService(env); return JNI_VERSION_1_4; diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index ac972a9c6863..c8545732864b 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -488,6 +488,7 @@ public final class SystemServer { MmsServiceBroker mmsService = null; EntropyMixer entropyMixer = null; VrManagerService vrManagerService = null; + HardwarePropertiesManagerService hardwarePropertiesService = null; boolean disableStorage = SystemProperties.getBoolean("config.disable_storage", false); boolean disableBluetooth = SystemProperties.getBoolean("config.disable_bluetooth", false); @@ -962,6 +963,17 @@ public final class SystemServer { Slog.e(TAG, "Failure starting SerialService", e); } Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); + + Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, + "StartHardwarePropertiesManagerService"); + try { + hardwarePropertiesService = new HardwarePropertiesManagerService(context); + ServiceManager.addService(Context.HARDWARE_PROPERTIES_SERVICE, + hardwarePropertiesService); + } catch (Throwable e) { + Slog.e(TAG, "Failure starting HardwarePropertiesManagerService", e); + } + Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } mSystemServiceManager.startService(TwilightService.class); diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java index 61f2c8afcf58..2a90c60656ab 100644 --- a/services/net/java/android/net/ip/IpManager.java +++ b/services/net/java/android/net/ip/IpManager.java @@ -24,6 +24,7 @@ import android.net.InterfaceConfiguration; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.LinkProperties.ProvisioningChange; +import android.net.ProxyInfo; import android.net.RouteInfo; import android.net.StaticIpConfiguration; import android.net.dhcp.DhcpClient; @@ -31,6 +32,7 @@ import android.os.INetworkManagementService; import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; +import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; @@ -64,6 +66,9 @@ public class IpManager extends StateMachine { private static final boolean DBG = true; private static final boolean VDBG = false; + private static final boolean NO_CALLBACKS = false; + private static final boolean SEND_CALLBACKS = true; + // For message logging. private static final Class[] sMessageClasses = { IpManager.class, DhcpClient.class }; private static final SparseArray<String> sWhatToString = @@ -104,6 +109,35 @@ public class IpManager extends StateMachine { public void onQuit() {} } + public static class WaitForProvisioningCallback extends Callback { + private LinkProperties mCallbackLinkProperties; + + public LinkProperties waitForProvisioning() { + synchronized (this) { + try { + wait(); + } catch (InterruptedException e) {} + return mCallbackLinkProperties; + } + } + + @Override + public void onProvisioningSuccess(LinkProperties newLp) { + synchronized (this) { + mCallbackLinkProperties = newLp; + notify(); + } + } + + @Override + public void onProvisioningFailure(LinkProperties newLp) { + synchronized (this) { + mCallbackLinkProperties = null; + notify(); + } + } + } + /** * This class encapsulates parameters to be passed to * IpManager#startProvisioning(). A defensive copy is made by IpManager @@ -168,6 +202,8 @@ public class IpManager extends StateMachine { private static final int EVENT_PRE_DHCP_ACTION_COMPLETE = 4; // Sent by NetlinkTracker to communicate netlink events. private static final int EVENT_NETLINK_LINKPROPERTIES_CHANGED = 5; + private static final int CMD_UPDATE_TCP_BUFFER_SIZES = 6; + private static final int CMD_UPDATE_HTTP_PROXY = 7; private static final int MAX_LOG_RECORDS = 1000; @@ -189,10 +225,12 @@ public class IpManager extends StateMachine { /** * Non-final member variables accessed only from within our StateMachine. */ + private ProvisioningConfiguration mConfiguration; private IpReachabilityMonitor mIpReachabilityMonitor; private DhcpClient mDhcpClient; private DhcpResults mDhcpResults; - private ProvisioningConfiguration mConfiguration; + private String mTcpBufferSizes; + private ProxyInfo mHttpProxy; /** * Member variables accessed both from within the StateMachine thread @@ -301,6 +339,26 @@ public class IpManager extends StateMachine { sendMessage(EVENT_PRE_DHCP_ACTION_COMPLETE); } + /** + * Set the TCP buffer sizes to use. + * + * This may be called, repeatedly, at any time before or after a call to + * #startProvisioning(). The setting is cleared upon calling #stop(). + */ + public void setTcpBufferSizes(String tcpBufferSizes) { + sendMessage(CMD_UPDATE_TCP_BUFFER_SIZES, tcpBufferSizes); + } + + /** + * Set the HTTP Proxy configuration to use. + * + * This may be called, repeatedly, at any time before or after a call to + * #startProvisioning(). The setting is cleared upon calling #stop(). + */ + public void setHttpProxy(ProxyInfo proxyInfo) { + sendMessage(CMD_UPDATE_HTTP_PROXY, proxyInfo); + } + public LinkProperties getLinkProperties() { synchronized (mLock) { return new LinkProperties(mLinkProperties); @@ -344,8 +402,10 @@ public class IpManager extends StateMachine { // assigned to the interface, etc. private void resetLinkProperties() { mNetlinkTracker.clearLinkProperties(); - mDhcpResults = null; mConfiguration = null; + mDhcpResults = null; + mTcpBufferSizes = ""; + mHttpProxy = null; synchronized (mLock) { mLinkProperties = new LinkProperties(); @@ -502,13 +562,33 @@ public class IpManager extends StateMachine { newLp.setDomains(mDhcpResults.domains); } + // [4] Add in TCP buffer sizes and HTTP Proxy config, if available. + if (!TextUtils.isEmpty(mTcpBufferSizes)) { + newLp.setTcpBufferSizes(mTcpBufferSizes); + } + if (mHttpProxy != null) { + newLp.setHttpProxy(mHttpProxy); + } + if (VDBG) { Log.d(mTag, "newLp{" + newLp + "}"); } - return newLp; } + // Returns false if we have lost provisioning, true otherwise. + private boolean handleLinkPropertiesUpdate(boolean sendCallbacks) { + final LinkProperties newLp = assembleLinkProperties(); + if (linkPropertiesUnchanged(newLp)) { + return true; + } + final ProvisioningChange delta = setLinkProperties(newLp); + if (sendCallbacks) { + dispatchCallback(delta, newLp); + } + return (delta != ProvisioningChange.LOST_PROVISIONING); + } + private void clearIPv4Address() { try { final InterfaceConfiguration ifcg = new InterfaceConfiguration(); @@ -587,7 +667,17 @@ public class IpManager extends StateMachine { break; case EVENT_NETLINK_LINKPROPERTIES_CHANGED: - setLinkProperties(assembleLinkProperties()); + handleLinkPropertiesUpdate(NO_CALLBACKS); + break; + + case CMD_UPDATE_TCP_BUFFER_SIZES: + mTcpBufferSizes = (String) msg.obj; + handleLinkPropertiesUpdate(NO_CALLBACKS); + break; + + case CMD_UPDATE_HTTP_PROXY: + mHttpProxy = (ProxyInfo) msg.obj; + handleLinkPropertiesUpdate(NO_CALLBACKS); break; case DhcpClient.CMD_ON_QUIT: @@ -718,18 +808,23 @@ public class IpManager extends StateMachine { } break; - case EVENT_NETLINK_LINKPROPERTIES_CHANGED: { - final LinkProperties newLp = assembleLinkProperties(); - if (linkPropertiesUnchanged(newLp)) { - break; - } - final ProvisioningChange delta = setLinkProperties(newLp); - dispatchCallback(delta, newLp); - if (delta == ProvisioningChange.LOST_PROVISIONING) { + case EVENT_NETLINK_LINKPROPERTIES_CHANGED: + if (!handleLinkPropertiesUpdate(SEND_CALLBACKS)) { transitionTo(mStoppedState); } break; - } + + case CMD_UPDATE_TCP_BUFFER_SIZES: + mTcpBufferSizes = (String) msg.obj; + // This cannot possibly change provisioning state. + handleLinkPropertiesUpdate(SEND_CALLBACKS); + break; + + case CMD_UPDATE_HTTP_PROXY: + mHttpProxy = (ProxyInfo) msg.obj; + // This cannot possibly change provisioning state. + handleLinkPropertiesUpdate(SEND_CALLBACKS); + break; case DhcpClient.CMD_PRE_DHCP_ACTION: if (VDBG) { Log.d(mTag, "onPreDhcpAction()"); } diff --git a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java index 577c3a1af195..c7860368289a 100644 --- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java @@ -58,7 +58,7 @@ public class JobStoreTest extends AndroidTestCase { .setMinimumLatency(runFromMillis) .setPersisted(true) .build(); - final JobStatus ts = new JobStatus(task, SOME_UID, null, -1); + final JobStatus ts = JobStatus.createFromJobInfo(task, SOME_UID, null, -1); mTaskStoreUnderTest.add(ts); Thread.sleep(IO_WAIT); // Manually load tasks from xml file. @@ -91,8 +91,8 @@ public class JobStoreTest extends AndroidTestCase { .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) .setPersisted(true) .build(); - final JobStatus taskStatus1 = new JobStatus(task1, SOME_UID, null, -1); - final JobStatus taskStatus2 = new JobStatus(task2, SOME_UID, null, -1); + final JobStatus taskStatus1 = JobStatus.createFromJobInfo(task1, SOME_UID, null, -1); + final JobStatus taskStatus2 = JobStatus.createFromJobInfo(task2, SOME_UID, null, -1); mTaskStoreUnderTest.add(taskStatus1); mTaskStoreUnderTest.add(taskStatus2); Thread.sleep(IO_WAIT); @@ -140,7 +140,7 @@ public class JobStoreTest extends AndroidTestCase { extras.putInt("into", 3); b.setExtras(extras); final JobInfo task = b.build(); - JobStatus taskStatus = new JobStatus(task, SOME_UID, null, -1); + JobStatus taskStatus = JobStatus.createFromJobInfo(task, SOME_UID, null, -1); mTaskStoreUnderTest.add(taskStatus); Thread.sleep(IO_WAIT); @@ -157,7 +157,8 @@ public class JobStoreTest extends AndroidTestCase { .setPeriodic(10000L) .setRequiresCharging(true) .setPersisted(true); - JobStatus taskStatus = new JobStatus(b.build(), SOME_UID, "com.google.android.gms", 0); + JobStatus taskStatus = JobStatus.createFromJobInfo(b.build(), SOME_UID, + "com.google.android.gms", 0); mTaskStoreUnderTest.add(taskStatus); Thread.sleep(IO_WAIT); @@ -178,7 +179,7 @@ public class JobStoreTest extends AndroidTestCase { .setPeriodic(5*60*60*1000, 1*60*60*1000) .setRequiresCharging(true) .setPersisted(true); - JobStatus taskStatus = new JobStatus(b.build(), SOME_UID, null, -1); + JobStatus taskStatus = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1); mTaskStoreUnderTest.add(taskStatus); Thread.sleep(IO_WAIT); @@ -203,7 +204,8 @@ public class JobStoreTest extends AndroidTestCase { SystemClock.elapsedRealtime() + (TWO_HOURS * ONE_HOUR) + TWO_HOURS; // > period+flex final long invalidEarlyRuntimeElapsedMillis = invalidLateRuntimeElapsedMillis - TWO_HOURS; // Early is (late - period). - final JobStatus js = new JobStatus(b.build(), SOME_UID, "somePackage", 0 /* sourceUserId */, + final JobStatus js = new JobStatus(b.build(), SOME_UID, "somePackage", + 0 /* sourceUserId */, invalidEarlyRuntimeElapsedMillis, invalidLateRuntimeElapsedMillis); mTaskStoreUnderTest.add(js); @@ -229,7 +231,7 @@ public class JobStoreTest extends AndroidTestCase { .setOverrideDeadline(5000) .setPriority(42) .setPersisted(true); - final JobStatus js = new JobStatus(b.build(), SOME_UID, null, -1); + final JobStatus js = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1); mTaskStoreUnderTest.add(js); Thread.sleep(IO_WAIT); final ArraySet<JobStatus> jobStatusSet = new ArraySet<JobStatus>(); @@ -245,12 +247,12 @@ public class JobStoreTest extends AndroidTestCase { JobInfo.Builder b = new Builder(42, mComponent) .setOverrideDeadline(10000) .setPersisted(false); - JobStatus jsNonPersisted = new JobStatus(b.build(), SOME_UID, null, -1); + JobStatus jsNonPersisted = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1); mTaskStoreUnderTest.add(jsNonPersisted); b = new Builder(43, mComponent) .setOverrideDeadline(10000) .setPersisted(true); - JobStatus jsPersisted = new JobStatus(b.build(), SOME_UID, null, -1); + JobStatus jsPersisted = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1); mTaskStoreUnderTest.add(jsPersisted); Thread.sleep(IO_WAIT); final ArraySet<JobStatus> jobStatusSet = new ArraySet<JobStatus>(); diff --git a/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java index 31182fcf46ae..f1fe3462432d 100644 --- a/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java +++ b/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java @@ -25,7 +25,6 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import android.app.Notification; -import android.os.Handler; import android.os.UserHandle; import android.service.notification.StatusBarNotification; import android.test.AndroidTestCase; @@ -55,14 +54,13 @@ public class RankingHelperTest extends AndroidTestCase { UserHandle user = UserHandle.ALL; mHelper = new RankingHelper(getContext(), handler, mUsageStats, - new String[] {TopicImportanceExtractor.class.getName()}); + new String[] {ImportanceExtractor.class.getName()}); mNotiGroupGSortA = new Notification.Builder(getContext()) .setContentTitle("A") .setGroup("G") .setSortKey("A") .setWhen(1205) - .setTopic(new Notification.Topic("A", "a")) .build(); mRecordGroupGSortA = new NotificationRecord(getContext(), new StatusBarNotification( "package", "package", 1, null, 0, 0, 0, mNotiGroupGSortA, user)); @@ -72,7 +70,6 @@ public class RankingHelperTest extends AndroidTestCase { .setGroup("G") .setSortKey("B") .setWhen(1200) - .setTopic(new Notification.Topic("A", "a")) .build(); mRecordGroupGSortB = new NotificationRecord(getContext(), new StatusBarNotification( "package", "package", 1, null, 0, 0, 0, mNotiGroupGSortB, user)); @@ -80,7 +77,6 @@ public class RankingHelperTest extends AndroidTestCase { mNotiNoGroup = new Notification.Builder(getContext()) .setContentTitle("C") .setWhen(1201) - .setTopic(new Notification.Topic("C", "c")) .build(); mRecordNoGroup = new NotificationRecord(getContext(), new StatusBarNotification( "package", "package", 1, null, 0, 0, 0, mNotiNoGroup, user)); @@ -88,7 +84,6 @@ public class RankingHelperTest extends AndroidTestCase { mNotiNoGroup2 = new Notification.Builder(getContext()) .setContentTitle("D") .setWhen(1202) - .setTopic(new Notification.Topic("D", "d")) .build(); mRecordNoGroup2 = new NotificationRecord(getContext(), new StatusBarNotification( "package", "package", 1, null, 0, 0, 0, mNotiNoGroup2, user)); @@ -97,7 +92,6 @@ public class RankingHelperTest extends AndroidTestCase { .setContentTitle("E") .setWhen(1201) .setSortKey("A") - .setTopic(new Notification.Topic("E", "e")) .build(); mRecordNoGroupSortA = new NotificationRecord(getContext(), new StatusBarNotification( "package", "package", 1, null, 0, 0, 0, mNotiNoGroupSortA, user)); @@ -152,26 +146,4 @@ public class RankingHelperTest extends AndroidTestCase { ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(); mHelper.sort(notificationList); } - - @SmallTest - public void testTopicImportanceExtractor() throws Exception { - mHelper.setImportance("package", 0, new Notification.Topic("A", "a"), IMPORTANCE_MAX); - // There is no B. There never was a b. Moving on... - mHelper.setImportance("package", 0, new Notification.Topic("C", "c"), IMPORTANCE_HIGH); - mHelper.setImportance("package", 0, new Notification.Topic("D", "d"), IMPORTANCE_LOW); - // watch out: different package. - mHelper.setImportance("package2", 0, new Notification.Topic("E", "e"), IMPORTANCE_NONE); - - TopicImportanceExtractor validator = mHelper.findExtractor(TopicImportanceExtractor.class); - validator.process(mRecordGroupGSortA); - validator.process(mRecordGroupGSortB); - validator.process(mRecordNoGroup); - validator.process(mRecordNoGroup2); - validator.process(mRecordNoGroupSortA); - assertTrue(mRecordGroupGSortA.getTopicImportance() == IMPORTANCE_MAX); - assertTrue(mRecordGroupGSortB.getTopicImportance() == IMPORTANCE_MAX); - assertTrue(mRecordNoGroup.getTopicImportance() == IMPORTANCE_HIGH); - assertTrue(mRecordNoGroup2.getTopicImportance() == IMPORTANCE_LOW); - assertTrue(mRecordNoGroupSortA.getTopicImportance() == IMPORTANCE_UNSPECIFIED); - } } diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java index cde47bd0666a..b4c4bf8b5ef3 100644 --- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java +++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java @@ -198,6 +198,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { return STATUS_ERROR; } modelData.setHandle(handle[0]); + modelData.setLoaded(); } modelData.setCallback(callback); modelData.setRecognitionConfig(recognitionConfig); @@ -346,7 +347,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { return STATUS_ERROR; } - if (currentCallback == null || !modelData.modelStarted()) { + if (currentCallback == null || !modelData.isModelStarted()) { // startRecognition hasn't been called or it failed. Slog.w(TAG, "Attempting stopRecognition without a successful startRecognition"); return STATUS_ERROR; @@ -451,7 +452,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { // Stop all generic recognition models. for (ModelData model : mGenericModelDataMap.values()) { - if (model.modelStarted()) { + if (model.isModelStarted()) { int status = stopGenericRecognitionLocked(model, false /* do not notify for synchronous calls */); if (status != STATUS_OK) { @@ -970,7 +971,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { } for (UUID modelId : mGenericModelDataMap.keySet()) { ModelData modelData = mGenericModelDataMap.get(modelId); - if (modelData.modelStarted()) { + if (modelData.isModelStarted()) { mRecognitionRunning = true; return mRecognitionRunning; } @@ -1001,7 +1002,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { // to SoundModel.TYPE_UNKNOWN; private int mModelType = SoundModel.TYPE_UNKNOWN; private IRecognitionStatusCallback mCallback = null; - private SoundModel mSoundModel = null; private RecognitionConfig mRecognitionConfig = null; @@ -1026,8 +1026,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { } synchronized boolean isModelLoaded() { - return (mModelState == MODEL_LOADED || mModelState == MODEL_STARTED) && - mSoundModel != null; + return (mModelState == MODEL_LOADED || mModelState == MODEL_STARTED); } synchronized void setStarted() { @@ -1038,13 +1037,16 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { mModelState = MODEL_LOADED; } - synchronized boolean modelStarted() { + synchronized void setLoaded() { + mModelState = MODEL_LOADED; + } + + synchronized boolean isModelStarted() { return mModelState == MODEL_STARTED; } synchronized void clearState() { mModelState = MODEL_NOTLOADED; - mSoundModel = null; mModelHandle = INVALID_VALUE; } diff --git a/tests/SoundTriggerTestApp/res/layout/main.xml b/tests/SoundTriggerTestApp/res/layout/main.xml index 5ecc7705cd75..702be49aac7b 100644 --- a/tests/SoundTriggerTestApp/res/layout/main.xml +++ b/tests/SoundTriggerTestApp/res/layout/main.xml @@ -66,6 +66,7 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="20dp" + android:checkedButton="@+id/model_one" android:orientation="vertical"> <RadioButton android:id="@+id/model_one" android:layout_width="wrap_content" @@ -84,15 +85,21 @@ android:onClick="onRadioButtonClicked"/> </RadioGroup> - <TextView - android:id="@+id/console" - android:gravity="left" +<ScrollView + android:id="@+id/scroller_id" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:scrollbars="vertical" + android:fillViewport="true"> + + <TextView + android:id="@+id/console" android:paddingTop="20pt" android:layout_height="fill_parent" - android:layout_width="match_parent" - android:maxLines="40" + android:layout_width="fill_parent" android:textSize="14dp" - android:scrollbars = "vertical" + android:layout_weight="1.0" android:text="@string/none"> </TextView> +</ScrollView> </LinearLayout> diff --git a/tests/SoundTriggerTestApp/res/values/strings.xml b/tests/SoundTriggerTestApp/res/values/strings.xml index 5f0fb1daf3e9..b4ca71b8286e 100644 --- a/tests/SoundTriggerTestApp/res/values/strings.xml +++ b/tests/SoundTriggerTestApp/res/values/strings.xml @@ -24,5 +24,5 @@ <string name="model_one">Model One</string> <string name="model_two">Model Two</string> <string name="model_three">Model Three</string> - <string name="none">Debug messages appear here:</string> + <string name="none">Debug messages appear here:\n</string> </resources> diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java index 96a69661a7aa..3149783506de 100644 --- a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java +++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java @@ -32,6 +32,7 @@ import android.os.UserManager; import android.util.Log; import android.view.View; import android.widget.RadioButton; +import android.widget.ScrollView; import android.widget.TextView; import android.widget.Toast; @@ -52,6 +53,7 @@ public class TestSoundTriggerActivity extends Activity { private TextView mDebugView = null; private int mSelectedModelId = 1; + private ScrollView mScrollView = null; @Override protected void onCreate(Bundle savedInstanceState) { @@ -59,6 +61,7 @@ public class TestSoundTriggerActivity extends Activity { super.onCreate(savedInstanceState); setContentView(R.layout.main); mDebugView = (TextView) findViewById(R.id.console); + mScrollView = (ScrollView) findViewById(R.id.scroller_id); mDebugView.setText(mDebugView.getText(), TextView.BufferType.EDITABLE); mDebugView.setMovementMethod(new ScrollingMovementMethod()); mSoundTriggerUtil = new SoundTriggerUtil(this); @@ -68,6 +71,18 @@ public class TestSoundTriggerActivity extends Activity { private void postMessage(String msg) { Log.i(TAG, "Posted: " + msg); ((Editable) mDebugView.getText()).append(msg + "\n"); + if ((mDebugView.getMeasuredHeight() - mScrollView.getScrollY()) <= + (mScrollView.getHeight() + mDebugView.getLineHeight())) { + scrollToBottom(); + } + } + + private void scrollToBottom() { + mScrollView.post(new Runnable() { + public void run() { + mScrollView.smoothScrollTo(0, mDebugView.getBottom()); + } + }); } private UUID getSelectedUuid() { diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java index 46de2016e4e4..9ac4dbfed65a 100644 --- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java +++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java @@ -162,78 +162,6 @@ public class NotificationTestList extends TestActivity } }, - new Test("with topic Hello") { - public void run() { - Notification.BigTextStyle bigText = new Notification.BigTextStyle(); - bigText.bigText("FgBHreherhethethethe\ntwetwrterter\netetweterteryetry"); - Notification n = new Notification.Builder(NotificationTestList.this) - .setSmallIcon(R.drawable.icon1) - .setStyle(bigText) - .setWhen(mActivityCreateTime) - .setContentTitle("hihi") - .setContentText("This is a notification!!!") - .setContentIntent(makeIntent2()) - .setTopic(new Notification.Topic("hello", "Hello")) - .build(); - - mNM.notify(70, n); - } - }, - - new Test("with topic GoodBye") { - public void run() { - Notification.BigPictureStyle picture = new Notification.BigPictureStyle(); - picture.bigPicture(BitmapFactory.decodeResource(getResources(), - R.id.large_icon_pineapple2)); - Notification n = new Notification.Builder(NotificationTestList.this) - .setSmallIcon(R.drawable.icon1) - .setWhen(mActivityCreateTime) - .setContentTitle("byebye") - .setContentText("This is a notification!!!") - .setContentIntent(makeIntent2()) - .setTopic(new Notification.Topic("bye", "Goodbye")) - .setStyle(picture) - .build(); - - mNM.notify(71, n); - } - }, - new Test("with topic Bananas") { - public void run() { - Notification.BigTextStyle bigText = new Notification.BigTextStyle(); - bigText.bigText("bananas are great\nso tasty\nyum\nyum\nyum\n"); - Notification n = new Notification.Builder(NotificationTestList.this) - .setSmallIcon(R.drawable.icon1) - .setStyle(bigText) - .setWhen(mActivityCreateTime) - .setContentTitle("bananananana") - .setContentText("This is a banana!!!") - .setContentIntent(makeIntent2()) - .setTopic(new Notification.Topic("bananas", "Bananas")) - .build(); - - mNM.notify(72, n); - } - }, - - new Test("with delete intent") { - public void run() { - Notification.BigTextStyle bigText = new Notification.BigTextStyle(); - bigText.bigText("bananas are great\nso tasty\nyum\nyum\nyum\n"); - Notification n = new Notification.Builder(NotificationTestList.this) - .setSmallIcon(R.drawable.icon1) - .setStyle(bigText) - .setWhen(mActivityCreateTime) - .setContentTitle("bananananana") - .setContentText("This is a banana!!!") - .setTopic(new Notification.Topic("bananas", "Bananas")) - .setDeleteIntent(makeIntent2()) - .build(); - - mNM.notify(73, n); - } - }, - new Test("Is blocked?") { public void run() { Toast.makeText(NotificationTestList.this, @@ -242,18 +170,10 @@ public class NotificationTestList extends TestActivity } }, - new Test("Topic banana importance?") { - public void run() { - Toast.makeText(NotificationTestList.this, - "bananas importance? " + mNM.getImportance("bananas"), - Toast.LENGTH_LONG).show(); - } - }, - - new Test("Topic garbage importance?") { + new Test("importance?") { public void run() { Toast.makeText(NotificationTestList.this, - "garbage importance? " + mNM.getImportance("garbage"), + "importance? " + mNM.getImportance(), Toast.LENGTH_LONG).show(); } }, diff --git a/tests/touchlag/Android.mk b/tests/touchlag/Android.mk index 4f8aa1e60ca8..70b198917547 100644 --- a/tests/touchlag/Android.mk +++ b/tests/touchlag/Android.mk @@ -9,6 +9,8 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_MODULE:= test-touchlag +LOCAL_CFLAGS += -Wall -Wextra -Werror + LOCAL_MODULE_TAGS := tests include $(BUILD_EXECUTABLE) diff --git a/tests/touchlag/touchlag.cpp b/tests/touchlag/touchlag.cpp index df4befb95fb9..9264a254ed24 100644 --- a/tests/touchlag/touchlag.cpp +++ b/tests/touchlag/touchlag.cpp @@ -54,11 +54,11 @@ void clearBuffer(Buffer* buf, uint32_t pixel) { void drawTwoPixels(Buffer* buf, uint32_t pixel, ssize_t x, ssize_t y, size_t w) { if (y>0 && y<ssize_t(buf->h)) { uint32_t* bits = buf->pixels + y * buf->s; - if (x>=0 && x<buf->w) { + if (x>=0 && x<ssize_t(buf->w)) { bits[x] = pixel; } ssize_t W(w); - if ((x+W)>=0 && (x+W)<buf->w) { + if ((x+W)>=0 && (x+W)<ssize_t(buf->w)) { bits[x+W] = pixel; } } @@ -251,13 +251,13 @@ int main(int argc, char** argv) { Queue queue; - int x=0, y=0, down=0; + int x=0, y=0; int lag_x=0, lag_y=0; clearBuffer(&framebuffer, 0); while (true) { uint32_t crt = 0; - int err = ioctl(fd, FBIO_WAITFORVSYNC, &crt); + ioctl(fd, FBIO_WAITFORVSYNC, &crt); // draw beam marker drawRect(&framebuffer, 0x400000, framebuffer.w-2, 0, 2, framebuffer.h); diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java index 31da6701e338..ed12bdf7b56d 100644 --- a/wifi/java/android/net/wifi/ScanResult.java +++ b/wifi/java/android/net/wifi/ScanResult.java @@ -331,6 +331,7 @@ public class ScanResult implements Parcelable { */ public static class InformationElement { public static final int EID_SSID = 0; + public static final int EID_TIM = 5; public static final int EID_BSS_LOAD = 11; public static final int EID_RSN = 48; public static final int EID_HT_OPERATION = 61; diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index cce83862e47c..ddd8f437955d 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -403,6 +403,15 @@ public class WifiConfiguration implements Parcelable { /** * @hide + * The number of beacon intervals between Delivery Traffic Indication Maps (DTIM) + * This value is populated from scan results that contain Beacon Frames, which are infrequent. + * The value is not guaranteed to be set or current (Although it SHOULDNT change once set) + * Valid values are from 1 - 255. Initialized here as 0, use this to check if set. + */ + public int dtimInterval = 0; + + /** + * @hide * Uid of app creating the configuration */ @SystemApi @@ -1298,6 +1307,7 @@ public class WifiConfiguration implements Parcelable { lastUpdateUid = -1; creatorUid = -1; shared = true; + dtimInterval = 0; } /** @@ -2044,4 +2054,4 @@ public class WifiConfiguration implements Parcelable { config.allowedKeyManagement.set(in.readInt()); return config; } -}
\ No newline at end of file +} diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java index 362738edec46..58e876130e0c 100644 --- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java +++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java @@ -20,6 +20,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.security.Credentials; import android.text.TextUtils; +import android.util.Log; import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; @@ -116,10 +117,30 @@ public class WifiEnterpriseConfig implements Parcelable { public static final String CA_CERT_ALIAS_DELIMITER = " "; + // Fields to copy verbatim from wpa_supplicant. + private static final String[] SUPPLICANT_CONFIG_KEYS = new String[] { + IDENTITY_KEY, + ANON_IDENTITY_KEY, + PASSWORD_KEY, + CLIENT_CERT_KEY, + CA_CERT_KEY, + SUBJECT_MATCH_KEY, + ENGINE_KEY, + ENGINE_ID_KEY, + PRIVATE_KEY_ID_KEY, + ALTSUBJECT_MATCH_KEY, + DOM_SUFFIX_MATCH_KEY, + CA_PATH_KEY + }; + private HashMap<String, String> mFields = new HashMap<String, String>(); private X509Certificate[] mCaCerts; private PrivateKey mClientPrivateKey; private X509Certificate mClientCertificate; + private int mEapMethod = Eap.NONE; + private int mPhase2Method = Phase2.NONE; + + private static final String TAG = "WifiEnterpriseConfig"; public WifiEnterpriseConfig() { // Do not set defaults so that the enterprise fields that are not changed @@ -134,6 +155,8 @@ public class WifiEnterpriseConfig implements Parcelable { for (String key : source.mFields.keySet()) { mFields.put(key, source.mFields.get(key)); } + mEapMethod = source.mEapMethod; + mPhase2Method = source.mPhase2Method; } @Override @@ -149,6 +172,8 @@ public class WifiEnterpriseConfig implements Parcelable { dest.writeString(entry.getValue()); } + dest.writeInt(mEapMethod); + dest.writeInt(mPhase2Method); writeCertificates(dest, mCaCerts); if (mClientPrivateKey != null) { @@ -200,6 +225,8 @@ public class WifiEnterpriseConfig implements Parcelable { enterpriseConfig.mFields.put(key, value); } + enterpriseConfig.mEapMethod = in.readInt(); + enterpriseConfig.mPhase2Method = in.readInt(); enterpriseConfig.mCaCerts = readCertificates(in); PrivateKey userKey = null; @@ -296,7 +323,8 @@ public class WifiEnterpriseConfig implements Parcelable { public static final int MSCHAPV2 = 3; /** Generic Token Card */ public static final int GTC = 4; - private static final String PREFIX = "auth="; + private static final String AUTH_PREFIX = "auth="; + private static final String AUTHEAP_PREFIX = "autheap="; /** @hide */ public static final String[] strings = {EMPTY_VALUE, "PAP", "MSCHAP", "MSCHAPV2", "GTC" }; @@ -305,11 +333,98 @@ public class WifiEnterpriseConfig implements Parcelable { private Phase2() {} } - /** Internal use only + // Loader and saver interfaces for exchanging data with wpa_supplicant. + // TODO: Decouple this object (which is just a placeholder of the configuration) + // from the implementation that knows what wpa_supplicant wants. + /** + * Interface used for retrieving supplicant configuration from WifiEnterpriseConfig + * @hide + */ + public interface SupplicantSaver { + /** + * Set a value within wpa_supplicant configuration + * @param key index to set within wpa_supplciant + * @param value the value for the key + * @return true if successful; false otherwise + */ + boolean saveValue(String key, String value); + } + + /** + * Interface used for populating a WifiEnterpriseConfig from supplicant configuration + * @hide + */ + public interface SupplicantLoader { + /** + * Returns a value within wpa_supplicant configuration + * @param key index to set within wpa_supplciant + * @return string value if successful; null otherwise + */ + String loadValue(String key); + } + + /** + * Internal use only; supply field values to wpa_supplicant config. The configuration + * process aborts on the first failed call on {@code saver}. + * @param saver proxy for setting configuration in wpa_supplciant + * @return whether the save succeeded on all attempts + * @hide + */ + public boolean saveToSupplicant(SupplicantSaver saver) { + if (!isEapMethodValid()) { + return false; + } + + for (String key : mFields.keySet()) { + if (!saver.saveValue(key, mFields.get(key))) { + return false; + } + } + + if (!saver.saveValue(EAP_KEY, Eap.strings[mEapMethod])) { + return false; + } + + if (mEapMethod != Eap.TLS && mPhase2Method != Phase2.NONE) { + boolean is_autheap = mEapMethod == Eap.TTLS && mPhase2Method == Phase2.GTC; + String prefix = is_autheap ? Phase2.AUTHEAP_PREFIX : Phase2.AUTH_PREFIX; + String value = convertToQuotedString(prefix + Phase2.strings[mPhase2Method]); + return saver.saveValue(PHASE2_KEY, value); + } else if (mPhase2Method == Phase2.NONE) { + // By default, send a null phase 2 to clear old configuration values. + return saver.saveValue(PHASE2_KEY, null); + } else { + Log.e(TAG, "WiFi enterprise configuration is invalid as it supplies a " + + "phase 2 method but the phase1 method does not support it."); + return false; + } + } + + /** + * Internal use only; retrieve configuration from wpa_supplicant config. + * @param loader proxy for retrieving configuration keys from wpa_supplicant * @hide */ - public HashMap<String, String> getFields() { - return mFields; + public void loadFromSupplicant(SupplicantLoader loader) { + for (String key : SUPPLICANT_CONFIG_KEYS) { + String value = loader.loadValue(key); + if (value == null) { + mFields.put(key, EMPTY_VALUE); + } else { + mFields.put(key, value); + } + } + String eapMethod = loader.loadValue(EAP_KEY); + mEapMethod = getStringIndex(Eap.strings, eapMethod, Eap.NONE); + + String phase2Method = removeDoubleQuotes(loader.loadValue(PHASE2_KEY)); + // Remove "auth=" or "autheap=" prefix. + if (phase2Method.startsWith(Phase2.AUTH_PREFIX)) { + phase2Method = phase2Method.substring(Phase2.AUTH_PREFIX.length()); + } else if (phase2Method.startsWith(Phase2.AUTHEAP_PREFIX)) { + phase2Method = phase2Method.substring(Phase2.AUTHEAP_PREFIX.length()); + } + mPhase2Method = getStringIndex(Phase2.strings, phase2Method, Phase2.NONE); } /** @@ -330,7 +445,7 @@ public class WifiEnterpriseConfig implements Parcelable { case Eap.SIM: case Eap.AKA: case Eap.AKA_PRIME: - mFields.put(EAP_KEY, Eap.strings[eapMethod]); + mEapMethod = eapMethod; mFields.put(OPP_KEY_CACHING, "1"); break; default: @@ -343,8 +458,7 @@ public class WifiEnterpriseConfig implements Parcelable { * @return eap method configured */ public int getEapMethod() { - String eapMethod = mFields.get(EAP_KEY); - return getStringIndex(Eap.strings, eapMethod, Eap.NONE); + return mEapMethod; } /** @@ -359,15 +473,11 @@ public class WifiEnterpriseConfig implements Parcelable { public void setPhase2Method(int phase2Method) { switch (phase2Method) { case Phase2.NONE: - mFields.put(PHASE2_KEY, EMPTY_VALUE); - break; - /** Valid methods */ case Phase2.PAP: case Phase2.MSCHAP: case Phase2.MSCHAPV2: case Phase2.GTC: - mFields.put(PHASE2_KEY, convertToQuotedString( - Phase2.PREFIX + Phase2.strings[phase2Method])); + mPhase2Method = phase2Method; break; default: throw new IllegalArgumentException("Unknown Phase 2 method"); @@ -379,12 +489,7 @@ public class WifiEnterpriseConfig implements Parcelable { * @return a phase 2 method defined at {@link Phase2} * */ public int getPhase2Method() { - String phase2Method = removeDoubleQuotes(mFields.get(PHASE2_KEY)); - // Remove auth= prefix - if (phase2Method.startsWith(Phase2.PREFIX)) { - phase2Method = phase2Method.substring(Phase2.PREFIX.length()); - } - return getStringIndex(Phase2.strings, phase2Method, Phase2.NONE); + return mPhase2Method; } /** @@ -412,7 +517,8 @@ public class WifiEnterpriseConfig implements Parcelable { setFieldValue(ANON_IDENTITY_KEY, anonymousIdentity, ""); } - /** Get the anonymous identity + /** + * Get the anonymous identity * @return anonymous identity */ public String getAnonymousIdentity() { @@ -839,18 +945,15 @@ public class WifiEnterpriseConfig implements Parcelable { } /** See {@link WifiConfiguration#getKeyIdForCredentials} @hide */ - String getKeyId(WifiEnterpriseConfig current) { - String eap = mFields.get(EAP_KEY); - String phase2 = mFields.get(PHASE2_KEY); - - // If either eap or phase2 are not initialized, use current config details - if (TextUtils.isEmpty((eap))) { - eap = current.mFields.get(EAP_KEY); + public String getKeyId(WifiEnterpriseConfig current) { + // If EAP method is not initialized, use current config details + if (mEapMethod == Eap.NONE) { + return (current != null) ? current.getKeyId(null) : EMPTY_VALUE; } - if (TextUtils.isEmpty(phase2)) { - phase2 = current.mFields.get(PHASE2_KEY); + if (!isEapMethodValid()) { + return EMPTY_VALUE; } - return eap + "_" + phase2; + return Eap.strings[mEapMethod] + "_" + Phase2.strings[mPhase2Method]; } private String removeDoubleQuotes(String string) { @@ -867,7 +970,8 @@ public class WifiEnterpriseConfig implements Parcelable { return "\"" + string + "\""; } - /** Returns the index at which the toBeFound string is found in the array. + /** + * Returns the index at which the toBeFound string is found in the array. * @param arr array of strings * @param toBeFound string to be found * @param defaultIndex default index to be returned when string is not found @@ -881,13 +985,16 @@ public class WifiEnterpriseConfig implements Parcelable { return defaultIndex; } - /** Returns the field value for the key. + /** + * Returns the field value for the key. * @param key into the hash * @param prefix is the prefix that the value may have * @return value * @hide */ public String getFieldValue(String key, String prefix) { + // TODO: Should raise an exception if |key| is EAP_KEY or PHASE2_KEY since + // neither of these keys should be retrieved in this manner. String value = mFields.get(key); // Uninitialized or known to be empty after reading from supplicant if (TextUtils.isEmpty(value) || EMPTY_VALUE.equals(value)) return ""; @@ -900,13 +1007,16 @@ public class WifiEnterpriseConfig implements Parcelable { } } - /** Set a value with an optional prefix at key + /** + * Set a value with an optional prefix at key * @param key into the hash * @param value to be set * @param prefix an optional value to be prefixed to actual value * @hide */ public void setFieldValue(String key, String value, String prefix) { + // TODO: Should raise an exception if |key| is EAP_KEY or PHASE2_KEY since + // neither of these keys should be set in this manner. if (TextUtils.isEmpty(value)) { mFields.put(key, EMPTY_VALUE); } else { @@ -915,13 +1025,16 @@ public class WifiEnterpriseConfig implements Parcelable { } - /** Set a value with an optional prefix at key + /** + * Set a value with an optional prefix at key * @param key into the hash * @param value to be set * @param prefix an optional value to be prefixed to actual value * @hide */ public void setFieldValue(String key, String value) { + // TODO: Should raise an exception if |key| is EAP_KEY or PHASE2_KEY since + // neither of these keys should be set in this manner. if (TextUtils.isEmpty(value)) { mFields.put(key, EMPTY_VALUE); } else { @@ -939,4 +1052,25 @@ public class WifiEnterpriseConfig implements Parcelable { } return sb.toString(); } + + /** + * Returns whether the EAP method data is valid, i.e., whether mEapMethod and mPhase2Method + * are valid indices into {@code Eap.strings[]} and {@code Phase2.strings[]} respectively. + */ + private boolean isEapMethodValid() { + if (mEapMethod == Eap.NONE) { + Log.e(TAG, "WiFi enterprise configuration is invalid as it supplies no EAP method."); + return false; + } + if (mEapMethod < 0 || mEapMethod >= Eap.strings.length) { + Log.e(TAG, "mEapMethod is invald for WiFi enterprise configuration: " + mEapMethod); + return false; + } + if (mPhase2Method < 0 || mPhase2Method >= Phase2.strings.length) { + Log.e(TAG, "mPhase2Method is invald for WiFi enterprise configuration: " + + mPhase2Method); + return false; + } + return true; + } } |