diff options
859 files changed, 22988 insertions, 10309 deletions
diff --git a/api/current.txt b/api/current.txt index 158525c8153b..8d7137526a08 100644 --- a/api/current.txt +++ b/api/current.txt @@ -113,6 +113,8 @@ package android { field public static final java.lang.String RECEIVE_SMS = "android.permission.RECEIVE_SMS"; field public static final java.lang.String RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH"; field public static final java.lang.String RECORD_AUDIO = "android.permission.RECORD_AUDIO"; + field public static final java.lang.String REGISTER_CONNECTION_MANAGER = "android.permission.REGISTER_CONNECTION_MANAGER"; + field public static final java.lang.String REGISTER_PROVIDER_OR_SUBSCRIPTION = "android.permission.REGISTER_PROVIDER_OR_SUBSCRIPTION"; field public static final java.lang.String REORDER_TASKS = "android.permission.REORDER_TASKS"; field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES"; field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE"; @@ -237,6 +239,8 @@ package android { field public static final int accessibilityFeedbackType = 16843650; // 0x1010382 field public static final int accessibilityFlags = 16843652; // 0x1010384 field public static final int accessibilityLiveRegion = 16843758; // 0x10103ee + field public static final int accessibilityTraversalAfter = 16844036; // 0x1010504 + field public static final int accessibilityTraversalBefore = 16844035; // 0x1010503 field public static final int accountPreferences = 16843423; // 0x101029f field public static final int accountType = 16843407; // 0x101028f field public static final int action = 16842797; // 0x101002d @@ -400,6 +404,7 @@ package android { field public static final int closeIcon = 16843905; // 0x1010481 field public static final int codes = 16843330; // 0x1010242 field public static final int collapseColumns = 16843083; // 0x101014b + field public static final int collapseContentDescription = 16844034; // 0x1010502 field public static final int color = 16843173; // 0x10101a5 field public static final int colorAccent = 16843829; // 0x1010435 field public static final int colorActivatedHighlight = 16843664; // 0x1010390 @@ -1002,6 +1007,7 @@ package android { field public static final int requiredForAllUsers = 16843728; // 0x10103d0 field public static final int requiresFadingEdge = 16843685; // 0x10103a5 field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364 + field public static final int resizeClip = 16844033; // 0x1010501 field public static final int resizeMode = 16843619; // 0x1010363 field public static final int resizeable = 16843405; // 0x101028d field public static final int resource = 16842789; // 0x1010025 @@ -3052,9 +3058,10 @@ package android.animation { method public android.graphics.Rect evaluate(float, android.graphics.Rect, android.graphics.Rect); } - public class StateListAnimator { + public class StateListAnimator implements java.lang.Cloneable { ctor public StateListAnimator(); method public void addState(int[], android.animation.Animator); + method public android.animation.StateListAnimator clone(); method public void jumpToCurrentState(); } @@ -4402,6 +4409,7 @@ package android.app { method public android.content.Intent createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence); method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult); method public boolean inKeyguardRestrictedInputMode(); + method public boolean isKeyguardInTrustedState(); method public boolean isKeyguardLocked(); method public boolean isKeyguardSecure(); method public deprecated android.app.KeyguardManager.KeyguardLock newKeyguardLock(java.lang.String); @@ -7432,6 +7440,7 @@ package android.content { method public java.lang.Object clone(); method public android.content.Intent cloneFilter(); method public static android.content.Intent createChooser(android.content.Intent, java.lang.CharSequence); + method public static android.content.Intent createChooser(android.content.Intent, java.lang.CharSequence, android.content.IntentSender); method public int describeContents(); method public int fillIn(android.content.Intent, int); method public boolean filterEquals(android.content.Intent); @@ -7707,6 +7716,8 @@ package android.content { field public static final java.lang.String EXTRA_CHANGED_COMPONENT_NAME_LIST = "android.intent.extra.changed_component_name_list"; field public static final java.lang.String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list"; field public static final java.lang.String EXTRA_CHANGED_UID_LIST = "android.intent.extra.changed_uid_list"; + field public static final java.lang.String EXTRA_CHOSEN_COMPONENT = "android.intent.extra.CHOSEN_COMPONENT"; + field public static final java.lang.String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER = "android.intent.extra.CHOSEN_COMPONENT_INTENT_SENDER"; field public static final java.lang.String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED"; field public static final java.lang.String EXTRA_DOCK_STATE = "android.intent.extra.DOCK_STATE"; field public static final int EXTRA_DOCK_STATE_CAR = 2; // 0x2 @@ -8621,6 +8632,7 @@ package android.content.pm { method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager); method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager); method public android.graphics.drawable.Drawable loadLogo(android.content.pm.PackageManager); + method public android.graphics.drawable.Drawable loadUnbadgedIcon(android.content.pm.PackageManager); method public android.content.res.XmlResourceParser loadXmlMetaData(android.content.pm.PackageManager, java.lang.String); method public void writeToParcel(android.os.Parcel, int); field public int banner; @@ -9250,6 +9262,7 @@ package android.content.res { method public int getType(int); method public boolean getValue(int, android.util.TypedValue); method public boolean hasValue(int); + method public boolean hasValueOrEmpty(int); method public int length(); method public android.util.TypedValue peekValue(int); method public void recycle(); @@ -16542,15 +16555,21 @@ package android.media.tv { method public static java.lang.String[] decode(java.lang.String); method public static java.lang.String encode(java.lang.String...); field public static final java.lang.String ANIMAL_WILDLIFE = "ANIMAL_WILDLIFE"; + field public static final java.lang.String ARTS = "ARTS"; field public static final java.lang.String COMEDY = "COMEDY"; field public static final java.lang.String DRAMA = "DRAMA"; field public static final java.lang.String EDUCATION = "EDUCATION"; + field public static final java.lang.String ENTERTAINMENT = "ENTERTAINMENT"; field public static final java.lang.String FAMILY_KIDS = "FAMILY_KIDS"; field public static final java.lang.String GAMING = "GAMING"; + field public static final java.lang.String LIFE_STYLE = "LIFE_STYLE"; field public static final java.lang.String MOVIES = "MOVIES"; + field public static final java.lang.String MUSIC = "MUSIC"; field public static final java.lang.String NEWS = "NEWS"; + field public static final java.lang.String PREMIER = "PREMIER"; field public static final java.lang.String SHOPPING = "SHOPPING"; field public static final java.lang.String SPORTS = "SPORTS"; + field public static final java.lang.String TECH_SCIENCE = "TECH_SCIENCE"; field public static final java.lang.String TRAVEL = "TRAVEL"; } @@ -17030,6 +17049,7 @@ package android.net { } public class Network implements android.os.Parcelable { + method public void bindSocket(java.net.DatagramSocket) throws java.io.IOException; method public void bindSocket(java.net.Socket) throws java.io.IOException; method public int describeContents(); method public java.net.InetAddress[] getAllByName(java.lang.String) throws java.net.UnknownHostException; @@ -17149,7 +17169,7 @@ package android.net { field public static final java.lang.String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE"; } - public class ProxyInfo implements android.os.Parcelable { + public deprecated class ProxyInfo implements android.os.Parcelable { method public static android.net.ProxyInfo buildDirectProxy(java.lang.String, int); method public static android.net.ProxyInfo buildDirectProxy(java.lang.String, int, java.util.List<java.lang.String>); method public static android.net.ProxyInfo buildPacProxy(android.net.Uri); @@ -17196,7 +17216,7 @@ package android.net { method public static javax.net.SocketFactory getDefault(int); method public static javax.net.ssl.SSLSocketFactory getDefault(int, android.net.SSLSessionCache); method public java.lang.String[] getDefaultCipherSuites(); - method public static org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache); + method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache); method public static javax.net.ssl.SSLSocketFactory getInsecure(int, android.net.SSLSessionCache); method public byte[] getNpnSelectedProtocol(java.net.Socket); method public java.lang.String[] getSupportedCipherSuites(); @@ -17414,7 +17434,7 @@ package android.net { package android.net.http { - public final class AndroidHttpClient implements org.apache.http.client.HttpClient { + public final deprecated class AndroidHttpClient implements org.apache.http.client.HttpClient { method public void close(); method public void disableCurlLogging(); method public void enableCurlLogging(java.lang.String, int); @@ -17432,8 +17452,8 @@ package android.net.http { method public org.apache.http.params.HttpParams getParams(); method public static java.io.InputStream getUngzippedContent(org.apache.http.HttpEntity) throws java.io.IOException; method public static void modifyRequestToAcceptGzipResponse(org.apache.http.HttpRequest); - method public static android.net.http.AndroidHttpClient newInstance(java.lang.String, android.content.Context); - method public static android.net.http.AndroidHttpClient newInstance(java.lang.String); + method public static deprecated android.net.http.AndroidHttpClient newInstance(java.lang.String, android.content.Context); + method public static deprecated android.net.http.AndroidHttpClient newInstance(java.lang.String); method public static long parseDate(java.lang.String); field public static long DEFAULT_SYNC_MIN_GZIP_BYTES; } @@ -21399,6 +21419,7 @@ package android.os { field public static final int KITKAT = 19; // 0x13 field public static final int KITKAT_WATCH = 20; // 0x14 field public static final int LOLLIPOP = 21; // 0x15 + field public static final int LOLLIPOP_MR1 = 22; // 0x16 } public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable { @@ -25127,6 +25148,7 @@ package android.provider { field public static final java.lang.String ACTION_APPLICATION_DETAILS_SETTINGS = "android.settings.APPLICATION_DETAILS_SETTINGS"; field public static final java.lang.String ACTION_APPLICATION_DEVELOPMENT_SETTINGS = "android.settings.APPLICATION_DEVELOPMENT_SETTINGS"; field public static final java.lang.String ACTION_APPLICATION_SETTINGS = "android.settings.APPLICATION_SETTINGS"; + field public static final java.lang.String ACTION_BATTERY_SAVER_SETTINGS = "android.settings.BATTERY_SAVER_SETTINGS"; field public static final java.lang.String ACTION_BLUETOOTH_SETTINGS = "android.settings.BLUETOOTH_SETTINGS"; field public static final java.lang.String ACTION_CAPTIONING_SETTINGS = "android.settings.CAPTIONING_SETTINGS"; field public static final java.lang.String ACTION_CAST_SETTINGS = "android.settings.CAST_SETTINGS"; @@ -25148,6 +25170,7 @@ package android.provider { field public static final java.lang.String ACTION_NFCSHARING_SETTINGS = "android.settings.NFCSHARING_SETTINGS"; field public static final java.lang.String ACTION_NFC_PAYMENT_SETTINGS = "android.settings.NFC_PAYMENT_SETTINGS"; field public static final java.lang.String ACTION_NFC_SETTINGS = "android.settings.NFC_SETTINGS"; + field public static final java.lang.String ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"; field public static final java.lang.String ACTION_PRINT_SETTINGS = "android.settings.ACTION_PRINT_SETTINGS"; field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS"; field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS"; @@ -25516,6 +25539,7 @@ package android.provider { field public static final java.lang.String STATUS = "st"; field public static final java.lang.String SUBJECT = "sub"; field public static final java.lang.String SUBJECT_CHARSET = "sub_cs"; + field public static final java.lang.String SUB_ID = "sub_id"; field public static final java.lang.String TEXT_ONLY = "text_only"; field public static final java.lang.String THREAD_ID = "thread_id"; field public static final java.lang.String TRANSACTION_ID = "tr_id"; @@ -25548,6 +25572,7 @@ package android.provider { field public static final java.lang.String PROXY = "proxy"; field public static final java.lang.String ROAMING_PROTOCOL = "roaming_protocol"; field public static final java.lang.String SERVER = "server"; + field public static final java.lang.String SUB_ID = "sub_id"; field public static final java.lang.String TYPE = "type"; field public static final java.lang.String USER = "user"; } @@ -25580,6 +25605,10 @@ package android.provider { public static final class Telephony.Mms.Intents { field public static final java.lang.String CONTENT_CHANGED_ACTION = "android.intent.action.CONTENT_CHANGED"; field public static final java.lang.String DELETED_CONTENTS = "deleted_contents"; + field public static final java.lang.String EXTRA_MMS_CONTENT_URI = "android.provider.Telephony.extra.MMS_CONTENT_URI"; + field public static final java.lang.String EXTRA_MMS_LOCATION_URL = "android.provider.Telephony.extra.MMS_LOCATION_URL"; + field public static final java.lang.String MMS_DOWNLOAD_ACTION = "android.provider.Telephony.MMS_DOWNLOAD"; + field public static final java.lang.String MMS_SEND_ACTION = "android.provider.Telephony.MMS_SEND"; } public static final class Telephony.Mms.Outbox implements android.provider.Telephony.BaseMmsColumns { @@ -25644,6 +25673,7 @@ package android.provider { field public static final java.lang.String MSG_TYPE = "msg_type"; field public static final java.lang.String PROTO_TYPE = "proto_type"; field public static final java.lang.String RETRY_INDEX = "retry_index"; + field public static final java.lang.String SUB_ID = "pending_sub_id"; } public static final class Telephony.Sms implements android.provider.BaseColumns android.provider.Telephony.TextBasedSmsColumns { @@ -25683,8 +25713,10 @@ package android.provider { field public static final java.lang.String SMS_CB_RECEIVED_ACTION = "android.provider.Telephony.SMS_CB_RECEIVED"; field public static final java.lang.String SMS_DELIVER_ACTION = "android.provider.Telephony.SMS_DELIVER"; field public static final java.lang.String SMS_EMERGENCY_CB_RECEIVED_ACTION = "android.provider.Telephony.SMS_EMERGENCY_CB_RECEIVED"; + field public static final java.lang.String SMS_FILTER_ACTION = "android.provider.Telephony.SMS_FILTER"; field public static final java.lang.String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED"; field public static final java.lang.String SMS_REJECTED_ACTION = "android.provider.Telephony.SMS_REJECTED"; + field public static final java.lang.String SMS_SEND_ACTION = "android.provider.Telephony.SMS_SEND"; field public static final java.lang.String SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION = "android.provider.Telephony.SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED"; field public static final java.lang.String WAP_PUSH_DELIVER_ACTION = "android.provider.Telephony.WAP_PUSH_DELIVER"; field public static final java.lang.String WAP_PUSH_RECEIVED_ACTION = "android.provider.Telephony.WAP_PUSH_RECEIVED"; @@ -25727,6 +25759,7 @@ package android.provider { field public static final int STATUS_NONE = -1; // 0xffffffff field public static final int STATUS_PENDING = 32; // 0x20 field public static final java.lang.String SUBJECT = "subject"; + field public static final java.lang.String SUB_ID = "sub_id"; field public static final java.lang.String THREAD_ID = "thread_id"; field public static final java.lang.String TYPE = "type"; } @@ -28037,16 +28070,346 @@ package android.system { package android.telecom { + public final class AudioState implements android.os.Parcelable { + ctor public AudioState(boolean, int, int); + ctor public AudioState(android.telecom.AudioState); + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.telecom.AudioState> CREATOR; + field public static final int ROUTE_BLUETOOTH = 2; // 0x2 + field public static final int ROUTE_EARPIECE = 1; // 0x1 + field public static final int ROUTE_SPEAKER = 8; // 0x8 + field public static final int ROUTE_WIRED_HEADSET = 4; // 0x4 + field public static final int ROUTE_WIRED_OR_EARPIECE = 5; // 0x5 + field public final boolean isMuted; + field public final int route; + field public final int supportedRouteMask; + } + + public abstract class Conference { + ctor public Conference(android.telecom.PhoneAccountHandle); + method public final boolean addConnection(android.telecom.Connection); + method public final void destroy(); + method public final android.telecom.AudioState getAudioState(); + method public final int getCapabilities(); + method public final java.util.List<android.telecom.Connection> getConferenceableConnections(); + method public final java.util.List<android.telecom.Connection> getConnections(); + method public final android.telecom.PhoneAccountHandle getPhoneAccountHandle(); + method public android.telecom.Connection getPrimaryConnection(); + method public final int getState(); + method public void onAudioStateChanged(android.telecom.AudioState); + method public void onDisconnect(); + method public void onHold(); + method public void onMerge(android.telecom.Connection); + method public void onMerge(); + method public void onPlayDtmfTone(char); + method public void onSeparate(android.telecom.Connection); + method public void onStopDtmfTone(); + method public void onSwap(); + method public void onUnhold(); + method public final void removeConnection(android.telecom.Connection); + method public final void setActive(); + method public final void setCapabilities(int); + method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>); + method public final void setDisconnected(android.telecom.DisconnectCause); + method public final void setOnHold(); + } + + public abstract class Connection { + ctor public Connection(); + method public static android.telecom.Connection createCanceledConnection(); + method public static android.telecom.Connection createFailedConnection(android.telecom.DisconnectCause); + method public final void destroy(); + method public final android.net.Uri getAddress(); + method public final int getAddressPresentation(); + method public final boolean getAudioModeIsVoip(); + method public final android.telecom.AudioState getAudioState(); + method public final int getCallCapabilities(); + method public final java.lang.String getCallerDisplayName(); + method public final int getCallerDisplayNamePresentation(); + method public final android.telecom.Conference getConference(); + method public final java.util.List<android.telecom.Connection> getConferenceableConnections(); + method public final android.telecom.DisconnectCause getDisconnectCause(); + method public final int getState(); + method public final android.telecom.StatusHints getStatusHints(); + method public final boolean isRingbackRequested(); + method public void onAbort(); + method public void onAnswer(); + method public void onAudioStateChanged(android.telecom.AudioState); + method public void onConferenceChanged(); + method public void onDisconnect(); + method public void onHold(); + method public void onPlayDtmfTone(char); + method public void onPostDialContinue(boolean); + method public void onReject(); + method public void onSeparate(); + method public void onStateChanged(int); + method public void onStopDtmfTone(); + method public void onUnhold(); + method public final void setActive(); + method public final void setAddress(android.net.Uri, int); + method public final void setAudioModeIsVoip(boolean); + method public final void setCallCapabilities(int); + method public final void setCallerDisplayName(java.lang.String, int); + method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>); + method public final void setConnectionService(android.telecom.ConnectionService); + method public final void setDialing(); + method public final void setDisconnected(android.telecom.DisconnectCause); + method public final void setInitialized(); + method public final void setInitializing(); + method public final void setOnHold(); + method public final void setPostDialWait(java.lang.String); + method public final void setRingbackRequested(boolean); + method public final void setRinging(); + method public final void setStatusHints(android.telecom.StatusHints); + method public static java.lang.String stateToString(int); + field public static final int STATE_ACTIVE = 4; // 0x4 + field public static final int STATE_DIALING = 3; // 0x3 + field public static final int STATE_DISCONNECTED = 6; // 0x6 + field public static final int STATE_HOLDING = 5; // 0x5 + field public static final int STATE_INITIALIZING = 0; // 0x0 + field public static final int STATE_NEW = 1; // 0x1 + field public static final int STATE_RINGING = 2; // 0x2 + } + + public final class ConnectionRequest implements android.os.Parcelable { + ctor public ConnectionRequest(android.telecom.PhoneAccountHandle, android.net.Uri, android.os.Bundle); + method public int describeContents(); + method public android.telecom.PhoneAccountHandle getAccountHandle(); + method public android.net.Uri getAddress(); + method public android.os.Bundle getExtras(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.telecom.ConnectionRequest> CREATOR; + } + + public abstract class ConnectionService extends android.app.Service { + ctor public ConnectionService(); + method public final void addConference(android.telecom.Conference); + method public final void addExistingConnection(android.telecom.PhoneAccountHandle, android.telecom.Connection); + method public final void conferenceRemoteConnections(android.telecom.RemoteConnection, android.telecom.RemoteConnection); + method public final android.telecom.RemoteConnection createRemoteIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); + method public final android.telecom.RemoteConnection createRemoteOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); + method public final java.util.Collection<android.telecom.Connection> getAllConnections(); + method public final android.os.IBinder onBind(android.content.Intent); + method public void onConference(android.telecom.Connection, android.telecom.Connection); + method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); + method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); + method public void onRemoteConferenceAdded(android.telecom.RemoteConference); + method public void onRemoteExistingConnectionAdded(android.telecom.RemoteConnection); + field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.ConnectionService"; + } + + public final class DisconnectCause implements android.os.Parcelable { + ctor public DisconnectCause(int); + ctor public DisconnectCause(int, java.lang.String); + ctor public DisconnectCause(int, java.lang.CharSequence, java.lang.CharSequence, java.lang.String); + ctor public DisconnectCause(int, java.lang.CharSequence, java.lang.CharSequence, java.lang.String, int); + method public int describeContents(); + method public int getCode(); + method public java.lang.CharSequence getDescription(); + method public java.lang.CharSequence getLabel(); + method public java.lang.String getReason(); + method public int getTone(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int BUSY = 7; // 0x7 + field public static final int CANCELED = 4; // 0x4 + field public static final android.os.Parcelable.Creator<android.telecom.DisconnectCause> CREATOR; + field public static final int ERROR = 1; // 0x1 + field public static final int LOCAL = 2; // 0x2 + field public static final int MISSED = 5; // 0x5 + field public static final int OTHER = 9; // 0x9 + field public static final int REJECTED = 6; // 0x6 + field public static final int REMOTE = 3; // 0x3 + field public static final int RESTRICTED = 8; // 0x8 + field public static final int UNKNOWN = 0; // 0x0 + } + + public class GatewayInfo implements android.os.Parcelable { + method public int describeContents(); + method public android.net.Uri getGatewayAddress(); + method public java.lang.String getGatewayProviderPackageName(); + method public android.net.Uri getOriginalAddress(); + method public boolean isEmpty(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.telecom.GatewayInfo> CREATOR; + } + + public class PhoneAccount implements android.os.Parcelable { + method public static android.telecom.PhoneAccount.Builder builder(android.telecom.PhoneAccountHandle, java.lang.CharSequence); + method public int describeContents(); + method public android.telecom.PhoneAccountHandle getAccountHandle(); + method public android.net.Uri getAddress(); + method public int getCapabilities(); + method public int getColor(); + method public android.graphics.drawable.Drawable getIcon(android.content.Context); + method public android.graphics.Bitmap getIconBitmap(); + method public java.lang.String getIconPackageName(); + method public int getIconResId(); + method public java.lang.CharSequence getLabel(); + method public java.lang.CharSequence getShortDescription(); + method public android.net.Uri getSubscriptionAddress(); + method public java.util.List<java.lang.String> getSupportedUriSchemes(); + method public boolean hasCapabilities(int); + method public boolean supportsUriScheme(java.lang.String); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1 + field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10 + field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4 + field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccount> CREATOR; + field public static final int NO_COLOR = -1; // 0xffffffff + field public static final java.lang.String SCHEME_SIP = "sip"; + field public static final java.lang.String SCHEME_TEL = "tel"; + field public static final java.lang.String SCHEME_VOICEMAIL = "voicemail"; + } + + public static class PhoneAccount.Builder { + ctor public PhoneAccount.Builder(android.telecom.PhoneAccountHandle, java.lang.CharSequence); + ctor public PhoneAccount.Builder(android.telecom.PhoneAccount); + method public android.telecom.PhoneAccount build(); + method public android.telecom.PhoneAccount.Builder setAddress(android.net.Uri); + method public android.telecom.PhoneAccount.Builder setCapabilities(int); + method public android.telecom.PhoneAccount.Builder setColor(int); + method public android.telecom.PhoneAccount.Builder setIconBitmap(android.graphics.Bitmap); + method public android.telecom.PhoneAccount.Builder setIconPackageName(java.lang.String); + method public android.telecom.PhoneAccount.Builder setIconResId(int); + method public android.telecom.PhoneAccount.Builder setShortDescription(java.lang.CharSequence); + method public android.telecom.PhoneAccount.Builder setSubscriptionAddress(android.net.Uri); + method public android.telecom.PhoneAccount.Builder setSupportedUriSchemes(java.util.List<java.lang.String>); + } + + public class PhoneAccountHandle implements android.os.Parcelable { + ctor public PhoneAccountHandle(android.content.ComponentName, java.lang.String); + method public int describeContents(); + method public android.content.ComponentName getComponentName(); + method public java.lang.String getId(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccountHandle> CREATOR; + } + + public final class PhoneCapabilities { + method public static java.lang.String toString(int); + field public static final int ADD_CALL = 16; // 0x10 + field public static final int ALL = 12543; // 0x30ff + field public static final int DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000 + field public static final int HOLD = 1; // 0x1 + field public static final int MANAGE_CONFERENCE = 128; // 0x80 + field public static final int MERGE_CONFERENCE = 4; // 0x4 + field public static final int MUTE = 64; // 0x40 + field public static final int RESPOND_VIA_TEXT = 32; // 0x20 + field public static final int SEPARATE_FROM_CONFERENCE = 4096; // 0x1000 + field public static final int SUPPORT_HOLD = 2; // 0x2 + field public static final int SWAP_CONFERENCE = 8; // 0x8 + } + + public final class RemoteConference { + method public void disconnect(); + method public final int getCallCapabilities(); + method public java.util.List<android.telecom.RemoteConnection> getConferenceableConnections(); + method public final java.util.List<android.telecom.RemoteConnection> getConnections(); + method public android.telecom.DisconnectCause getDisconnectCause(); + method public final int getState(); + method public void hold(); + method public void merge(); + method public void playDtmfTone(char); + method public final void registerCallback(android.telecom.RemoteConference.Callback); + method public void separate(android.telecom.RemoteConnection); + method public void setAudioState(android.telecom.AudioState); + method public void stopDtmfTone(); + method public void swap(); + method public void unhold(); + method public final void unregisterCallback(android.telecom.RemoteConference.Callback); + } + + public static abstract class RemoteConference.Callback { + ctor public RemoteConference.Callback(); + method public void onCapabilitiesChanged(android.telecom.RemoteConference, int); + method public void onConferenceableConnectionsChanged(android.telecom.RemoteConference, java.util.List<android.telecom.RemoteConnection>); + method public void onConnectionAdded(android.telecom.RemoteConference, android.telecom.RemoteConnection); + method public void onConnectionRemoved(android.telecom.RemoteConference, android.telecom.RemoteConnection); + method public void onDestroyed(android.telecom.RemoteConference); + method public void onDisconnected(android.telecom.RemoteConference, android.telecom.DisconnectCause); + method public void onStateChanged(android.telecom.RemoteConference, int, int); + } + + public final class RemoteConnection { + method public void abort(); + method public void answer(); + method public void disconnect(); + method public android.net.Uri getAddress(); + method public int getAddressPresentation(); + method public int getCallCapabilities(); + method public java.lang.CharSequence getCallerDisplayName(); + method public int getCallerDisplayNamePresentation(); + method public android.telecom.RemoteConference getConference(); + method public java.util.List<android.telecom.RemoteConnection> getConferenceableConnections(); + method public android.telecom.DisconnectCause getDisconnectCause(); + method public int getState(); + method public android.telecom.StatusHints getStatusHints(); + method public void hold(); + method public boolean isRingbackRequested(); + method public boolean isVoipAudioMode(); + method public void playDtmfTone(char); + method public void postDialContinue(boolean); + method public void registerCallback(android.telecom.RemoteConnection.Callback); + method public void reject(); + method public void setAudioState(android.telecom.AudioState); + method public void stopDtmfTone(); + method public void unhold(); + method public void unregisterCallback(android.telecom.RemoteConnection.Callback); + } + + public static abstract class RemoteConnection.Callback { + ctor public RemoteConnection.Callback(); + method public void onAddressChanged(android.telecom.RemoteConnection, android.net.Uri, int); + method public void onCallCapabilitiesChanged(android.telecom.RemoteConnection, int); + method public void onCallerDisplayNameChanged(android.telecom.RemoteConnection, java.lang.String, int); + method public void onConferenceChanged(android.telecom.RemoteConnection, android.telecom.RemoteConference); + method public void onConferenceableConnectionsChanged(android.telecom.RemoteConnection, java.util.List<android.telecom.RemoteConnection>); + method public void onDestroyed(android.telecom.RemoteConnection); + method public void onDisconnected(android.telecom.RemoteConnection, android.telecom.DisconnectCause); + method public void onPostDialWait(android.telecom.RemoteConnection, java.lang.String); + method public void onRingbackRequested(android.telecom.RemoteConnection, boolean); + method public void onStateChanged(android.telecom.RemoteConnection, int); + method public void onStatusHintsChanged(android.telecom.RemoteConnection, android.telecom.StatusHints); + method public void onVoipAudioChanged(android.telecom.RemoteConnection, boolean); + } + + public final class StatusHints implements android.os.Parcelable { + ctor public StatusHints(android.content.ComponentName, java.lang.CharSequence, int, android.os.Bundle); + method public int describeContents(); + method public android.os.Bundle getExtras(); + method public android.graphics.drawable.Drawable getIcon(android.content.Context); + method public int getIconResId(); + method public java.lang.CharSequence getLabel(); + method public android.content.ComponentName getPackageName(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.telecom.StatusHints> CREATOR; + } + public class TelecomManager { + method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle); method public void cancelMissedCallsNotification(); + method public void clearAccounts(); + method public android.telecom.PhoneAccountHandle getConnectionManager(); + method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle); + method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage(); method public boolean handleMmi(java.lang.String); + method public boolean handleMmi(android.telecom.PhoneAccountHandle, java.lang.String); + method public boolean hasMultipleCallCapableAccounts(); method public boolean isInCall(); + method public void registerPhoneAccount(android.telecom.PhoneAccount); method public void showInCallScreen(boolean); + method public void unregisterPhoneAccount(android.telecom.PhoneAccountHandle); + field public static final java.lang.String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecom.action.CHANGE_PHONE_ACCOUNTS"; + field public static final java.lang.String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.telecom.action.CONNECTION_SERVICE_CONFIGURE"; field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS"; field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ',' field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';' + field public static final java.lang.String EXTRA_CALL_BACK_NUMBER = "android.telecom.extra.CALL_BACK_NUMBER"; field public static final java.lang.String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecom.extra.CALL_DISCONNECT_CAUSE"; field public static final java.lang.String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecom.extra.CALL_DISCONNECT_MESSAGE"; + field public static final java.lang.String EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE"; + field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecom.extra.PHONE_ACCOUNT_HANDLE"; field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecom.extra.START_CALL_WITH_SPEAKERPHONE"; field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS"; field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE"; @@ -28366,11 +28729,18 @@ package android.telephony { method public void downloadMultimediaMessage(android.content.Context, java.lang.String, android.net.Uri, android.os.Bundle, android.app.PendingIntent); method public android.os.Bundle getCarrierConfigValues(); method public static android.telephony.SmsManager getDefault(); + method public static android.telephony.SmsManager getSmsManagerForSubscriber(int); + method public int getSubId(); + method public void injectSmsPdu(byte[], java.lang.String, android.app.PendingIntent); method public void sendDataMessage(java.lang.String, java.lang.String, short, byte[], android.app.PendingIntent, android.app.PendingIntent); method public void sendMultimediaMessage(android.content.Context, android.net.Uri, java.lang.String, android.os.Bundle, android.app.PendingIntent); method public void sendMultipartTextMessage(java.lang.String, java.lang.String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>); method public void sendTextMessage(java.lang.String, java.lang.String, java.lang.String, android.app.PendingIntent, android.app.PendingIntent); + method public void updateMmsDownloadStatus(android.content.Context, int, int, android.net.Uri); + method public void updateMmsSendStatus(android.content.Context, int, byte[], int, android.net.Uri); + method public void updateSmsSendStatus(int, boolean); field public static final java.lang.String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA"; + field public static final java.lang.String EXTRA_MMS_HTTP_STATUS = "android.telephony.extra.MMS_HTTP_STATUS"; field public static final java.lang.String MMS_CONFIG_ALIAS_ENABLED = "aliasEnabled"; field public static final java.lang.String MMS_CONFIG_ALIAS_MAX_CHARS = "aliasMaxChars"; field public static final java.lang.String MMS_CONFIG_ALIAS_MIN_CHARS = "aliasMinChars"; @@ -28407,6 +28777,7 @@ package android.telephony { field public static final int MMS_ERROR_RETRY = 6; // 0x6 field public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; // 0x3 field public static final int MMS_ERROR_UNSPECIFIED = 1; // 0x1 + field public static final java.lang.String MMS_SHOW_CELL_BROADCAST_APP_LINKS = "config_cellBroadcastAppLinks"; field public static final int RESULT_ERROR_GENERIC_FAILURE = 1; // 0x1 field public static final int RESULT_ERROR_NO_SERVICE = 4; // 0x4 field public static final int RESULT_ERROR_NULL_PDU = 3; // 0x3 @@ -28476,6 +28847,47 @@ package android.telephony { field public byte[] encodedScAddress; } + public class SubInfoRecord implements android.os.Parcelable { + ctor public SubInfoRecord(); + ctor public SubInfoRecord(int, java.lang.String, int, java.lang.String, int, int, java.lang.String, int, int, int[], int, int); + method public int describeContents(); + method public int getColor(); + method public android.graphics.drawable.BitmapDrawable getIconDrawable(); + method public java.lang.String getLabel(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.telephony.SubInfoRecord> CREATOR; + field public int color; + field public int dataRoaming; + field public java.lang.String displayName; + field public int displayNumberFormat; + field public java.lang.String iccId; + field public int mcc; + field public int mnc; + field public int nameSource; + field public java.lang.String number; + field public int[] simIconRes; + field public int slotId; + field public int subId; + } + + public class SubscriptionManager implements android.provider.BaseColumns { + method public static java.util.List<android.telephony.SubInfoRecord> getActiveSubInfoList(); + method public static int getDefaultSmsSubId(); + method public static int getSlotId(int); + method public static android.telephony.SubInfoRecord getSubInfoForSubscriber(int); + method public static java.util.List<android.telephony.SubInfoRecord> getSubInfoUsingSlotId(int); + method public static boolean isValidSubId(int); + field public static final int ASK_USER_SUB_ID = -1001; // 0xfffffc17 + field public static final int DEFAULT_PHONE_ID = 2147483647; // 0x7fffffff + field public static final int DEFAULT_SUB_ID = 2147483647; // 0x7fffffff + field public static final int INVALID_PHONE_ID = -1000; // 0xfffffc18 + field public static final int INVALID_SLOT_ID = -1000; // 0xfffffc18 + field public static final int INVALID_SUB_ID = -1000; // 0xfffffc18 + field public static final java.lang.String MCC = "mcc"; + field public static final java.lang.String MNC = "mnc"; + field public static final int SIM_NOT_INSERTED = -1; // 0xffffffff + } + public class TelephonyManager { method public java.util.List<android.telephony.CellInfo> getAllCellInfo(); method public int getCallState(); @@ -28502,6 +28914,7 @@ package android.telephony { method public java.lang.String getSubscriberId(); method public java.lang.String getVoiceMailAlphaTag(); method public java.lang.String getVoiceMailNumber(); + method public int hasCarrierPrivileges(); method public boolean hasIccCard(); method public boolean iccCloseLogicalChannel(int); method public byte[] iccExchangeSimIO(int, int, int, int, int, java.lang.String); @@ -28512,11 +28925,18 @@ package android.telephony { method public boolean isSmsCapable(); method public void listen(android.telephony.PhoneStateListener, int); method public java.lang.String sendEnvelopeWithStatus(java.lang.String); + method public boolean setGlobalPreferredNetworkType(); + method public void setLine1NumberForDisplay(java.lang.String, java.lang.String); + method public boolean setOperatorBrandOverride(java.lang.String); field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE"; field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE"; field public static final int CALL_STATE_IDLE = 0; // 0x0 field public static final int CALL_STATE_OFFHOOK = 2; // 0x2 field public static final int CALL_STATE_RINGING = 1; // 0x1 + field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe + field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1 + field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0 + field public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; // 0xffffffff field public static final int DATA_ACTIVITY_DORMANT = 4; // 0x4 field public static final int DATA_ACTIVITY_IN = 1; // 0x1 field public static final int DATA_ACTIVITY_INOUT = 3; // 0x3 @@ -29944,7 +30364,7 @@ package android.text.format { method public static java.lang.String formatShortFileSize(android.content.Context, long); } - public class Time { + public deprecated class Time { ctor public Time(java.lang.String); ctor public Time(); ctor public Time(android.text.format.Time); @@ -30914,6 +31334,7 @@ package android.transition { ctor public ChangeBounds(android.content.Context, android.util.AttributeSet); method public void captureEndValues(android.transition.TransitionValues); method public void captureStartValues(android.transition.TransitionValues); + method public boolean getResizeClip(); method public deprecated void setReparent(boolean); method public void setResizeClip(boolean); } @@ -31315,7 +31736,7 @@ package android.util { field public final int mTag; } - public class FloatMath { + public deprecated class FloatMath { method public static float ceil(float); method public static float cos(float); method public static float exp(float); @@ -31737,6 +32158,7 @@ package android.util { method public static int complexToDimensionPixelSize(int, android.util.DisplayMetrics); method public static float complexToFloat(int); method public static float complexToFraction(int, float, float); + method public int getComplexUnit(); method public float getDimension(android.util.DisplayMetrics); method public final float getFloat(); method public float getFraction(float, float); @@ -31759,6 +32181,8 @@ package android.util { field public static final int COMPLEX_UNIT_PX = 0; // 0x0 field public static final int COMPLEX_UNIT_SHIFT = 0; // 0x0 field public static final int COMPLEX_UNIT_SP = 2; // 0x2 + field public static final int DATA_NULL_EMPTY = 1; // 0x1 + field public static final int DATA_NULL_UNDEFINED = 0; // 0x0 field public static final int DENSITY_DEFAULT = 0; // 0x0 field public static final int DENSITY_NONE = 65535; // 0xffff field public static final int TYPE_ATTRIBUTE = 2; // 0x2 @@ -33190,6 +33614,8 @@ package android.view { method public static int generateViewId(); method public int getAccessibilityLiveRegion(); method public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider(); + method public int getAccessibilityTraversalAfter(); + method public int getAccessibilityTraversalBefore(); method public float getAlpha(); method public android.view.animation.Animation getAnimation(); method public android.os.IBinder getApplicationWindowToken(); @@ -33466,6 +33892,8 @@ package android.view { method public void sendAccessibilityEventUnchecked(android.view.accessibility.AccessibilityEvent); method public void setAccessibilityDelegate(android.view.View.AccessibilityDelegate); method public void setAccessibilityLiveRegion(int); + method public void setAccessibilityTraversalAfter(int); + method public void setAccessibilityTraversalBefore(int); method public void setActivated(boolean); method public void setAlpha(float); method public void setAnimation(android.view.animation.Animation); @@ -34316,12 +34744,14 @@ package android.view { method public void setCallback(android.view.Window.Callback); method public abstract void setChildDrawable(int, android.graphics.drawable.Drawable); method public abstract void setChildInt(int, int); + method public void setClipToOutline(boolean); method public void setContainer(android.view.Window); method public abstract void setContentView(int); method public abstract void setContentView(android.view.View); method public abstract void setContentView(android.view.View, android.view.ViewGroup.LayoutParams); method protected void setDefaultWindowFormat(int); method public void setDimAmount(float); + method public void setElevation(float); method public void setEnterTransition(android.transition.Transition); method public void setExitTransition(android.transition.Transition); method public abstract void setFeatureDrawable(int, android.graphics.drawable.Drawable); @@ -34522,6 +34952,7 @@ package android.view { field public static final int FLAG_HARDWARE_ACCELERATED = 16777216; // 0x1000000 field public static final int FLAG_IGNORE_CHEEK_PRESSES = 32768; // 0x8000 field public static final int FLAG_KEEP_SCREEN_ON = 128; // 0x80 + field public static final int FLAG_LAYOUT_ATTACHED_IN_DECOR = 1073741824; // 0x40000000 field public static final int FLAG_LAYOUT_INSET_DECOR = 65536; // 0x10000 field public static final int FLAG_LAYOUT_IN_OVERSCAN = 33554432; // 0x2000000 field public static final int FLAG_LAYOUT_IN_SCREEN = 256; // 0x100 @@ -34571,6 +35002,7 @@ package android.view { field public static final int SOFT_INPUT_STATE_UNSPECIFIED = 0; // 0x0 field public static final int SOFT_INPUT_STATE_VISIBLE = 4; // 0x4 field public static final int TITLE_CHANGED = 64; // 0x40 + field public static final int TYPE_ACCESSIBILITY_OVERLAY = 2032; // 0x7f0 field public static final int TYPE_APPLICATION = 2; // 0x2 field public static final int TYPE_APPLICATION_ATTACHED_DIALOG = 1003; // 0x3eb field public static final int TYPE_APPLICATION_MEDIA = 1001; // 0x3e9 @@ -34741,6 +35173,8 @@ package android.view.accessibility { method public java.lang.CharSequence getText(); method public int getTextSelectionEnd(); method public int getTextSelectionStart(); + method public android.view.accessibility.AccessibilityNodeInfo getTraversalAfter(); + method public android.view.accessibility.AccessibilityNodeInfo getTraversalBefore(); method public java.lang.String getViewIdResourceName(); method public android.view.accessibility.AccessibilityWindowInfo getWindow(); method public int getWindowId(); @@ -34811,6 +35245,10 @@ package android.view.accessibility { method public void setSource(android.view.View, int); method public void setText(java.lang.CharSequence); method public void setTextSelection(int, int); + method public void setTraversalAfter(android.view.View); + method public void setTraversalAfter(android.view.View, int); + method public void setTraversalBefore(android.view.View); + method public void setTraversalBefore(android.view.View, int); method public void setViewIdResourceName(java.lang.String); method public void setVisibleToUser(boolean); method public void writeToParcel(android.os.Parcel, int); @@ -34990,6 +35428,7 @@ package android.view.accessibility { method public void recycle(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.view.accessibility.AccessibilityWindowInfo> CREATOR; + field public static final int TYPE_ACCESSIBILITY_OVERLAY = 4; // 0x4 field public static final int TYPE_APPLICATION = 1; // 0x1 field public static final int TYPE_INPUT_METHOD = 2; // 0x2 field public static final int TYPE_SYSTEM = 3; // 0x3 @@ -35036,13 +35475,13 @@ package android.view.accessibility { package android.view.animation { - public class AccelerateDecelerateInterpolator implements android.view.animation.Interpolator { + public class AccelerateDecelerateInterpolator extends android.view.animation.BaseInterpolator { ctor public AccelerateDecelerateInterpolator(); ctor public AccelerateDecelerateInterpolator(android.content.Context, android.util.AttributeSet); method public float getInterpolation(float); } - public class AccelerateInterpolator implements android.view.animation.Interpolator { + public class AccelerateInterpolator extends android.view.animation.BaseInterpolator { ctor public AccelerateInterpolator(); ctor public AccelerateInterpolator(float); ctor public AccelerateInterpolator(android.content.Context, android.util.AttributeSet); @@ -35144,14 +35583,14 @@ package android.view.animation { method public static android.view.animation.Animation makeOutAnimation(android.content.Context, boolean); } - public class AnticipateInterpolator implements android.view.animation.Interpolator { + public class AnticipateInterpolator extends android.view.animation.BaseInterpolator { ctor public AnticipateInterpolator(); ctor public AnticipateInterpolator(float); ctor public AnticipateInterpolator(android.content.Context, android.util.AttributeSet); method public float getInterpolation(float); } - public class AnticipateOvershootInterpolator implements android.view.animation.Interpolator { + public class AnticipateOvershootInterpolator extends android.view.animation.BaseInterpolator { ctor public AnticipateOvershootInterpolator(); ctor public AnticipateOvershootInterpolator(float); ctor public AnticipateOvershootInterpolator(float, float); @@ -35159,19 +35598,23 @@ package android.view.animation { method public float getInterpolation(float); } - public class BounceInterpolator implements android.view.animation.Interpolator { + public abstract class BaseInterpolator implements android.view.animation.Interpolator { + ctor public BaseInterpolator(); + } + + public class BounceInterpolator extends android.view.animation.BaseInterpolator { ctor public BounceInterpolator(); ctor public BounceInterpolator(android.content.Context, android.util.AttributeSet); method public float getInterpolation(float); } - public class CycleInterpolator implements android.view.animation.Interpolator { + public class CycleInterpolator extends android.view.animation.BaseInterpolator { ctor public CycleInterpolator(float); ctor public CycleInterpolator(android.content.Context, android.util.AttributeSet); method public float getInterpolation(float); } - public class DecelerateInterpolator implements android.view.animation.Interpolator { + public class DecelerateInterpolator extends android.view.animation.BaseInterpolator { ctor public DecelerateInterpolator(); ctor public DecelerateInterpolator(float); ctor public DecelerateInterpolator(android.content.Context, android.util.AttributeSet); @@ -35246,20 +35689,20 @@ package android.view.animation { field public int index; } - public class LinearInterpolator implements android.view.animation.Interpolator { + public class LinearInterpolator extends android.view.animation.BaseInterpolator { ctor public LinearInterpolator(); ctor public LinearInterpolator(android.content.Context, android.util.AttributeSet); method public float getInterpolation(float); } - public class OvershootInterpolator implements android.view.animation.Interpolator { + public class OvershootInterpolator extends android.view.animation.BaseInterpolator { ctor public OvershootInterpolator(); ctor public OvershootInterpolator(float); ctor public OvershootInterpolator(android.content.Context, android.util.AttributeSet); method public float getInterpolation(float); } - public class PathInterpolator implements android.view.animation.Interpolator { + public class PathInterpolator extends android.view.animation.BaseInterpolator { ctor public PathInterpolator(android.graphics.Path); ctor public PathInterpolator(float, float); ctor public PathInterpolator(float, float, float, float); @@ -37744,6 +38187,7 @@ package android.widget { public class PopupMenu { ctor public PopupMenu(android.content.Context, android.view.View); ctor public PopupMenu(android.content.Context, android.view.View, int); + ctor public PopupMenu(android.content.Context, android.view.View, int, int, int); method public void dismiss(); method public android.view.View.OnTouchListener getDragToOpenListener(); method public android.view.Menu getMenu(); @@ -37784,6 +38228,7 @@ package android.widget { method public int getSoftInputMode(); method public int getWidth(); method public boolean isAboveAnchor(); + method public boolean isAttachedInDecor(); method public boolean isClippingEnabled(); method public boolean isFocusable(); method public boolean isOutsideTouchable(); @@ -37791,6 +38236,7 @@ package android.widget { method public boolean isSplitTouchEnabled(); method public boolean isTouchable(); method public void setAnimationStyle(int); + method public void setAttachedInDecor(boolean); method public void setBackgroundDrawable(android.graphics.drawable.Drawable); method public void setClippingEnabled(boolean); method public void setContentView(android.view.View); @@ -38000,6 +38446,8 @@ package android.widget { method public boolean onLoadClass(java.lang.Class); method public void reapply(android.content.Context, android.view.View); method public void removeAllViews(int); + method public void setAccessibilityTraversalAfter(int, int); + method public void setAccessibilityTraversalBefore(int, int); method public void setBitmap(int, java.lang.String, android.graphics.Bitmap); method public void setBoolean(int, java.lang.String, boolean); method public void setBundle(int, java.lang.String, android.os.Bundle); @@ -53994,7 +54442,7 @@ package junit.runner { package org.apache.commons.logging { - public abstract interface Log { + public abstract deprecated interface Log { method public abstract void debug(java.lang.Object); method public abstract void debug(java.lang.Object, java.lang.Throwable); method public abstract void error(java.lang.Object); @@ -54019,26 +54467,26 @@ package org.apache.commons.logging { package org.apache.http { - public class ConnectionClosedException extends java.io.IOException { + public deprecated class ConnectionClosedException extends java.io.IOException { ctor public ConnectionClosedException(java.lang.String); } - public abstract interface ConnectionReuseStrategy { + public abstract deprecated interface ConnectionReuseStrategy { method public abstract boolean keepAlive(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext); } - public abstract interface FormattedHeader implements org.apache.http.Header { + public abstract deprecated interface FormattedHeader implements org.apache.http.Header { method public abstract org.apache.http.util.CharArrayBuffer getBuffer(); method public abstract int getValuePos(); } - public abstract interface Header { + public abstract deprecated interface Header { method public abstract org.apache.http.HeaderElement[] getElements() throws org.apache.http.ParseException; method public abstract java.lang.String getName(); method public abstract java.lang.String getValue(); } - public abstract interface HeaderElement { + public abstract deprecated interface HeaderElement { method public abstract java.lang.String getName(); method public abstract org.apache.http.NameValuePair getParameter(int); method public abstract org.apache.http.NameValuePair getParameterByName(java.lang.String); @@ -54047,17 +54495,17 @@ package org.apache.http { method public abstract java.lang.String getValue(); } - public abstract interface HeaderElementIterator implements java.util.Iterator { + public abstract deprecated interface HeaderElementIterator implements java.util.Iterator { method public abstract boolean hasNext(); method public abstract org.apache.http.HeaderElement nextElement(); } - public abstract interface HeaderIterator implements java.util.Iterator { + public abstract deprecated interface HeaderIterator implements java.util.Iterator { method public abstract boolean hasNext(); method public abstract org.apache.http.Header nextHeader(); } - public abstract interface HttpClientConnection implements org.apache.http.HttpConnection { + public abstract deprecated interface HttpClientConnection implements org.apache.http.HttpConnection { method public abstract void flush() throws java.io.IOException; method public abstract boolean isResponseAvailable(int) throws java.io.IOException; method public abstract void receiveResponseEntity(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException; @@ -54066,7 +54514,7 @@ package org.apache.http { method public abstract void sendRequestHeader(org.apache.http.HttpRequest) throws org.apache.http.HttpException, java.io.IOException; } - public abstract interface HttpConnection { + public abstract deprecated interface HttpConnection { method public abstract void close() throws java.io.IOException; method public abstract org.apache.http.HttpConnectionMetrics getMetrics(); method public abstract int getSocketTimeout(); @@ -54076,7 +54524,7 @@ package org.apache.http { method public abstract void shutdown() throws java.io.IOException; } - public abstract interface HttpConnectionMetrics { + public abstract deprecated interface HttpConnectionMetrics { method public abstract java.lang.Object getMetric(java.lang.String); method public abstract long getReceivedBytesCount(); method public abstract long getRequestCount(); @@ -54085,7 +54533,7 @@ package org.apache.http { method public abstract void reset(); } - public abstract interface HttpEntity { + public abstract deprecated interface HttpEntity { method public abstract void consumeContent() throws java.io.IOException; method public abstract java.io.InputStream getContent() throws java.io.IOException, java.lang.IllegalStateException; method public abstract org.apache.http.Header getContentEncoding(); @@ -54097,19 +54545,19 @@ package org.apache.http { method public abstract void writeTo(java.io.OutputStream) throws java.io.IOException; } - public abstract interface HttpEntityEnclosingRequest implements org.apache.http.HttpRequest { + public abstract deprecated interface HttpEntityEnclosingRequest implements org.apache.http.HttpRequest { method public abstract boolean expectContinue(); method public abstract org.apache.http.HttpEntity getEntity(); method public abstract void setEntity(org.apache.http.HttpEntity); } - public class HttpException extends java.lang.Exception { + public deprecated class HttpException extends java.lang.Exception { ctor public HttpException(); ctor public HttpException(java.lang.String); ctor public HttpException(java.lang.String, java.lang.Throwable); } - public final class HttpHost implements java.lang.Cloneable { + public final deprecated class HttpHost implements java.lang.Cloneable { ctor public HttpHost(java.lang.String, int, java.lang.String); ctor public HttpHost(java.lang.String, int); ctor public HttpHost(java.lang.String); @@ -54127,14 +54575,14 @@ package org.apache.http { field protected final java.lang.String schemeName; } - public abstract interface HttpInetConnection implements org.apache.http.HttpConnection { + public abstract deprecated interface HttpInetConnection implements org.apache.http.HttpConnection { method public abstract java.net.InetAddress getLocalAddress(); method public abstract int getLocalPort(); method public abstract java.net.InetAddress getRemoteAddress(); method public abstract int getRemotePort(); } - public abstract interface HttpMessage { + public abstract deprecated interface HttpMessage { method public abstract void addHeader(org.apache.http.Header); method public abstract void addHeader(java.lang.String, java.lang.String); method public abstract boolean containsHeader(java.lang.String); @@ -54154,20 +54602,20 @@ package org.apache.http { method public abstract void setParams(org.apache.http.params.HttpParams); } - public abstract interface HttpRequest implements org.apache.http.HttpMessage { + public abstract deprecated interface HttpRequest implements org.apache.http.HttpMessage { method public abstract org.apache.http.RequestLine getRequestLine(); } - public abstract interface HttpRequestFactory { + public abstract deprecated interface HttpRequestFactory { method public abstract org.apache.http.HttpRequest newHttpRequest(org.apache.http.RequestLine) throws org.apache.http.MethodNotSupportedException; method public abstract org.apache.http.HttpRequest newHttpRequest(java.lang.String, java.lang.String) throws org.apache.http.MethodNotSupportedException; } - public abstract interface HttpRequestInterceptor { + public abstract deprecated interface HttpRequestInterceptor { method public abstract void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } - public abstract interface HttpResponse implements org.apache.http.HttpMessage { + public abstract deprecated interface HttpResponse implements org.apache.http.HttpMessage { method public abstract org.apache.http.HttpEntity getEntity(); method public abstract java.util.Locale getLocale(); method public abstract org.apache.http.StatusLine getStatusLine(); @@ -54180,16 +54628,16 @@ package org.apache.http { method public abstract void setStatusLine(org.apache.http.ProtocolVersion, int, java.lang.String); } - public abstract interface HttpResponseFactory { + public abstract deprecated interface HttpResponseFactory { method public abstract org.apache.http.HttpResponse newHttpResponse(org.apache.http.ProtocolVersion, int, org.apache.http.protocol.HttpContext); method public abstract org.apache.http.HttpResponse newHttpResponse(org.apache.http.StatusLine, org.apache.http.protocol.HttpContext); } - public abstract interface HttpResponseInterceptor { + public abstract deprecated interface HttpResponseInterceptor { method public abstract void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } - public abstract interface HttpServerConnection implements org.apache.http.HttpConnection { + public abstract deprecated interface HttpServerConnection implements org.apache.http.HttpConnection { method public abstract void flush() throws java.io.IOException; method public abstract void receiveRequestEntity(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.HttpException, java.io.IOException; method public abstract org.apache.http.HttpRequest receiveRequestHeader() throws org.apache.http.HttpException, java.io.IOException; @@ -54197,7 +54645,7 @@ package org.apache.http { method public abstract void sendResponseHeader(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException; } - public abstract interface HttpStatus { + public abstract deprecated interface HttpStatus { field public static final int SC_ACCEPTED = 202; // 0xca field public static final int SC_BAD_GATEWAY = 502; // 0x1f6 field public static final int SC_BAD_REQUEST = 400; // 0x190 @@ -54248,7 +54696,7 @@ package org.apache.http { field public static final int SC_USE_PROXY = 305; // 0x131 } - public final class HttpVersion extends org.apache.http.ProtocolVersion implements java.io.Serializable { + public final deprecated class HttpVersion extends org.apache.http.ProtocolVersion implements java.io.Serializable { ctor public HttpVersion(int, int); field public static final java.lang.String HTTP = "HTTP"; field public static final org.apache.http.HttpVersion HTTP_0_9; @@ -54256,37 +54704,37 @@ package org.apache.http { field public static final org.apache.http.HttpVersion HTTP_1_1; } - public class MalformedChunkCodingException extends java.io.IOException { + public deprecated class MalformedChunkCodingException extends java.io.IOException { ctor public MalformedChunkCodingException(); ctor public MalformedChunkCodingException(java.lang.String); } - public class MethodNotSupportedException extends org.apache.http.HttpException { + public deprecated class MethodNotSupportedException extends org.apache.http.HttpException { ctor public MethodNotSupportedException(java.lang.String); ctor public MethodNotSupportedException(java.lang.String, java.lang.Throwable); } - public abstract interface NameValuePair { + public abstract deprecated interface NameValuePair { method public abstract java.lang.String getName(); method public abstract java.lang.String getValue(); } - public class NoHttpResponseException extends java.io.IOException { + public deprecated class NoHttpResponseException extends java.io.IOException { ctor public NoHttpResponseException(java.lang.String); } - public class ParseException extends java.lang.RuntimeException { + public deprecated class ParseException extends java.lang.RuntimeException { ctor public ParseException(); ctor public ParseException(java.lang.String); } - public class ProtocolException extends org.apache.http.HttpException { + public deprecated class ProtocolException extends org.apache.http.HttpException { ctor public ProtocolException(); ctor public ProtocolException(java.lang.String); ctor public ProtocolException(java.lang.String, java.lang.Throwable); } - public class ProtocolVersion implements java.lang.Cloneable java.io.Serializable { + public deprecated class ProtocolVersion implements java.lang.Cloneable java.io.Serializable { ctor public ProtocolVersion(java.lang.String, int, int); method public java.lang.Object clone() throws java.lang.CloneNotSupportedException; method public int compareToVersion(org.apache.http.ProtocolVersion); @@ -54304,28 +54752,28 @@ package org.apache.http { field protected final java.lang.String protocol; } - public abstract interface ReasonPhraseCatalog { + public abstract deprecated interface ReasonPhraseCatalog { method public abstract java.lang.String getReason(int, java.util.Locale); } - public abstract interface RequestLine { + public abstract deprecated interface RequestLine { method public abstract java.lang.String getMethod(); method public abstract org.apache.http.ProtocolVersion getProtocolVersion(); method public abstract java.lang.String getUri(); } - public abstract interface StatusLine { + public abstract deprecated interface StatusLine { method public abstract org.apache.http.ProtocolVersion getProtocolVersion(); method public abstract java.lang.String getReasonPhrase(); method public abstract int getStatusCode(); } - public abstract interface TokenIterator implements java.util.Iterator { + public abstract deprecated interface TokenIterator implements java.util.Iterator { method public abstract boolean hasNext(); method public abstract java.lang.String nextToken(); } - public class UnsupportedHttpVersionException extends org.apache.http.ProtocolException { + public deprecated class UnsupportedHttpVersionException extends org.apache.http.ProtocolException { ctor public UnsupportedHttpVersionException(); ctor public UnsupportedHttpVersionException(java.lang.String); } @@ -54334,14 +54782,14 @@ package org.apache.http { package org.apache.http.auth { - public final class AUTH { + public final deprecated class AUTH { field public static final java.lang.String PROXY_AUTH = "Proxy-Authenticate"; field public static final java.lang.String PROXY_AUTH_RESP = "Proxy-Authorization"; field public static final java.lang.String WWW_AUTH = "WWW-Authenticate"; field public static final java.lang.String WWW_AUTH_RESP = "Authorization"; } - public abstract interface AuthScheme { + public abstract deprecated interface AuthScheme { method public abstract org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException; method public abstract java.lang.String getParameter(java.lang.String); method public abstract java.lang.String getRealm(); @@ -54351,11 +54799,11 @@ package org.apache.http.auth { method public abstract void processChallenge(org.apache.http.Header) throws org.apache.http.auth.MalformedChallengeException; } - public abstract interface AuthSchemeFactory { + public abstract deprecated interface AuthSchemeFactory { method public abstract org.apache.http.auth.AuthScheme newInstance(org.apache.http.params.HttpParams); } - public final class AuthSchemeRegistry { + public final deprecated class AuthSchemeRegistry { ctor public AuthSchemeRegistry(); method public synchronized org.apache.http.auth.AuthScheme getAuthScheme(java.lang.String, org.apache.http.params.HttpParams) throws java.lang.IllegalStateException; method public synchronized java.util.List<java.lang.String> getSchemeNames(); @@ -54364,7 +54812,7 @@ package org.apache.http.auth { method public synchronized void unregister(java.lang.String); } - public class AuthScope { + public deprecated class AuthScope { ctor public AuthScope(java.lang.String, int, java.lang.String, java.lang.String); ctor public AuthScope(java.lang.String, int, java.lang.String); ctor public AuthScope(java.lang.String, int); @@ -54381,7 +54829,7 @@ package org.apache.http.auth { field public static final java.lang.String ANY_SCHEME; } - public class AuthState { + public deprecated class AuthState { ctor public AuthState(); method public org.apache.http.auth.AuthScheme getAuthScheme(); method public org.apache.http.auth.AuthScope getAuthScope(); @@ -54393,35 +54841,35 @@ package org.apache.http.auth { method public void setCredentials(org.apache.http.auth.Credentials); } - public class AuthenticationException extends org.apache.http.ProtocolException { + public deprecated class AuthenticationException extends org.apache.http.ProtocolException { ctor public AuthenticationException(); ctor public AuthenticationException(java.lang.String); ctor public AuthenticationException(java.lang.String, java.lang.Throwable); } - public final class BasicUserPrincipal implements java.security.Principal { + public final deprecated class BasicUserPrincipal implements java.security.Principal { ctor public BasicUserPrincipal(java.lang.String); method public java.lang.String getName(); } - public abstract interface Credentials { + public abstract deprecated interface Credentials { method public abstract java.lang.String getPassword(); method public abstract java.security.Principal getUserPrincipal(); } - public class InvalidCredentialsException extends org.apache.http.auth.AuthenticationException { + public deprecated class InvalidCredentialsException extends org.apache.http.auth.AuthenticationException { ctor public InvalidCredentialsException(); ctor public InvalidCredentialsException(java.lang.String); ctor public InvalidCredentialsException(java.lang.String, java.lang.Throwable); } - public class MalformedChallengeException extends org.apache.http.ProtocolException { + public deprecated class MalformedChallengeException extends org.apache.http.ProtocolException { ctor public MalformedChallengeException(); ctor public MalformedChallengeException(java.lang.String); ctor public MalformedChallengeException(java.lang.String, java.lang.Throwable); } - public class NTCredentials implements org.apache.http.auth.Credentials { + public deprecated class NTCredentials implements org.apache.http.auth.Credentials { ctor public NTCredentials(java.lang.String); ctor public NTCredentials(java.lang.String, java.lang.String, java.lang.String, java.lang.String); method public java.lang.String getDomain(); @@ -54431,14 +54879,14 @@ package org.apache.http.auth { method public java.lang.String getWorkstation(); } - public class NTUserPrincipal implements java.security.Principal { + public deprecated class NTUserPrincipal implements java.security.Principal { ctor public NTUserPrincipal(java.lang.String, java.lang.String); method public java.lang.String getDomain(); method public java.lang.String getName(); method public java.lang.String getUsername(); } - public class UsernamePasswordCredentials implements org.apache.http.auth.Credentials { + public deprecated class UsernamePasswordCredentials implements org.apache.http.auth.Credentials { ctor public UsernamePasswordCredentials(java.lang.String); ctor public UsernamePasswordCredentials(java.lang.String, java.lang.String); method public java.lang.String getPassword(); @@ -54450,16 +54898,16 @@ package org.apache.http.auth { package org.apache.http.auth.params { - public abstract interface AuthPNames { + public abstract deprecated interface AuthPNames { field public static final java.lang.String CREDENTIAL_CHARSET = "http.auth.credential-charset"; } - public class AuthParamBean extends org.apache.http.params.HttpAbstractParamBean { + public deprecated class AuthParamBean extends org.apache.http.params.HttpAbstractParamBean { ctor public AuthParamBean(org.apache.http.params.HttpParams); method public void setCredentialCharset(java.lang.String); } - public final class AuthParams { + public final deprecated class AuthParams { method public static java.lang.String getCredentialCharset(org.apache.http.params.HttpParams); method public static void setCredentialCharset(org.apache.http.params.HttpParams, java.lang.String); } @@ -54468,39 +54916,39 @@ package org.apache.http.auth.params { package org.apache.http.client { - public abstract interface AuthenticationHandler { + public abstract deprecated interface AuthenticationHandler { method public abstract java.util.Map<java.lang.String, org.apache.http.Header> getChallenges(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.MalformedChallengeException; method public abstract boolean isAuthenticationRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext); method public abstract org.apache.http.auth.AuthScheme selectScheme(java.util.Map<java.lang.String, org.apache.http.Header>, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.AuthenticationException; } - public class CircularRedirectException extends org.apache.http.client.RedirectException { + public deprecated class CircularRedirectException extends org.apache.http.client.RedirectException { ctor public CircularRedirectException(); ctor public CircularRedirectException(java.lang.String); ctor public CircularRedirectException(java.lang.String, java.lang.Throwable); } - public class ClientProtocolException extends java.io.IOException { + public deprecated class ClientProtocolException extends java.io.IOException { ctor public ClientProtocolException(); ctor public ClientProtocolException(java.lang.String); ctor public ClientProtocolException(java.lang.Throwable); ctor public ClientProtocolException(java.lang.String, java.lang.Throwable); } - public abstract interface CookieStore { + public abstract deprecated interface CookieStore { method public abstract void addCookie(org.apache.http.cookie.Cookie); method public abstract void clear(); method public abstract boolean clearExpired(java.util.Date); method public abstract java.util.List<org.apache.http.cookie.Cookie> getCookies(); } - public abstract interface CredentialsProvider { + public abstract deprecated interface CredentialsProvider { method public abstract void clear(); method public abstract org.apache.http.auth.Credentials getCredentials(org.apache.http.auth.AuthScope); method public abstract void setCredentials(org.apache.http.auth.AuthScope, org.apache.http.auth.Credentials); } - public abstract interface HttpClient { + public abstract deprecated interface HttpClient { method public abstract org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest) throws org.apache.http.client.ClientProtocolException, java.io.IOException; method public abstract org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException; method public abstract org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest) throws org.apache.http.client.ClientProtocolException, java.io.IOException; @@ -54513,40 +54961,40 @@ package org.apache.http.client { method public abstract org.apache.http.params.HttpParams getParams(); } - public abstract interface HttpRequestRetryHandler { + public abstract deprecated interface HttpRequestRetryHandler { method public abstract boolean retryRequest(java.io.IOException, int, org.apache.http.protocol.HttpContext); } - public class HttpResponseException extends org.apache.http.client.ClientProtocolException { + public deprecated class HttpResponseException extends org.apache.http.client.ClientProtocolException { ctor public HttpResponseException(int, java.lang.String); method public int getStatusCode(); } - public class NonRepeatableRequestException extends org.apache.http.ProtocolException { + public deprecated class NonRepeatableRequestException extends org.apache.http.ProtocolException { ctor public NonRepeatableRequestException(); ctor public NonRepeatableRequestException(java.lang.String); } - public class RedirectException extends org.apache.http.ProtocolException { + public deprecated class RedirectException extends org.apache.http.ProtocolException { ctor public RedirectException(); ctor public RedirectException(java.lang.String); ctor public RedirectException(java.lang.String, java.lang.Throwable); } - public abstract interface RedirectHandler { + public abstract deprecated interface RedirectHandler { method public abstract java.net.URI getLocationURI(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.ProtocolException; method public abstract boolean isRedirectRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext); } - public abstract interface RequestDirector { + public abstract deprecated interface RequestDirector { method public abstract org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } - public abstract interface ResponseHandler { + public abstract deprecated interface ResponseHandler { method public abstract T handleResponse(org.apache.http.HttpResponse) throws org.apache.http.client.ClientProtocolException, java.io.IOException; } - public abstract interface UserTokenHandler { + public abstract deprecated interface UserTokenHandler { method public abstract java.lang.Object getUserToken(org.apache.http.protocol.HttpContext); } @@ -54554,7 +55002,7 @@ package org.apache.http.client { package org.apache.http.client.entity { - public class UrlEncodedFormEntity extends org.apache.http.entity.StringEntity { + public deprecated class UrlEncodedFormEntity extends org.apache.http.entity.StringEntity { ctor public UrlEncodedFormEntity(java.util.List<? extends org.apache.http.NameValuePair>, java.lang.String) throws java.io.UnsupportedEncodingException; ctor public UrlEncodedFormEntity(java.util.List<? extends org.apache.http.NameValuePair>) throws java.io.UnsupportedEncodingException; } @@ -54563,13 +55011,13 @@ package org.apache.http.client.entity { package org.apache.http.client.methods { - public abstract interface AbortableHttpRequest { + public abstract deprecated interface AbortableHttpRequest { method public abstract void abort(); method public abstract void setConnectionRequest(org.apache.http.conn.ClientConnectionRequest) throws java.io.IOException; method public abstract void setReleaseTrigger(org.apache.http.conn.ConnectionReleaseTrigger) throws java.io.IOException; } - public class HttpDelete extends org.apache.http.client.methods.HttpRequestBase { + public deprecated class HttpDelete extends org.apache.http.client.methods.HttpRequestBase { ctor public HttpDelete(); ctor public HttpDelete(java.net.URI); ctor public HttpDelete(java.lang.String); @@ -54577,14 +55025,14 @@ package org.apache.http.client.methods { field public static final java.lang.String METHOD_NAME = "DELETE"; } - public abstract class HttpEntityEnclosingRequestBase extends org.apache.http.client.methods.HttpRequestBase implements org.apache.http.HttpEntityEnclosingRequest { + public abstract deprecated class HttpEntityEnclosingRequestBase extends org.apache.http.client.methods.HttpRequestBase implements org.apache.http.HttpEntityEnclosingRequest { ctor public HttpEntityEnclosingRequestBase(); method public boolean expectContinue(); method public org.apache.http.HttpEntity getEntity(); method public void setEntity(org.apache.http.HttpEntity); } - public class HttpGet extends org.apache.http.client.methods.HttpRequestBase { + public deprecated class HttpGet extends org.apache.http.client.methods.HttpRequestBase { ctor public HttpGet(); ctor public HttpGet(java.net.URI); ctor public HttpGet(java.lang.String); @@ -54592,7 +55040,7 @@ package org.apache.http.client.methods { field public static final java.lang.String METHOD_NAME = "GET"; } - public class HttpHead extends org.apache.http.client.methods.HttpRequestBase { + public deprecated class HttpHead extends org.apache.http.client.methods.HttpRequestBase { ctor public HttpHead(); ctor public HttpHead(java.net.URI); ctor public HttpHead(java.lang.String); @@ -54600,7 +55048,7 @@ package org.apache.http.client.methods { field public static final java.lang.String METHOD_NAME = "HEAD"; } - public class HttpOptions extends org.apache.http.client.methods.HttpRequestBase { + public deprecated class HttpOptions extends org.apache.http.client.methods.HttpRequestBase { ctor public HttpOptions(); ctor public HttpOptions(java.net.URI); ctor public HttpOptions(java.lang.String); @@ -54609,7 +55057,7 @@ package org.apache.http.client.methods { field public static final java.lang.String METHOD_NAME = "OPTIONS"; } - public class HttpPost extends org.apache.http.client.methods.HttpEntityEnclosingRequestBase { + public deprecated class HttpPost extends org.apache.http.client.methods.HttpEntityEnclosingRequestBase { ctor public HttpPost(); ctor public HttpPost(java.net.URI); ctor public HttpPost(java.lang.String); @@ -54617,7 +55065,7 @@ package org.apache.http.client.methods { field public static final java.lang.String METHOD_NAME = "POST"; } - public class HttpPut extends org.apache.http.client.methods.HttpEntityEnclosingRequestBase { + public deprecated class HttpPut extends org.apache.http.client.methods.HttpEntityEnclosingRequestBase { ctor public HttpPut(); ctor public HttpPut(java.net.URI); ctor public HttpPut(java.lang.String); @@ -54625,7 +55073,7 @@ package org.apache.http.client.methods { field public static final java.lang.String METHOD_NAME = "PUT"; } - public abstract class HttpRequestBase extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.client.methods.AbortableHttpRequest java.lang.Cloneable org.apache.http.client.methods.HttpUriRequest { + public abstract deprecated class HttpRequestBase extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.client.methods.AbortableHttpRequest java.lang.Cloneable org.apache.http.client.methods.HttpUriRequest { ctor public HttpRequestBase(); method public void abort(); method public java.lang.Object clone() throws java.lang.CloneNotSupportedException; @@ -54639,7 +55087,7 @@ package org.apache.http.client.methods { method public void setURI(java.net.URI); } - public class HttpTrace extends org.apache.http.client.methods.HttpRequestBase { + public deprecated class HttpTrace extends org.apache.http.client.methods.HttpRequestBase { ctor public HttpTrace(); ctor public HttpTrace(java.net.URI); ctor public HttpTrace(java.lang.String); @@ -54647,7 +55095,7 @@ package org.apache.http.client.methods { field public static final java.lang.String METHOD_NAME = "TRACE"; } - public abstract interface HttpUriRequest implements org.apache.http.HttpRequest { + public abstract deprecated interface HttpUriRequest implements org.apache.http.HttpRequest { method public abstract void abort() throws java.lang.UnsupportedOperationException; method public abstract java.lang.String getMethod(); method public abstract java.net.URI getURI(); @@ -54658,16 +55106,16 @@ package org.apache.http.client.methods { package org.apache.http.client.params { - public abstract interface AllClientPNames implements org.apache.http.auth.params.AuthPNames org.apache.http.client.params.ClientPNames org.apache.http.conn.params.ConnConnectionPNames org.apache.http.conn.params.ConnManagerPNames org.apache.http.conn.params.ConnRoutePNames org.apache.http.cookie.params.CookieSpecPNames org.apache.http.params.CoreConnectionPNames org.apache.http.params.CoreProtocolPNames { + public abstract deprecated interface AllClientPNames implements org.apache.http.auth.params.AuthPNames org.apache.http.client.params.ClientPNames org.apache.http.conn.params.ConnConnectionPNames org.apache.http.conn.params.ConnManagerPNames org.apache.http.conn.params.ConnRoutePNames org.apache.http.cookie.params.CookieSpecPNames org.apache.http.params.CoreConnectionPNames org.apache.http.params.CoreProtocolPNames { } - public final class AuthPolicy { + public final deprecated class AuthPolicy { field public static final java.lang.String BASIC = "Basic"; field public static final java.lang.String DIGEST = "Digest"; field public static final java.lang.String NTLM = "NTLM"; } - public abstract interface ClientPNames { + public abstract deprecated interface ClientPNames { field public static final java.lang.String ALLOW_CIRCULAR_REDIRECTS = "http.protocol.allow-circular-redirects"; field public static final java.lang.String CONNECTION_MANAGER_FACTORY = "http.connection-manager.factory-object"; field public static final java.lang.String CONNECTION_MANAGER_FACTORY_CLASS_NAME = "http.connection-manager.factory-class-name"; @@ -54681,7 +55129,7 @@ package org.apache.http.client.params { field public static final java.lang.String VIRTUAL_HOST = "http.virtual-host"; } - public class ClientParamBean extends org.apache.http.params.HttpAbstractParamBean { + public deprecated class ClientParamBean extends org.apache.http.params.HttpAbstractParamBean { ctor public ClientParamBean(org.apache.http.params.HttpParams); method public void setAllowCircularRedirects(boolean); method public void setConnectionManagerFactory(org.apache.http.conn.ClientConnectionManagerFactory); @@ -54696,7 +55144,7 @@ package org.apache.http.client.params { method public void setVirtualHost(org.apache.http.HttpHost); } - public final class CookiePolicy { + public final deprecated class CookiePolicy { field public static final java.lang.String BEST_MATCH = "best-match"; field public static final java.lang.String BROWSER_COMPATIBILITY = "compatibility"; field public static final java.lang.String NETSCAPE = "netscape"; @@ -54704,7 +55152,7 @@ package org.apache.http.client.params { field public static final java.lang.String RFC_2965 = "rfc2965"; } - public class HttpClientParams { + public deprecated class HttpClientParams { method public static java.lang.String getCookiePolicy(org.apache.http.params.HttpParams); method public static boolean isAuthenticating(org.apache.http.params.HttpParams); method public static boolean isRedirecting(org.apache.http.params.HttpParams); @@ -54717,7 +55165,7 @@ package org.apache.http.client.params { package org.apache.http.client.protocol { - public abstract interface ClientContext { + public abstract deprecated interface ClientContext { field public static final java.lang.String AUTHSCHEME_REGISTRY = "http.authscheme-registry"; field public static final java.lang.String AUTH_SCHEME_PREF = "http.auth.scheme-pref"; field public static final java.lang.String COOKIESPEC_REGISTRY = "http.cookiespec-registry"; @@ -54730,7 +55178,7 @@ package org.apache.http.client.protocol { field public static final java.lang.String USER_TOKEN = "http.user-token"; } - public class ClientContextConfigurer implements org.apache.http.client.protocol.ClientContext { + public deprecated class ClientContextConfigurer implements org.apache.http.client.protocol.ClientContext { ctor public ClientContextConfigurer(org.apache.http.protocol.HttpContext); method public void setAuthSchemePref(java.util.List<java.lang.String>); method public void setAuthSchemeRegistry(org.apache.http.auth.AuthSchemeRegistry); @@ -54739,27 +55187,27 @@ package org.apache.http.client.protocol { method public void setCredentialsProvider(org.apache.http.client.CredentialsProvider); } - public class RequestAddCookies implements org.apache.http.HttpRequestInterceptor { + public deprecated class RequestAddCookies implements org.apache.http.HttpRequestInterceptor { ctor public RequestAddCookies(); method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } - public class RequestDefaultHeaders implements org.apache.http.HttpRequestInterceptor { + public deprecated class RequestDefaultHeaders implements org.apache.http.HttpRequestInterceptor { ctor public RequestDefaultHeaders(); method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } - public class RequestProxyAuthentication implements org.apache.http.HttpRequestInterceptor { + public deprecated class RequestProxyAuthentication implements org.apache.http.HttpRequestInterceptor { ctor public RequestProxyAuthentication(); method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } - public class RequestTargetAuthentication implements org.apache.http.HttpRequestInterceptor { + public deprecated class RequestTargetAuthentication implements org.apache.http.HttpRequestInterceptor { ctor public RequestTargetAuthentication(); method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } - public class ResponseProcessCookies implements org.apache.http.HttpResponseInterceptor { + public deprecated class ResponseProcessCookies implements org.apache.http.HttpResponseInterceptor { ctor public ResponseProcessCookies(); method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } @@ -54768,11 +55216,11 @@ package org.apache.http.client.protocol { package org.apache.http.client.utils { - public class CloneUtils { + public deprecated class CloneUtils { method public static java.lang.Object clone(java.lang.Object) throws java.lang.CloneNotSupportedException; } - public class URIUtils { + public deprecated class URIUtils { method public static java.net.URI createURI(java.lang.String, java.lang.String, int, java.lang.String, java.lang.String, java.lang.String) throws java.net.URISyntaxException; method public static java.net.URI resolve(java.net.URI, java.lang.String); method public static java.net.URI resolve(java.net.URI, java.net.URI); @@ -54780,7 +55228,7 @@ package org.apache.http.client.utils { method public static java.net.URI rewriteURI(java.net.URI, org.apache.http.HttpHost) throws java.net.URISyntaxException; } - public class URLEncodedUtils { + public deprecated class URLEncodedUtils { ctor public URLEncodedUtils(); method public static java.lang.String format(java.util.List<? extends org.apache.http.NameValuePair>, java.lang.String); method public static boolean isEncoded(org.apache.http.HttpEntity); @@ -54794,7 +55242,7 @@ package org.apache.http.client.utils { package org.apache.http.conn { - public class BasicEofSensorWatcher implements org.apache.http.conn.EofSensorWatcher { + public deprecated class BasicEofSensorWatcher implements org.apache.http.conn.EofSensorWatcher { ctor public BasicEofSensorWatcher(org.apache.http.conn.ManagedClientConnection, boolean); method public boolean eofDetected(java.io.InputStream) throws java.io.IOException; method public boolean streamAbort(java.io.InputStream) throws java.io.IOException; @@ -54803,7 +55251,7 @@ package org.apache.http.conn { field protected org.apache.http.conn.ManagedClientConnection managedConn; } - public class BasicManagedEntity extends org.apache.http.entity.HttpEntityWrapper implements org.apache.http.conn.ConnectionReleaseTrigger org.apache.http.conn.EofSensorWatcher { + public deprecated class BasicManagedEntity extends org.apache.http.entity.HttpEntityWrapper implements org.apache.http.conn.ConnectionReleaseTrigger org.apache.http.conn.EofSensorWatcher { ctor public BasicManagedEntity(org.apache.http.HttpEntity, org.apache.http.conn.ManagedClientConnection, boolean); method public void abortConnection() throws java.io.IOException; method public boolean eofDetected(java.io.InputStream) throws java.io.IOException; @@ -54815,7 +55263,7 @@ package org.apache.http.conn { field protected org.apache.http.conn.ManagedClientConnection managedConn; } - public abstract interface ClientConnectionManager { + public abstract deprecated interface ClientConnectionManager { method public abstract void closeExpiredConnections(); method public abstract void closeIdleConnections(long, java.util.concurrent.TimeUnit); method public abstract org.apache.http.conn.scheme.SchemeRegistry getSchemeRegistry(); @@ -54824,41 +55272,41 @@ package org.apache.http.conn { method public abstract void shutdown(); } - public abstract interface ClientConnectionManagerFactory { + public abstract deprecated interface ClientConnectionManagerFactory { method public abstract org.apache.http.conn.ClientConnectionManager newInstance(org.apache.http.params.HttpParams, org.apache.http.conn.scheme.SchemeRegistry); } - public abstract interface ClientConnectionOperator { + public abstract deprecated interface ClientConnectionOperator { method public abstract org.apache.http.conn.OperatedClientConnection createConnection(); method public abstract void openConnection(org.apache.http.conn.OperatedClientConnection, org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException; method public abstract void updateSecureConnection(org.apache.http.conn.OperatedClientConnection, org.apache.http.HttpHost, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException; } - public abstract interface ClientConnectionRequest { + public abstract deprecated interface ClientConnectionRequest { method public abstract void abortRequest(); method public abstract org.apache.http.conn.ManagedClientConnection getConnection(long, java.util.concurrent.TimeUnit) throws org.apache.http.conn.ConnectionPoolTimeoutException, java.lang.InterruptedException; } - public class ConnectTimeoutException extends java.io.InterruptedIOException { + public deprecated class ConnectTimeoutException extends java.io.InterruptedIOException { ctor public ConnectTimeoutException(); ctor public ConnectTimeoutException(java.lang.String); } - public abstract interface ConnectionKeepAliveStrategy { + public abstract deprecated interface ConnectionKeepAliveStrategy { method public abstract long getKeepAliveDuration(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext); } - public class ConnectionPoolTimeoutException extends org.apache.http.conn.ConnectTimeoutException { + public deprecated class ConnectionPoolTimeoutException extends org.apache.http.conn.ConnectTimeoutException { ctor public ConnectionPoolTimeoutException(); ctor public ConnectionPoolTimeoutException(java.lang.String); } - public abstract interface ConnectionReleaseTrigger { + public abstract deprecated interface ConnectionReleaseTrigger { method public abstract void abortConnection() throws java.io.IOException; method public abstract void releaseConnection() throws java.io.IOException; } - public class EofSensorInputStream extends java.io.InputStream implements org.apache.http.conn.ConnectionReleaseTrigger { + public deprecated class EofSensorInputStream extends java.io.InputStream implements org.apache.http.conn.ConnectionReleaseTrigger { ctor public EofSensorInputStream(java.io.InputStream, org.apache.http.conn.EofSensorWatcher); method public void abortConnection() throws java.io.IOException; method protected void checkAbort() throws java.io.IOException; @@ -54870,18 +55318,18 @@ package org.apache.http.conn { field protected java.io.InputStream wrappedStream; } - public abstract interface EofSensorWatcher { + public abstract deprecated interface EofSensorWatcher { method public abstract boolean eofDetected(java.io.InputStream) throws java.io.IOException; method public abstract boolean streamAbort(java.io.InputStream) throws java.io.IOException; method public abstract boolean streamClosed(java.io.InputStream) throws java.io.IOException; } - public class HttpHostConnectException extends java.net.ConnectException { + public deprecated class HttpHostConnectException extends java.net.ConnectException { ctor public HttpHostConnectException(org.apache.http.HttpHost, java.net.ConnectException); method public org.apache.http.HttpHost getHost(); } - public abstract interface ManagedClientConnection implements org.apache.http.conn.ConnectionReleaseTrigger org.apache.http.HttpClientConnection org.apache.http.HttpInetConnection { + public abstract deprecated interface ManagedClientConnection implements org.apache.http.conn.ConnectionReleaseTrigger org.apache.http.HttpClientConnection org.apache.http.HttpInetConnection { method public abstract org.apache.http.conn.routing.HttpRoute getRoute(); method public abstract javax.net.ssl.SSLSession getSSLSession(); method public abstract java.lang.Object getState(); @@ -54897,14 +55345,14 @@ package org.apache.http.conn { method public abstract void unmarkReusable(); } - public final class MultihomePlainSocketFactory implements org.apache.http.conn.scheme.SocketFactory { + public final deprecated class MultihomePlainSocketFactory implements org.apache.http.conn.scheme.SocketFactory { method public java.net.Socket connectSocket(java.net.Socket, java.lang.String, int, java.net.InetAddress, int, org.apache.http.params.HttpParams) throws java.io.IOException; method public java.net.Socket createSocket(); method public static org.apache.http.conn.MultihomePlainSocketFactory getSocketFactory(); method public final boolean isSecure(java.net.Socket) throws java.lang.IllegalArgumentException; } - public abstract interface OperatedClientConnection implements org.apache.http.HttpClientConnection org.apache.http.HttpInetConnection { + public abstract deprecated interface OperatedClientConnection implements org.apache.http.HttpClientConnection org.apache.http.HttpInetConnection { method public abstract java.net.Socket getSocket(); method public abstract org.apache.http.HttpHost getTargetHost(); method public abstract boolean isSecure(); @@ -54917,29 +55365,29 @@ package org.apache.http.conn { package org.apache.http.conn.params { - public abstract interface ConnConnectionPNames { + public abstract deprecated interface ConnConnectionPNames { field public static final java.lang.String MAX_STATUS_LINE_GARBAGE = "http.connection.max-status-line-garbage"; } - public class ConnConnectionParamBean extends org.apache.http.params.HttpAbstractParamBean { + public deprecated class ConnConnectionParamBean extends org.apache.http.params.HttpAbstractParamBean { ctor public ConnConnectionParamBean(org.apache.http.params.HttpParams); method public void setMaxStatusLineGarbage(int); } - public abstract interface ConnManagerPNames { + public abstract deprecated interface ConnManagerPNames { field public static final java.lang.String MAX_CONNECTIONS_PER_ROUTE = "http.conn-manager.max-per-route"; field public static final java.lang.String MAX_TOTAL_CONNECTIONS = "http.conn-manager.max-total"; field public static final java.lang.String TIMEOUT = "http.conn-manager.timeout"; } - public class ConnManagerParamBean extends org.apache.http.params.HttpAbstractParamBean { + public deprecated class ConnManagerParamBean extends org.apache.http.params.HttpAbstractParamBean { ctor public ConnManagerParamBean(org.apache.http.params.HttpParams); method public void setConnectionsPerRoute(org.apache.http.conn.params.ConnPerRouteBean); method public void setMaxTotalConnections(int); method public void setTimeout(long); } - public final class ConnManagerParams implements org.apache.http.conn.params.ConnManagerPNames { + public final deprecated class ConnManagerParams implements org.apache.http.conn.params.ConnManagerPNames { ctor public ConnManagerParams(); method public static org.apache.http.conn.params.ConnPerRoute getMaxConnectionsPerRoute(org.apache.http.params.HttpParams); method public static int getMaxTotalConnections(org.apache.http.params.HttpParams); @@ -54950,11 +55398,11 @@ package org.apache.http.conn.params { field public static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 20; // 0x14 } - public abstract interface ConnPerRoute { + public abstract deprecated interface ConnPerRoute { method public abstract int getMaxForRoute(org.apache.http.conn.routing.HttpRoute); } - public final class ConnPerRouteBean implements org.apache.http.conn.params.ConnPerRoute { + public final deprecated class ConnPerRouteBean implements org.apache.http.conn.params.ConnPerRoute { ctor public ConnPerRouteBean(int); ctor public ConnPerRouteBean(); method public int getDefaultMax(); @@ -54965,20 +55413,20 @@ package org.apache.http.conn.params { field public static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 2; // 0x2 } - public abstract interface ConnRoutePNames { + public abstract deprecated interface ConnRoutePNames { field public static final java.lang.String DEFAULT_PROXY = "http.route.default-proxy"; field public static final java.lang.String FORCED_ROUTE = "http.route.forced-route"; field public static final java.lang.String LOCAL_ADDRESS = "http.route.local-address"; } - public class ConnRouteParamBean extends org.apache.http.params.HttpAbstractParamBean { + public deprecated class ConnRouteParamBean extends org.apache.http.params.HttpAbstractParamBean { ctor public ConnRouteParamBean(org.apache.http.params.HttpParams); method public void setDefaultProxy(org.apache.http.HttpHost); method public void setForcedRoute(org.apache.http.conn.routing.HttpRoute); method public void setLocalAddress(java.net.InetAddress); } - public class ConnRouteParams implements org.apache.http.conn.params.ConnRoutePNames { + public deprecated class ConnRouteParams implements org.apache.http.conn.params.ConnRoutePNames { method public static org.apache.http.HttpHost getDefaultProxy(org.apache.http.params.HttpParams); method public static org.apache.http.conn.routing.HttpRoute getForcedRoute(org.apache.http.params.HttpParams); method public static java.net.InetAddress getLocalAddress(org.apache.http.params.HttpParams); @@ -54993,7 +55441,7 @@ package org.apache.http.conn.params { package org.apache.http.conn.routing { - public class BasicRouteDirector implements org.apache.http.conn.routing.HttpRouteDirector { + public deprecated class BasicRouteDirector implements org.apache.http.conn.routing.HttpRouteDirector { ctor public BasicRouteDirector(); method protected int directStep(org.apache.http.conn.routing.RouteInfo, org.apache.http.conn.routing.RouteInfo); method protected int firstStep(org.apache.http.conn.routing.RouteInfo); @@ -55001,7 +55449,7 @@ package org.apache.http.conn.routing { method protected int proxiedStep(org.apache.http.conn.routing.RouteInfo, org.apache.http.conn.routing.RouteInfo); } - public final class HttpRoute implements java.lang.Cloneable org.apache.http.conn.routing.RouteInfo { + public final deprecated class HttpRoute implements java.lang.Cloneable org.apache.http.conn.routing.RouteInfo { ctor public HttpRoute(org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.HttpHost[], boolean, org.apache.http.conn.routing.RouteInfo.TunnelType, org.apache.http.conn.routing.RouteInfo.LayerType); ctor public HttpRoute(org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.HttpHost, boolean, org.apache.http.conn.routing.RouteInfo.TunnelType, org.apache.http.conn.routing.RouteInfo.LayerType); ctor public HttpRoute(org.apache.http.HttpHost, java.net.InetAddress, boolean); @@ -55023,7 +55471,7 @@ package org.apache.http.conn.routing { method public final java.lang.String toString(); } - public abstract interface HttpRouteDirector { + public abstract deprecated interface HttpRouteDirector { method public abstract int nextStep(org.apache.http.conn.routing.RouteInfo, org.apache.http.conn.routing.RouteInfo); field public static final int COMPLETE = 0; // 0x0 field public static final int CONNECT_PROXY = 2; // 0x2 @@ -55034,11 +55482,11 @@ package org.apache.http.conn.routing { field public static final int UNREACHABLE = -1; // 0xffffffff } - public abstract interface HttpRoutePlanner { + public abstract deprecated interface HttpRoutePlanner { method public abstract org.apache.http.conn.routing.HttpRoute determineRoute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException; } - public abstract interface RouteInfo { + public abstract deprecated interface RouteInfo { method public abstract int getHopCount(); method public abstract org.apache.http.HttpHost getHopTarget(int); method public abstract org.apache.http.conn.routing.RouteInfo.LayerType getLayerType(); @@ -55065,7 +55513,7 @@ package org.apache.http.conn.routing { enum_constant public static final org.apache.http.conn.routing.RouteInfo.TunnelType TUNNELLED; } - public final class RouteTracker implements java.lang.Cloneable org.apache.http.conn.routing.RouteInfo { + public final deprecated class RouteTracker implements java.lang.Cloneable org.apache.http.conn.routing.RouteInfo { ctor public RouteTracker(org.apache.http.HttpHost, java.net.InetAddress); ctor public RouteTracker(org.apache.http.conn.routing.HttpRoute); method public java.lang.Object clone() throws java.lang.CloneNotSupportedException; @@ -55095,15 +55543,15 @@ package org.apache.http.conn.routing { package org.apache.http.conn.scheme { - public abstract interface HostNameResolver { + public abstract deprecated interface HostNameResolver { method public abstract java.net.InetAddress resolve(java.lang.String) throws java.io.IOException; } - public abstract interface LayeredSocketFactory implements org.apache.http.conn.scheme.SocketFactory { + public abstract deprecated interface LayeredSocketFactory implements org.apache.http.conn.scheme.SocketFactory { method public abstract java.net.Socket createSocket(java.net.Socket, java.lang.String, int, boolean) throws java.io.IOException, java.net.UnknownHostException; } - public final class PlainSocketFactory implements org.apache.http.conn.scheme.SocketFactory { + public final deprecated class PlainSocketFactory implements org.apache.http.conn.scheme.SocketFactory { ctor public PlainSocketFactory(org.apache.http.conn.scheme.HostNameResolver); ctor public PlainSocketFactory(); method public java.net.Socket connectSocket(java.net.Socket, java.lang.String, int, java.net.InetAddress, int, org.apache.http.params.HttpParams) throws java.io.IOException; @@ -55112,7 +55560,7 @@ package org.apache.http.conn.scheme { method public final boolean isSecure(java.net.Socket) throws java.lang.IllegalArgumentException; } - public final class Scheme { + public final deprecated class Scheme { ctor public Scheme(java.lang.String, org.apache.http.conn.scheme.SocketFactory, int); method public final boolean equals(java.lang.Object); method public final int getDefaultPort(); @@ -55123,7 +55571,7 @@ package org.apache.http.conn.scheme { method public final java.lang.String toString(); } - public final class SchemeRegistry { + public final deprecated class SchemeRegistry { ctor public SchemeRegistry(); method public final synchronized org.apache.http.conn.scheme.Scheme get(java.lang.String); method public final synchronized org.apache.http.conn.scheme.Scheme getScheme(java.lang.String); @@ -55134,7 +55582,7 @@ package org.apache.http.conn.scheme { method public final synchronized org.apache.http.conn.scheme.Scheme unregister(java.lang.String); } - public abstract interface SocketFactory { + public abstract deprecated interface SocketFactory { method public abstract java.net.Socket connectSocket(java.net.Socket, java.lang.String, int, java.net.InetAddress, int, org.apache.http.params.HttpParams) throws org.apache.http.conn.ConnectTimeoutException, java.io.IOException, java.net.UnknownHostException; method public abstract java.net.Socket createSocket() throws java.io.IOException; method public abstract boolean isSecure(java.net.Socket) throws java.lang.IllegalArgumentException; @@ -55144,7 +55592,7 @@ package org.apache.http.conn.scheme { package org.apache.http.conn.ssl { - public abstract class AbstractVerifier implements org.apache.http.conn.ssl.X509HostnameVerifier { + public abstract deprecated class AbstractVerifier implements org.apache.http.conn.ssl.X509HostnameVerifier { ctor public AbstractVerifier(); method public static boolean acceptableCountryWildcard(java.lang.String); method public static int countDots(java.lang.String); @@ -55156,19 +55604,19 @@ package org.apache.http.conn.ssl { method public final void verify(java.lang.String, java.lang.String[], java.lang.String[], boolean) throws javax.net.ssl.SSLException; } - public class AllowAllHostnameVerifier extends org.apache.http.conn.ssl.AbstractVerifier { + public deprecated class AllowAllHostnameVerifier extends org.apache.http.conn.ssl.AbstractVerifier { ctor public AllowAllHostnameVerifier(); method public final java.lang.String toString(); method public final void verify(java.lang.String, java.lang.String[], java.lang.String[]); } - public class BrowserCompatHostnameVerifier extends org.apache.http.conn.ssl.AbstractVerifier { + public deprecated class BrowserCompatHostnameVerifier extends org.apache.http.conn.ssl.AbstractVerifier { ctor public BrowserCompatHostnameVerifier(); method public final java.lang.String toString(); method public final void verify(java.lang.String, java.lang.String[], java.lang.String[]) throws javax.net.ssl.SSLException; } - public class SSLSocketFactory implements org.apache.http.conn.scheme.LayeredSocketFactory { + public deprecated class SSLSocketFactory implements org.apache.http.conn.scheme.LayeredSocketFactory { ctor public SSLSocketFactory(java.lang.String, java.security.KeyStore, java.lang.String, java.security.KeyStore, java.security.SecureRandom, org.apache.http.conn.scheme.HostNameResolver) throws java.security.KeyManagementException, java.security.KeyStoreException, java.security.NoSuchAlgorithmException, java.security.UnrecoverableKeyException; ctor public SSLSocketFactory(java.security.KeyStore, java.lang.String, java.security.KeyStore) throws java.security.KeyManagementException, java.security.KeyStoreException, java.security.NoSuchAlgorithmException, java.security.UnrecoverableKeyException; ctor public SSLSocketFactory(java.security.KeyStore, java.lang.String) throws java.security.KeyManagementException, java.security.KeyStoreException, java.security.NoSuchAlgorithmException, java.security.UnrecoverableKeyException; @@ -55188,13 +55636,13 @@ package org.apache.http.conn.ssl { field public static final java.lang.String TLS = "TLS"; } - public class StrictHostnameVerifier extends org.apache.http.conn.ssl.AbstractVerifier { + public deprecated class StrictHostnameVerifier extends org.apache.http.conn.ssl.AbstractVerifier { ctor public StrictHostnameVerifier(); method public final java.lang.String toString(); method public final void verify(java.lang.String, java.lang.String[], java.lang.String[]) throws javax.net.ssl.SSLException; } - public abstract interface X509HostnameVerifier implements javax.net.ssl.HostnameVerifier { + public abstract deprecated interface X509HostnameVerifier implements javax.net.ssl.HostnameVerifier { method public abstract boolean verify(java.lang.String, javax.net.ssl.SSLSession); method public abstract void verify(java.lang.String, javax.net.ssl.SSLSocket) throws java.io.IOException; method public abstract void verify(java.lang.String, java.security.cert.X509Certificate) throws javax.net.ssl.SSLException; @@ -55205,7 +55653,7 @@ package org.apache.http.conn.ssl { package org.apache.http.conn.util { - public class InetAddressUtils { + public deprecated class InetAddressUtils { method public static boolean isIPv4Address(java.lang.String); method public static boolean isIPv6Address(java.lang.String); method public static boolean isIPv6HexCompressedAddress(java.lang.String); @@ -55216,7 +55664,7 @@ package org.apache.http.conn.util { package org.apache.http.cookie { - public abstract interface ClientCookie implements org.apache.http.cookie.Cookie { + public abstract deprecated interface ClientCookie implements org.apache.http.cookie.Cookie { method public abstract boolean containsAttribute(java.lang.String); method public abstract java.lang.String getAttribute(java.lang.String); field public static final java.lang.String COMMENTURL_ATTR = "commenturl"; @@ -55231,7 +55679,7 @@ package org.apache.http.cookie { field public static final java.lang.String VERSION_ATTR = "version"; } - public abstract interface Cookie { + public abstract deprecated interface Cookie { method public abstract java.lang.String getComment(); method public abstract java.lang.String getCommentURL(); method public abstract java.lang.String getDomain(); @@ -55246,18 +55694,18 @@ package org.apache.http.cookie { method public abstract boolean isSecure(); } - public abstract interface CookieAttributeHandler { + public abstract deprecated interface CookieAttributeHandler { method public abstract boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin); method public abstract void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException; method public abstract void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException; } - public class CookieIdentityComparator implements java.util.Comparator java.io.Serializable { + public deprecated class CookieIdentityComparator implements java.util.Comparator java.io.Serializable { ctor public CookieIdentityComparator(); method public int compare(org.apache.http.cookie.Cookie, org.apache.http.cookie.Cookie); } - public final class CookieOrigin { + public final deprecated class CookieOrigin { ctor public CookieOrigin(java.lang.String, int, java.lang.String, boolean); method public java.lang.String getHost(); method public java.lang.String getPath(); @@ -55265,12 +55713,12 @@ package org.apache.http.cookie { method public boolean isSecure(); } - public class CookiePathComparator implements java.util.Comparator java.io.Serializable { + public deprecated class CookiePathComparator implements java.util.Comparator java.io.Serializable { ctor public CookiePathComparator(); method public int compare(org.apache.http.cookie.Cookie, org.apache.http.cookie.Cookie); } - public abstract interface CookieSpec { + public abstract deprecated interface CookieSpec { method public abstract java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>); method public abstract int getVersion(); method public abstract org.apache.http.Header getVersionHeader(); @@ -55279,11 +55727,11 @@ package org.apache.http.cookie { method public abstract void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException; } - public abstract interface CookieSpecFactory { + public abstract deprecated interface CookieSpecFactory { method public abstract org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams); } - public final class CookieSpecRegistry { + public final deprecated class CookieSpecRegistry { ctor public CookieSpecRegistry(); method public synchronized org.apache.http.cookie.CookieSpec getCookieSpec(java.lang.String, org.apache.http.params.HttpParams) throws java.lang.IllegalStateException; method public synchronized org.apache.http.cookie.CookieSpec getCookieSpec(java.lang.String) throws java.lang.IllegalStateException; @@ -55293,20 +55741,20 @@ package org.apache.http.cookie { method public synchronized void unregister(java.lang.String); } - public class MalformedCookieException extends org.apache.http.ProtocolException { + public deprecated class MalformedCookieException extends org.apache.http.ProtocolException { ctor public MalformedCookieException(); ctor public MalformedCookieException(java.lang.String); ctor public MalformedCookieException(java.lang.String, java.lang.Throwable); } - public abstract interface SM { + public abstract deprecated interface SM { field public static final java.lang.String COOKIE = "Cookie"; field public static final java.lang.String COOKIE2 = "Cookie2"; field public static final java.lang.String SET_COOKIE = "Set-Cookie"; field public static final java.lang.String SET_COOKIE2 = "Set-Cookie2"; } - public abstract interface SetCookie implements org.apache.http.cookie.Cookie { + public abstract deprecated interface SetCookie implements org.apache.http.cookie.Cookie { method public abstract void setComment(java.lang.String); method public abstract void setDomain(java.lang.String); method public abstract void setExpiryDate(java.util.Date); @@ -55316,7 +55764,7 @@ package org.apache.http.cookie { method public abstract void setVersion(int); } - public abstract interface SetCookie2 implements org.apache.http.cookie.SetCookie { + public abstract deprecated interface SetCookie2 implements org.apache.http.cookie.SetCookie { method public abstract void setCommentURL(java.lang.String); method public abstract void setDiscard(boolean); method public abstract void setPorts(int[]); @@ -55326,12 +55774,12 @@ package org.apache.http.cookie { package org.apache.http.cookie.params { - public abstract interface CookieSpecPNames { + public abstract deprecated interface CookieSpecPNames { field public static final java.lang.String DATE_PATTERNS = "http.protocol.cookie-datepatterns"; field public static final java.lang.String SINGLE_COOKIE_HEADER = "http.protocol.single-cookie-header"; } - public class CookieSpecParamBean extends org.apache.http.params.HttpAbstractParamBean { + public deprecated class CookieSpecParamBean extends org.apache.http.params.HttpAbstractParamBean { ctor public CookieSpecParamBean(org.apache.http.params.HttpParams); method public void setDatePatterns(java.util.Collection<java.lang.String>); method public void setSingleHeader(boolean); @@ -55341,7 +55789,7 @@ package org.apache.http.cookie.params { package org.apache.http.entity { - public abstract class AbstractHttpEntity implements org.apache.http.HttpEntity { + public abstract deprecated class AbstractHttpEntity implements org.apache.http.HttpEntity { ctor protected AbstractHttpEntity(); method public void consumeContent() throws java.io.IOException, java.lang.UnsupportedOperationException; method public org.apache.http.Header getContentEncoding(); @@ -55357,7 +55805,7 @@ package org.apache.http.entity { field protected org.apache.http.Header contentType; } - public class BasicHttpEntity extends org.apache.http.entity.AbstractHttpEntity { + public deprecated class BasicHttpEntity extends org.apache.http.entity.AbstractHttpEntity { ctor public BasicHttpEntity(); method public java.io.InputStream getContent() throws java.lang.IllegalStateException; method public long getContentLength(); @@ -55368,11 +55816,11 @@ package org.apache.http.entity { method public void writeTo(java.io.OutputStream) throws java.io.IOException; } - public class BufferedHttpEntity extends org.apache.http.entity.HttpEntityWrapper { + public deprecated class BufferedHttpEntity extends org.apache.http.entity.HttpEntityWrapper { ctor public BufferedHttpEntity(org.apache.http.HttpEntity) throws java.io.IOException; } - public class ByteArrayEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable { + public deprecated class ByteArrayEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable { ctor public ByteArrayEntity(byte[]); method public java.lang.Object clone() throws java.lang.CloneNotSupportedException; method public java.io.InputStream getContent(); @@ -55383,17 +55831,17 @@ package org.apache.http.entity { field protected final byte[] content; } - public abstract interface ContentLengthStrategy { + public abstract deprecated interface ContentLengthStrategy { method public abstract long determineLength(org.apache.http.HttpMessage) throws org.apache.http.HttpException; field public static final int CHUNKED = -2; // 0xfffffffe field public static final int IDENTITY = -1; // 0xffffffff } - public abstract interface ContentProducer { + public abstract deprecated interface ContentProducer { method public abstract void writeTo(java.io.OutputStream) throws java.io.IOException; } - public class EntityTemplate extends org.apache.http.entity.AbstractHttpEntity { + public deprecated class EntityTemplate extends org.apache.http.entity.AbstractHttpEntity { ctor public EntityTemplate(org.apache.http.entity.ContentProducer); method public java.io.InputStream getContent(); method public long getContentLength(); @@ -55402,7 +55850,7 @@ package org.apache.http.entity { method public void writeTo(java.io.OutputStream) throws java.io.IOException; } - public class FileEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable { + public deprecated class FileEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable { ctor public FileEntity(java.io.File, java.lang.String); method public java.lang.Object clone() throws java.lang.CloneNotSupportedException; method public java.io.InputStream getContent() throws java.io.IOException; @@ -55413,7 +55861,7 @@ package org.apache.http.entity { field protected final java.io.File file; } - public class HttpEntityWrapper implements org.apache.http.HttpEntity { + public deprecated class HttpEntityWrapper implements org.apache.http.HttpEntity { ctor public HttpEntityWrapper(org.apache.http.HttpEntity); method public void consumeContent() throws java.io.IOException; method public java.io.InputStream getContent() throws java.io.IOException; @@ -55427,7 +55875,7 @@ package org.apache.http.entity { field protected org.apache.http.HttpEntity wrappedEntity; } - public class InputStreamEntity extends org.apache.http.entity.AbstractHttpEntity { + public deprecated class InputStreamEntity extends org.apache.http.entity.AbstractHttpEntity { ctor public InputStreamEntity(java.io.InputStream, long); method public java.io.InputStream getContent() throws java.io.IOException; method public long getContentLength(); @@ -55436,7 +55884,7 @@ package org.apache.http.entity { method public void writeTo(java.io.OutputStream) throws java.io.IOException; } - public class SerializableEntity extends org.apache.http.entity.AbstractHttpEntity { + public deprecated class SerializableEntity extends org.apache.http.entity.AbstractHttpEntity { ctor public SerializableEntity(java.io.Serializable, boolean) throws java.io.IOException; method public java.io.InputStream getContent() throws java.io.IOException, java.lang.IllegalStateException; method public long getContentLength(); @@ -55445,7 +55893,7 @@ package org.apache.http.entity { method public void writeTo(java.io.OutputStream) throws java.io.IOException; } - public class StringEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable { + public deprecated class StringEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable { ctor public StringEntity(java.lang.String, java.lang.String) throws java.io.UnsupportedEncodingException; ctor public StringEntity(java.lang.String) throws java.io.UnsupportedEncodingException; method public java.lang.Object clone() throws java.lang.CloneNotSupportedException; @@ -55461,7 +55909,7 @@ package org.apache.http.entity { package org.apache.http.impl { - public abstract class AbstractHttpClientConnection implements org.apache.http.HttpClientConnection { + public abstract deprecated class AbstractHttpClientConnection implements org.apache.http.HttpClientConnection { ctor public AbstractHttpClientConnection(); method protected abstract void assertOpen() throws java.lang.IllegalStateException; method protected org.apache.http.impl.entity.EntityDeserializer createEntityDeserializer(); @@ -55481,7 +55929,7 @@ package org.apache.http.impl { method public void sendRequestHeader(org.apache.http.HttpRequest) throws org.apache.http.HttpException, java.io.IOException; } - public abstract class AbstractHttpServerConnection implements org.apache.http.HttpServerConnection { + public abstract deprecated class AbstractHttpServerConnection implements org.apache.http.HttpServerConnection { ctor public AbstractHttpServerConnection(); method protected abstract void assertOpen() throws java.lang.IllegalStateException; method protected org.apache.http.impl.entity.EntityDeserializer createEntityDeserializer(); @@ -55500,24 +55948,24 @@ package org.apache.http.impl { method public void sendResponseHeader(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException; } - public class DefaultConnectionReuseStrategy implements org.apache.http.ConnectionReuseStrategy { + public deprecated class DefaultConnectionReuseStrategy implements org.apache.http.ConnectionReuseStrategy { ctor public DefaultConnectionReuseStrategy(); method protected org.apache.http.TokenIterator createTokenIterator(org.apache.http.HeaderIterator); method public boolean keepAlive(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext); } - public class DefaultHttpClientConnection extends org.apache.http.impl.SocketHttpClientConnection { + public deprecated class DefaultHttpClientConnection extends org.apache.http.impl.SocketHttpClientConnection { ctor public DefaultHttpClientConnection(); method public void bind(java.net.Socket, org.apache.http.params.HttpParams) throws java.io.IOException; } - public class DefaultHttpRequestFactory implements org.apache.http.HttpRequestFactory { + public deprecated class DefaultHttpRequestFactory implements org.apache.http.HttpRequestFactory { ctor public DefaultHttpRequestFactory(); method public org.apache.http.HttpRequest newHttpRequest(org.apache.http.RequestLine) throws org.apache.http.MethodNotSupportedException; method public org.apache.http.HttpRequest newHttpRequest(java.lang.String, java.lang.String) throws org.apache.http.MethodNotSupportedException; } - public class DefaultHttpResponseFactory implements org.apache.http.HttpResponseFactory { + public deprecated class DefaultHttpResponseFactory implements org.apache.http.HttpResponseFactory { ctor public DefaultHttpResponseFactory(org.apache.http.ReasonPhraseCatalog); ctor public DefaultHttpResponseFactory(); method protected java.util.Locale determineLocale(org.apache.http.protocol.HttpContext); @@ -55526,18 +55974,18 @@ package org.apache.http.impl { field protected final org.apache.http.ReasonPhraseCatalog reasonCatalog; } - public class DefaultHttpServerConnection extends org.apache.http.impl.SocketHttpServerConnection { + public deprecated class DefaultHttpServerConnection extends org.apache.http.impl.SocketHttpServerConnection { ctor public DefaultHttpServerConnection(); method public void bind(java.net.Socket, org.apache.http.params.HttpParams) throws java.io.IOException; } - public class EnglishReasonPhraseCatalog implements org.apache.http.ReasonPhraseCatalog { + public deprecated class EnglishReasonPhraseCatalog implements org.apache.http.ReasonPhraseCatalog { ctor protected EnglishReasonPhraseCatalog(); method public java.lang.String getReason(int, java.util.Locale); field public static final org.apache.http.impl.EnglishReasonPhraseCatalog INSTANCE; } - public class HttpConnectionMetricsImpl implements org.apache.http.HttpConnectionMetrics { + public deprecated class HttpConnectionMetricsImpl implements org.apache.http.HttpConnectionMetrics { ctor public HttpConnectionMetricsImpl(org.apache.http.io.HttpTransportMetrics, org.apache.http.io.HttpTransportMetrics); method public java.lang.Object getMetric(java.lang.String); method public long getReceivedBytesCount(); @@ -55554,12 +56002,12 @@ package org.apache.http.impl { field public static final java.lang.String SENT_BYTES_COUNT = "http.sent-bytes-count"; } - public class NoConnectionReuseStrategy implements org.apache.http.ConnectionReuseStrategy { + public deprecated class NoConnectionReuseStrategy implements org.apache.http.ConnectionReuseStrategy { ctor public NoConnectionReuseStrategy(); method public boolean keepAlive(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext); } - public class SocketHttpClientConnection extends org.apache.http.impl.AbstractHttpClientConnection implements org.apache.http.HttpInetConnection { + public deprecated class SocketHttpClientConnection extends org.apache.http.impl.AbstractHttpClientConnection implements org.apache.http.HttpInetConnection { ctor public SocketHttpClientConnection(); method protected void assertNotOpen(); method protected void assertOpen(); @@ -55578,7 +56026,7 @@ package org.apache.http.impl { method public void shutdown() throws java.io.IOException; } - public class SocketHttpServerConnection extends org.apache.http.impl.AbstractHttpServerConnection implements org.apache.http.HttpInetConnection { + public deprecated class SocketHttpServerConnection extends org.apache.http.impl.AbstractHttpServerConnection implements org.apache.http.HttpInetConnection { ctor public SocketHttpServerConnection(); method protected void assertNotOpen(); method protected void assertOpen(); @@ -55601,14 +56049,14 @@ package org.apache.http.impl { package org.apache.http.impl.auth { - public abstract class AuthSchemeBase implements org.apache.http.auth.AuthScheme { + public abstract deprecated class AuthSchemeBase implements org.apache.http.auth.AuthScheme { ctor public AuthSchemeBase(); method public boolean isProxy(); method protected abstract void parseChallenge(org.apache.http.util.CharArrayBuffer, int, int) throws org.apache.http.auth.MalformedChallengeException; method public void processChallenge(org.apache.http.Header) throws org.apache.http.auth.MalformedChallengeException; } - public class BasicScheme extends org.apache.http.impl.auth.RFC2617Scheme { + public deprecated class BasicScheme extends org.apache.http.impl.auth.RFC2617Scheme { ctor public BasicScheme(); method public org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException; method public static org.apache.http.Header authenticate(org.apache.http.auth.Credentials, java.lang.String, boolean); @@ -55617,12 +56065,12 @@ package org.apache.http.impl.auth { method public boolean isConnectionBased(); } - public class BasicSchemeFactory implements org.apache.http.auth.AuthSchemeFactory { + public deprecated class BasicSchemeFactory implements org.apache.http.auth.AuthSchemeFactory { ctor public BasicSchemeFactory(); method public org.apache.http.auth.AuthScheme newInstance(org.apache.http.params.HttpParams); } - public class DigestScheme extends org.apache.http.impl.auth.RFC2617Scheme { + public deprecated class DigestScheme extends org.apache.http.impl.auth.RFC2617Scheme { ctor public DigestScheme(); method public org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException; method public static java.lang.String createCnonce(); @@ -55632,23 +56080,23 @@ package org.apache.http.impl.auth { method public void overrideParamter(java.lang.String, java.lang.String); } - public class DigestSchemeFactory implements org.apache.http.auth.AuthSchemeFactory { + public deprecated class DigestSchemeFactory implements org.apache.http.auth.AuthSchemeFactory { ctor public DigestSchemeFactory(); method public org.apache.http.auth.AuthScheme newInstance(org.apache.http.params.HttpParams); } - public abstract interface NTLMEngine { + public abstract deprecated interface NTLMEngine { method public abstract java.lang.String generateType1Msg(java.lang.String, java.lang.String) throws org.apache.http.impl.auth.NTLMEngineException; method public abstract java.lang.String generateType3Msg(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws org.apache.http.impl.auth.NTLMEngineException; } - public class NTLMEngineException extends org.apache.http.auth.AuthenticationException { + public deprecated class NTLMEngineException extends org.apache.http.auth.AuthenticationException { ctor public NTLMEngineException(); ctor public NTLMEngineException(java.lang.String); ctor public NTLMEngineException(java.lang.String, java.lang.Throwable); } - public class NTLMScheme extends org.apache.http.impl.auth.AuthSchemeBase { + public deprecated class NTLMScheme extends org.apache.http.impl.auth.AuthSchemeBase { ctor public NTLMScheme(org.apache.http.impl.auth.NTLMEngine); method public org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException; method public java.lang.String getParameter(java.lang.String); @@ -55659,7 +56107,7 @@ package org.apache.http.impl.auth { method protected void parseChallenge(org.apache.http.util.CharArrayBuffer, int, int) throws org.apache.http.auth.MalformedChallengeException; } - public abstract class RFC2617Scheme extends org.apache.http.impl.auth.AuthSchemeBase { + public abstract deprecated class RFC2617Scheme extends org.apache.http.impl.auth.AuthSchemeBase { ctor public RFC2617Scheme(); method public java.lang.String getParameter(java.lang.String); method protected java.util.Map<java.lang.String, java.lang.String> getParameters(); @@ -55667,7 +56115,7 @@ package org.apache.http.impl.auth { method protected void parseChallenge(org.apache.http.util.CharArrayBuffer, int, int) throws org.apache.http.auth.MalformedChallengeException; } - public class UnsupportedDigestAlgorithmException extends java.lang.RuntimeException { + public deprecated class UnsupportedDigestAlgorithmException extends java.lang.RuntimeException { ctor public UnsupportedDigestAlgorithmException(); ctor public UnsupportedDigestAlgorithmException(java.lang.String); ctor public UnsupportedDigestAlgorithmException(java.lang.String, java.lang.Throwable); @@ -55677,14 +56125,14 @@ package org.apache.http.impl.auth { package org.apache.http.impl.client { - public abstract class AbstractAuthenticationHandler implements org.apache.http.client.AuthenticationHandler { + public abstract deprecated class AbstractAuthenticationHandler implements org.apache.http.client.AuthenticationHandler { ctor public AbstractAuthenticationHandler(); method protected java.util.List<java.lang.String> getAuthPreferences(); method protected java.util.Map<java.lang.String, org.apache.http.Header> parseChallenges(org.apache.http.Header[]) throws org.apache.http.auth.MalformedChallengeException; method public org.apache.http.auth.AuthScheme selectScheme(java.util.Map<java.lang.String, org.apache.http.Header>, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.AuthenticationException; } - public abstract class AbstractHttpClient implements org.apache.http.client.HttpClient { + public abstract deprecated class AbstractHttpClient implements org.apache.http.client.HttpClient { ctor protected AbstractHttpClient(org.apache.http.conn.ClientConnectionManager, org.apache.http.params.HttpParams); method public synchronized void addRequestInterceptor(org.apache.http.HttpRequestInterceptor); method public synchronized void addRequestInterceptor(org.apache.http.HttpRequestInterceptor, int); @@ -55756,7 +56204,7 @@ package org.apache.http.impl.client { method public synchronized void setUserTokenHandler(org.apache.http.client.UserTokenHandler); } - public class BasicCookieStore implements org.apache.http.client.CookieStore { + public deprecated class BasicCookieStore implements org.apache.http.client.CookieStore { ctor public BasicCookieStore(); method public synchronized void addCookie(org.apache.http.cookie.Cookie); method public synchronized void addCookies(org.apache.http.cookie.Cookie[]); @@ -55765,19 +56213,19 @@ package org.apache.http.impl.client { method public synchronized java.util.List<org.apache.http.cookie.Cookie> getCookies(); } - public class BasicCredentialsProvider implements org.apache.http.client.CredentialsProvider { + public deprecated class BasicCredentialsProvider implements org.apache.http.client.CredentialsProvider { ctor public BasicCredentialsProvider(); method public synchronized void clear(); method public synchronized org.apache.http.auth.Credentials getCredentials(org.apache.http.auth.AuthScope); method public synchronized void setCredentials(org.apache.http.auth.AuthScope, org.apache.http.auth.Credentials); } - public class BasicResponseHandler implements org.apache.http.client.ResponseHandler { + public deprecated class BasicResponseHandler implements org.apache.http.client.ResponseHandler { ctor public BasicResponseHandler(); method public java.lang.String handleResponse(org.apache.http.HttpResponse) throws org.apache.http.client.HttpResponseException, java.io.IOException; } - public class ClientParamsStack extends org.apache.http.params.AbstractHttpParams { + public deprecated class ClientParamsStack extends org.apache.http.params.AbstractHttpParams { ctor public ClientParamsStack(org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams); ctor public ClientParamsStack(org.apache.http.impl.client.ClientParamsStack); ctor public ClientParamsStack(org.apache.http.impl.client.ClientParamsStack, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams); @@ -55795,12 +56243,12 @@ package org.apache.http.impl.client { field protected final org.apache.http.params.HttpParams requestParams; } - public class DefaultConnectionKeepAliveStrategy implements org.apache.http.conn.ConnectionKeepAliveStrategy { + public deprecated class DefaultConnectionKeepAliveStrategy implements org.apache.http.conn.ConnectionKeepAliveStrategy { ctor public DefaultConnectionKeepAliveStrategy(); method public long getKeepAliveDuration(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext); } - public class DefaultHttpClient extends org.apache.http.impl.client.AbstractHttpClient { + public deprecated class DefaultHttpClient extends org.apache.http.impl.client.AbstractHttpClient { ctor public DefaultHttpClient(org.apache.http.conn.ClientConnectionManager, org.apache.http.params.HttpParams); ctor public DefaultHttpClient(org.apache.http.params.HttpParams); ctor public DefaultHttpClient(); @@ -55823,7 +56271,7 @@ package org.apache.http.impl.client { method protected org.apache.http.client.UserTokenHandler createUserTokenHandler(); } - public class DefaultHttpRequestRetryHandler implements org.apache.http.client.HttpRequestRetryHandler { + public deprecated class DefaultHttpRequestRetryHandler implements org.apache.http.client.HttpRequestRetryHandler { ctor public DefaultHttpRequestRetryHandler(int, boolean); ctor public DefaultHttpRequestRetryHandler(); method public int getRetryCount(); @@ -55831,19 +56279,19 @@ package org.apache.http.impl.client { method public boolean retryRequest(java.io.IOException, int, org.apache.http.protocol.HttpContext); } - public class DefaultProxyAuthenticationHandler extends org.apache.http.impl.client.AbstractAuthenticationHandler { + public deprecated class DefaultProxyAuthenticationHandler extends org.apache.http.impl.client.AbstractAuthenticationHandler { ctor public DefaultProxyAuthenticationHandler(); method public java.util.Map<java.lang.String, org.apache.http.Header> getChallenges(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.MalformedChallengeException; method public boolean isAuthenticationRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext); } - public class DefaultRedirectHandler implements org.apache.http.client.RedirectHandler { + public deprecated class DefaultRedirectHandler implements org.apache.http.client.RedirectHandler { ctor public DefaultRedirectHandler(); method public java.net.URI getLocationURI(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.ProtocolException; method public boolean isRedirectRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext); } - public class DefaultRequestDirector implements org.apache.http.client.RequestDirector { + public deprecated class DefaultRequestDirector implements org.apache.http.client.RequestDirector { ctor public DefaultRequestDirector(org.apache.http.protocol.HttpRequestExecutor, org.apache.http.conn.ClientConnectionManager, org.apache.http.ConnectionReuseStrategy, org.apache.http.conn.ConnectionKeepAliveStrategy, org.apache.http.conn.routing.HttpRoutePlanner, org.apache.http.protocol.HttpProcessor, org.apache.http.client.HttpRequestRetryHandler, org.apache.http.client.RedirectHandler, org.apache.http.client.AuthenticationHandler, org.apache.http.client.AuthenticationHandler, org.apache.http.client.UserTokenHandler, org.apache.http.params.HttpParams); method protected org.apache.http.HttpRequest createConnectRequest(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext); method protected boolean createTunnelToProxy(org.apache.http.conn.routing.HttpRoute, int, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; @@ -55866,32 +56314,32 @@ package org.apache.http.impl.client { field protected final org.apache.http.conn.routing.HttpRoutePlanner routePlanner; } - public class DefaultTargetAuthenticationHandler extends org.apache.http.impl.client.AbstractAuthenticationHandler { + public deprecated class DefaultTargetAuthenticationHandler extends org.apache.http.impl.client.AbstractAuthenticationHandler { ctor public DefaultTargetAuthenticationHandler(); method public java.util.Map<java.lang.String, org.apache.http.Header> getChallenges(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.MalformedChallengeException; method public boolean isAuthenticationRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext); } - public class DefaultUserTokenHandler implements org.apache.http.client.UserTokenHandler { + public deprecated class DefaultUserTokenHandler implements org.apache.http.client.UserTokenHandler { ctor public DefaultUserTokenHandler(); method public java.lang.Object getUserToken(org.apache.http.protocol.HttpContext); } - public class EntityEnclosingRequestWrapper extends org.apache.http.impl.client.RequestWrapper implements org.apache.http.HttpEntityEnclosingRequest { + public deprecated class EntityEnclosingRequestWrapper extends org.apache.http.impl.client.RequestWrapper implements org.apache.http.HttpEntityEnclosingRequest { ctor public EntityEnclosingRequestWrapper(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.ProtocolException; method public boolean expectContinue(); method public org.apache.http.HttpEntity getEntity(); method public void setEntity(org.apache.http.HttpEntity); } - public class RedirectLocations { + public deprecated class RedirectLocations { ctor public RedirectLocations(); method public void add(java.net.URI); method public boolean contains(java.net.URI); method public boolean remove(java.net.URI); } - public class RequestWrapper extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.client.methods.HttpUriRequest { + public deprecated class RequestWrapper extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.client.methods.HttpUriRequest { ctor public RequestWrapper(org.apache.http.HttpRequest) throws org.apache.http.ProtocolException; method public void abort() throws java.lang.UnsupportedOperationException; method public int getExecCount(); @@ -55909,7 +56357,7 @@ package org.apache.http.impl.client { method public void setURI(java.net.URI); } - public class RoutedRequest { + public deprecated class RoutedRequest { ctor public RoutedRequest(org.apache.http.impl.client.RequestWrapper, org.apache.http.conn.routing.HttpRoute); method public final org.apache.http.impl.client.RequestWrapper getRequest(); method public final org.apache.http.conn.routing.HttpRoute getRoute(); @@ -55917,7 +56365,7 @@ package org.apache.http.impl.client { field protected final org.apache.http.conn.routing.HttpRoute route; } - public class TunnelRefusedException extends org.apache.http.HttpException { + public deprecated class TunnelRefusedException extends org.apache.http.HttpException { ctor public TunnelRefusedException(java.lang.String, org.apache.http.HttpResponse); method public org.apache.http.HttpResponse getResponse(); } @@ -55926,7 +56374,7 @@ package org.apache.http.impl.client { package org.apache.http.impl.conn { - public abstract class AbstractClientConnAdapter implements org.apache.http.conn.ManagedClientConnection { + public abstract deprecated class AbstractClientConnAdapter implements org.apache.http.conn.ManagedClientConnection { ctor protected AbstractClientConnAdapter(org.apache.http.conn.ClientConnectionManager, org.apache.http.conn.OperatedClientConnection); method public void abortConnection(); method protected final void assertNotAborted() throws java.io.InterruptedIOException; @@ -55958,7 +56406,7 @@ package org.apache.http.impl.conn { method public void unmarkReusable(); } - public abstract class AbstractPoolEntry { + public abstract deprecated class AbstractPoolEntry { ctor protected AbstractPoolEntry(org.apache.http.conn.ClientConnectionOperator, org.apache.http.conn.routing.HttpRoute); method public java.lang.Object getState(); method public void layerProtocol(org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException; @@ -55974,7 +56422,7 @@ package org.apache.http.impl.conn { field protected volatile org.apache.http.conn.routing.RouteTracker tracker; } - public abstract class AbstractPooledConnAdapter extends org.apache.http.impl.conn.AbstractClientConnAdapter { + public abstract deprecated class AbstractPooledConnAdapter extends org.apache.http.impl.conn.AbstractClientConnAdapter { ctor protected AbstractPooledConnAdapter(org.apache.http.conn.ClientConnectionManager, org.apache.http.impl.conn.AbstractPoolEntry); method protected final void assertAttached(); method public void close() throws java.io.IOException; @@ -55989,7 +56437,7 @@ package org.apache.http.impl.conn { field protected volatile org.apache.http.impl.conn.AbstractPoolEntry poolEntry; } - public class DefaultClientConnection extends org.apache.http.impl.SocketHttpClientConnection implements org.apache.http.conn.OperatedClientConnection { + public deprecated class DefaultClientConnection extends org.apache.http.impl.SocketHttpClientConnection implements org.apache.http.conn.OperatedClientConnection { ctor public DefaultClientConnection(); method public final java.net.Socket getSocket(); method public final org.apache.http.HttpHost getTargetHost(); @@ -55999,7 +56447,7 @@ package org.apache.http.impl.conn { method public void update(java.net.Socket, org.apache.http.HttpHost, boolean, org.apache.http.params.HttpParams) throws java.io.IOException; } - public class DefaultClientConnectionOperator implements org.apache.http.conn.ClientConnectionOperator { + public deprecated class DefaultClientConnectionOperator implements org.apache.http.conn.ClientConnectionOperator { ctor public DefaultClientConnectionOperator(org.apache.http.conn.scheme.SchemeRegistry); method public org.apache.http.conn.OperatedClientConnection createConnection(); method public void openConnection(org.apache.http.conn.OperatedClientConnection, org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException; @@ -56008,18 +56456,18 @@ package org.apache.http.impl.conn { field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry; } - public class DefaultHttpRoutePlanner implements org.apache.http.conn.routing.HttpRoutePlanner { + public deprecated class DefaultHttpRoutePlanner implements org.apache.http.conn.routing.HttpRoutePlanner { ctor public DefaultHttpRoutePlanner(org.apache.http.conn.scheme.SchemeRegistry); method public org.apache.http.conn.routing.HttpRoute determineRoute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException; field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry; } - public class DefaultResponseParser extends org.apache.http.impl.io.AbstractMessageParser { + public deprecated class DefaultResponseParser extends org.apache.http.impl.io.AbstractMessageParser { ctor public DefaultResponseParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.HttpResponseFactory, org.apache.http.params.HttpParams); method protected org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException; } - public class IdleConnectionHandler { + public deprecated class IdleConnectionHandler { ctor public IdleConnectionHandler(); method public void add(org.apache.http.HttpConnection, long, java.util.concurrent.TimeUnit); method public void closeExpiredConnections(); @@ -56028,7 +56476,7 @@ package org.apache.http.impl.conn { method public void removeAll(); } - public class LoggingSessionInputBuffer implements org.apache.http.io.SessionInputBuffer { + public deprecated class LoggingSessionInputBuffer implements org.apache.http.io.SessionInputBuffer { ctor public LoggingSessionInputBuffer(org.apache.http.io.SessionInputBuffer, org.apache.http.impl.conn.Wire); method public org.apache.http.io.HttpTransportMetrics getMetrics(); method public boolean isDataAvailable(int) throws java.io.IOException; @@ -56039,7 +56487,7 @@ package org.apache.http.impl.conn { method public int readLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException; } - public class LoggingSessionOutputBuffer implements org.apache.http.io.SessionOutputBuffer { + public deprecated class LoggingSessionOutputBuffer implements org.apache.http.io.SessionOutputBuffer { ctor public LoggingSessionOutputBuffer(org.apache.http.io.SessionOutputBuffer, org.apache.http.impl.conn.Wire); method public void flush() throws java.io.IOException; method public org.apache.http.io.HttpTransportMetrics getMetrics(); @@ -56050,7 +56498,7 @@ package org.apache.http.impl.conn { method public void writeLine(java.lang.String) throws java.io.IOException; } - public class ProxySelectorRoutePlanner implements org.apache.http.conn.routing.HttpRoutePlanner { + public deprecated class ProxySelectorRoutePlanner implements org.apache.http.conn.routing.HttpRoutePlanner { ctor public ProxySelectorRoutePlanner(org.apache.http.conn.scheme.SchemeRegistry, java.net.ProxySelector); method protected java.net.Proxy chooseProxy(java.util.List<java.net.Proxy>, org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext); method protected org.apache.http.HttpHost determineProxy(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException; @@ -56062,7 +56510,7 @@ package org.apache.http.impl.conn { field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry; } - public class SingleClientConnManager implements org.apache.http.conn.ClientConnectionManager { + public deprecated class SingleClientConnManager implements org.apache.http.conn.ClientConnectionManager { ctor public SingleClientConnManager(org.apache.http.params.HttpParams, org.apache.http.conn.scheme.SchemeRegistry); method protected final void assertStillUp() throws java.lang.IllegalStateException; method public void closeExpiredConnections(); @@ -56095,7 +56543,7 @@ package org.apache.http.impl.conn { method protected void shutdown() throws java.io.IOException; } - public class Wire { + public deprecated class Wire { ctor public Wire(org.apache.commons.logging.Log); method public boolean enabled(); method public void input(java.io.InputStream) throws java.io.IOException; @@ -56114,7 +56562,7 @@ package org.apache.http.impl.conn { package org.apache.http.impl.conn.tsccm { - public abstract class AbstractConnPool implements org.apache.http.impl.conn.tsccm.RefQueueHandler { + public abstract deprecated class AbstractConnPool implements org.apache.http.impl.conn.tsccm.RefQueueHandler { ctor protected AbstractConnPool(); method protected void closeConnection(org.apache.http.conn.OperatedClientConnection); method public void closeExpiredConnections(); @@ -56135,24 +56583,24 @@ package org.apache.http.impl.conn.tsccm { field protected java.lang.ref.ReferenceQueue<java.lang.Object> refQueue; } - public class BasicPoolEntry extends org.apache.http.impl.conn.AbstractPoolEntry { + public deprecated class BasicPoolEntry extends org.apache.http.impl.conn.AbstractPoolEntry { ctor public BasicPoolEntry(org.apache.http.conn.ClientConnectionOperator, org.apache.http.conn.routing.HttpRoute, java.lang.ref.ReferenceQueue<java.lang.Object>); method protected final org.apache.http.conn.OperatedClientConnection getConnection(); method protected final org.apache.http.conn.routing.HttpRoute getPlannedRoute(); method protected final org.apache.http.impl.conn.tsccm.BasicPoolEntryRef getWeakRef(); } - public class BasicPoolEntryRef extends java.lang.ref.WeakReference { + public deprecated class BasicPoolEntryRef extends java.lang.ref.WeakReference { ctor public BasicPoolEntryRef(org.apache.http.impl.conn.tsccm.BasicPoolEntry, java.lang.ref.ReferenceQueue<java.lang.Object>); method public final org.apache.http.conn.routing.HttpRoute getRoute(); } - public class BasicPooledConnAdapter extends org.apache.http.impl.conn.AbstractPooledConnAdapter { + public deprecated class BasicPooledConnAdapter extends org.apache.http.impl.conn.AbstractPooledConnAdapter { ctor protected BasicPooledConnAdapter(org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager, org.apache.http.impl.conn.AbstractPoolEntry); method protected org.apache.http.impl.conn.AbstractPoolEntry getPoolEntry(); } - public class ConnPoolByRoute extends org.apache.http.impl.conn.tsccm.AbstractConnPool { + public deprecated class ConnPoolByRoute extends org.apache.http.impl.conn.tsccm.AbstractConnPool { ctor public ConnPoolByRoute(org.apache.http.conn.ClientConnectionOperator, org.apache.http.params.HttpParams); method protected org.apache.http.impl.conn.tsccm.BasicPoolEntry createEntry(org.apache.http.impl.conn.tsccm.RouteSpecificPool, org.apache.http.conn.ClientConnectionOperator); method protected java.util.Queue<org.apache.http.impl.conn.tsccm.BasicPoolEntry> createFreeConnQueue(); @@ -56178,16 +56626,16 @@ package org.apache.http.impl.conn.tsccm { field protected java.util.Queue<org.apache.http.impl.conn.tsccm.WaitingThread> waitingThreads; } - public abstract interface PoolEntryRequest { + public abstract deprecated interface PoolEntryRequest { method public abstract void abortRequest(); method public abstract org.apache.http.impl.conn.tsccm.BasicPoolEntry getPoolEntry(long, java.util.concurrent.TimeUnit) throws org.apache.http.conn.ConnectionPoolTimeoutException, java.lang.InterruptedException; } - public abstract interface RefQueueHandler { + public abstract deprecated interface RefQueueHandler { method public abstract void handleReference(java.lang.ref.Reference<?>); } - public class RefQueueWorker implements java.lang.Runnable { + public deprecated class RefQueueWorker implements java.lang.Runnable { ctor public RefQueueWorker(java.lang.ref.ReferenceQueue<?>, org.apache.http.impl.conn.tsccm.RefQueueHandler); method public void run(); method public void shutdown(); @@ -56196,7 +56644,7 @@ package org.apache.http.impl.conn.tsccm { field protected volatile java.lang.Thread workerThread; } - public class RouteSpecificPool { + public deprecated class RouteSpecificPool { ctor public RouteSpecificPool(org.apache.http.conn.routing.HttpRoute, int); method public org.apache.http.impl.conn.tsccm.BasicPoolEntry allocEntry(java.lang.Object); method public void createdEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry); @@ -56219,7 +56667,7 @@ package org.apache.http.impl.conn.tsccm { field protected final java.util.Queue<org.apache.http.impl.conn.tsccm.WaitingThread> waitingThreads; } - public class ThreadSafeClientConnManager implements org.apache.http.conn.ClientConnectionManager { + public deprecated class ThreadSafeClientConnManager implements org.apache.http.conn.ClientConnectionManager { ctor public ThreadSafeClientConnManager(org.apache.http.params.HttpParams, org.apache.http.conn.scheme.SchemeRegistry); method public void closeExpiredConnections(); method public void closeIdleConnections(long, java.util.concurrent.TimeUnit); @@ -56236,7 +56684,7 @@ package org.apache.http.impl.conn.tsccm { field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry; } - public class WaitingThread { + public deprecated class WaitingThread { ctor public WaitingThread(java.util.concurrent.locks.Condition, org.apache.http.impl.conn.tsccm.RouteSpecificPool); method public boolean await(java.util.Date) throws java.lang.InterruptedException; method public final java.util.concurrent.locks.Condition getCondition(); @@ -56246,7 +56694,7 @@ package org.apache.http.impl.conn.tsccm { method public void wakeup(); } - public class WaitingThreadAborter { + public deprecated class WaitingThreadAborter { ctor public WaitingThreadAborter(); method public void abort(); method public void setWaitingThread(org.apache.http.impl.conn.tsccm.WaitingThread); @@ -56256,13 +56704,13 @@ package org.apache.http.impl.conn.tsccm { package org.apache.http.impl.cookie { - public abstract class AbstractCookieAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler { + public abstract deprecated class AbstractCookieAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler { ctor public AbstractCookieAttributeHandler(); method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin); method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException; } - public abstract class AbstractCookieSpec implements org.apache.http.cookie.CookieSpec { + public abstract deprecated class AbstractCookieSpec implements org.apache.http.cookie.CookieSpec { ctor public AbstractCookieSpec(); method protected org.apache.http.cookie.CookieAttributeHandler findAttribHandler(java.lang.String); method protected org.apache.http.cookie.CookieAttributeHandler getAttribHandler(java.lang.String); @@ -56270,7 +56718,7 @@ package org.apache.http.impl.cookie { method public void registerAttribHandler(java.lang.String, org.apache.http.cookie.CookieAttributeHandler); } - public class BasicClientCookie implements org.apache.http.cookie.ClientCookie java.lang.Cloneable org.apache.http.cookie.SetCookie { + public deprecated class BasicClientCookie implements org.apache.http.cookie.ClientCookie java.lang.Cloneable org.apache.http.cookie.SetCookie { ctor public BasicClientCookie(java.lang.String, java.lang.String); method public java.lang.Object clone() throws java.lang.CloneNotSupportedException; method public boolean containsAttribute(java.lang.String); @@ -56297,48 +56745,48 @@ package org.apache.http.impl.cookie { method public void setVersion(int); } - public class BasicClientCookie2 extends org.apache.http.impl.cookie.BasicClientCookie implements org.apache.http.cookie.SetCookie2 { + public deprecated class BasicClientCookie2 extends org.apache.http.impl.cookie.BasicClientCookie implements org.apache.http.cookie.SetCookie2 { ctor public BasicClientCookie2(java.lang.String, java.lang.String); method public void setCommentURL(java.lang.String); method public void setDiscard(boolean); method public void setPorts(int[]); } - public class BasicCommentHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler { + public deprecated class BasicCommentHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler { ctor public BasicCommentHandler(); method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException; } - public class BasicDomainHandler implements org.apache.http.cookie.CookieAttributeHandler { + public deprecated class BasicDomainHandler implements org.apache.http.cookie.CookieAttributeHandler { ctor public BasicDomainHandler(); method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin); method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException; method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException; } - public class BasicExpiresHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler { + public deprecated class BasicExpiresHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler { ctor public BasicExpiresHandler(java.lang.String[]); method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException; } - public class BasicMaxAgeHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler { + public deprecated class BasicMaxAgeHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler { ctor public BasicMaxAgeHandler(); method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException; } - public class BasicPathHandler implements org.apache.http.cookie.CookieAttributeHandler { + public deprecated class BasicPathHandler implements org.apache.http.cookie.CookieAttributeHandler { ctor public BasicPathHandler(); method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin); method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException; method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException; } - public class BasicSecureHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler { + public deprecated class BasicSecureHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler { ctor public BasicSecureHandler(); method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException; } - public class BestMatchSpec implements org.apache.http.cookie.CookieSpec { + public deprecated class BestMatchSpec implements org.apache.http.cookie.CookieSpec { ctor public BestMatchSpec(java.lang.String[], boolean); ctor public BestMatchSpec(); method public java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>); @@ -56349,12 +56797,12 @@ package org.apache.http.impl.cookie { method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException; } - public class BestMatchSpecFactory implements org.apache.http.cookie.CookieSpecFactory { + public deprecated class BestMatchSpecFactory implements org.apache.http.cookie.CookieSpecFactory { ctor public BestMatchSpecFactory(); method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams); } - public class BrowserCompatSpec extends org.apache.http.impl.cookie.CookieSpecBase { + public deprecated class BrowserCompatSpec extends org.apache.http.impl.cookie.CookieSpecBase { ctor public BrowserCompatSpec(java.lang.String[]); ctor public BrowserCompatSpec(); method public java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>); @@ -56364,12 +56812,12 @@ package org.apache.http.impl.cookie { field protected static final java.lang.String[] DATE_PATTERNS; } - public class BrowserCompatSpecFactory implements org.apache.http.cookie.CookieSpecFactory { + public deprecated class BrowserCompatSpecFactory implements org.apache.http.cookie.CookieSpecFactory { ctor public BrowserCompatSpecFactory(); method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams); } - public abstract class CookieSpecBase extends org.apache.http.impl.cookie.AbstractCookieSpec { + public abstract deprecated class CookieSpecBase extends org.apache.http.impl.cookie.AbstractCookieSpec { ctor public CookieSpecBase(); method protected static java.lang.String getDefaultDomain(org.apache.http.cookie.CookieOrigin); method protected static java.lang.String getDefaultPath(org.apache.http.cookie.CookieOrigin); @@ -56378,12 +56826,12 @@ package org.apache.http.impl.cookie { method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException; } - public class DateParseException extends java.lang.Exception { + public deprecated class DateParseException extends java.lang.Exception { ctor public DateParseException(); ctor public DateParseException(java.lang.String); } - public final class DateUtils { + public final deprecated class DateUtils { method public static java.lang.String formatDate(java.util.Date); method public static java.lang.String formatDate(java.util.Date, java.lang.String); method public static java.util.Date parseDate(java.lang.String) throws org.apache.http.impl.cookie.DateParseException; @@ -56395,17 +56843,17 @@ package org.apache.http.impl.cookie { field public static final java.lang.String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz"; } - public class NetscapeDomainHandler extends org.apache.http.impl.cookie.BasicDomainHandler { + public deprecated class NetscapeDomainHandler extends org.apache.http.impl.cookie.BasicDomainHandler { ctor public NetscapeDomainHandler(); } - public class NetscapeDraftHeaderParser { + public deprecated class NetscapeDraftHeaderParser { ctor public NetscapeDraftHeaderParser(); method public org.apache.http.HeaderElement parseHeader(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException; field public static final org.apache.http.impl.cookie.NetscapeDraftHeaderParser DEFAULT; } - public class NetscapeDraftSpec extends org.apache.http.impl.cookie.CookieSpecBase { + public deprecated class NetscapeDraftSpec extends org.apache.http.impl.cookie.CookieSpecBase { ctor public NetscapeDraftSpec(java.lang.String[]); ctor public NetscapeDraftSpec(); method public java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>); @@ -56415,19 +56863,19 @@ package org.apache.http.impl.cookie { field protected static final java.lang.String EXPIRES_PATTERN = "EEE, dd-MMM-yyyy HH:mm:ss z"; } - public class NetscapeDraftSpecFactory implements org.apache.http.cookie.CookieSpecFactory { + public deprecated class NetscapeDraftSpecFactory implements org.apache.http.cookie.CookieSpecFactory { ctor public NetscapeDraftSpecFactory(); method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams); } - public class RFC2109DomainHandler implements org.apache.http.cookie.CookieAttributeHandler { + public deprecated class RFC2109DomainHandler implements org.apache.http.cookie.CookieAttributeHandler { ctor public RFC2109DomainHandler(); method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin); method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException; method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException; } - public class RFC2109Spec extends org.apache.http.impl.cookie.CookieSpecBase { + public deprecated class RFC2109Spec extends org.apache.http.impl.cookie.CookieSpecBase { ctor public RFC2109Spec(java.lang.String[], boolean); ctor public RFC2109Spec(); method protected void formatCookieAsVer(org.apache.http.util.CharArrayBuffer, org.apache.http.cookie.Cookie, int); @@ -56438,31 +56886,31 @@ package org.apache.http.impl.cookie { method public java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.Header, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException; } - public class RFC2109SpecFactory implements org.apache.http.cookie.CookieSpecFactory { + public deprecated class RFC2109SpecFactory implements org.apache.http.cookie.CookieSpecFactory { ctor public RFC2109SpecFactory(); method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams); } - public class RFC2109VersionHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler { + public deprecated class RFC2109VersionHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler { ctor public RFC2109VersionHandler(); method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException; } - public class RFC2965CommentUrlAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler { + public deprecated class RFC2965CommentUrlAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler { ctor public RFC2965CommentUrlAttributeHandler(); method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin); method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException; method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException; } - public class RFC2965DiscardAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler { + public deprecated class RFC2965DiscardAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler { ctor public RFC2965DiscardAttributeHandler(); method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin); method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException; method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException; } - public class RFC2965DomainAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler { + public deprecated class RFC2965DomainAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler { ctor public RFC2965DomainAttributeHandler(); method public boolean domainMatch(java.lang.String, java.lang.String); method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin); @@ -56470,24 +56918,24 @@ package org.apache.http.impl.cookie { method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException; } - public class RFC2965PortAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler { + public deprecated class RFC2965PortAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler { ctor public RFC2965PortAttributeHandler(); method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin); method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException; method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException; } - public class RFC2965Spec extends org.apache.http.impl.cookie.RFC2109Spec { + public deprecated class RFC2965Spec extends org.apache.http.impl.cookie.RFC2109Spec { ctor public RFC2965Spec(); ctor public RFC2965Spec(java.lang.String[], boolean); } - public class RFC2965SpecFactory implements org.apache.http.cookie.CookieSpecFactory { + public deprecated class RFC2965SpecFactory implements org.apache.http.cookie.CookieSpecFactory { ctor public RFC2965SpecFactory(); method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams); } - public class RFC2965VersionAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler { + public deprecated class RFC2965VersionAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler { ctor public RFC2965VersionAttributeHandler(); method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin); method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException; @@ -56498,24 +56946,24 @@ package org.apache.http.impl.cookie { package org.apache.http.impl.entity { - public class EntityDeserializer { + public deprecated class EntityDeserializer { ctor public EntityDeserializer(org.apache.http.entity.ContentLengthStrategy); method public org.apache.http.HttpEntity deserialize(org.apache.http.io.SessionInputBuffer, org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException; method protected org.apache.http.entity.BasicHttpEntity doDeserialize(org.apache.http.io.SessionInputBuffer, org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException; } - public class EntitySerializer { + public deprecated class EntitySerializer { ctor public EntitySerializer(org.apache.http.entity.ContentLengthStrategy); method protected java.io.OutputStream doSerialize(org.apache.http.io.SessionOutputBuffer, org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException; method public void serialize(org.apache.http.io.SessionOutputBuffer, org.apache.http.HttpMessage, org.apache.http.HttpEntity) throws org.apache.http.HttpException, java.io.IOException; } - public class LaxContentLengthStrategy implements org.apache.http.entity.ContentLengthStrategy { + public deprecated class LaxContentLengthStrategy implements org.apache.http.entity.ContentLengthStrategy { ctor public LaxContentLengthStrategy(); method public long determineLength(org.apache.http.HttpMessage) throws org.apache.http.HttpException; } - public class StrictContentLengthStrategy implements org.apache.http.entity.ContentLengthStrategy { + public deprecated class StrictContentLengthStrategy implements org.apache.http.entity.ContentLengthStrategy { ctor public StrictContentLengthStrategy(); method public long determineLength(org.apache.http.HttpMessage) throws org.apache.http.HttpException; } @@ -56524,7 +56972,7 @@ package org.apache.http.impl.entity { package org.apache.http.impl.io { - public abstract class AbstractMessageParser implements org.apache.http.io.HttpMessageParser { + public abstract deprecated class AbstractMessageParser implements org.apache.http.io.HttpMessageParser { ctor public AbstractMessageParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.params.HttpParams); method public org.apache.http.HttpMessage parse() throws org.apache.http.HttpException, java.io.IOException; method protected abstract org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException, org.apache.http.ParseException; @@ -56532,7 +56980,7 @@ package org.apache.http.impl.io { field protected final org.apache.http.message.LineParser lineParser; } - public abstract class AbstractMessageWriter implements org.apache.http.io.HttpMessageWriter { + public abstract deprecated class AbstractMessageWriter implements org.apache.http.io.HttpMessageWriter { ctor public AbstractMessageWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.message.LineFormatter, org.apache.http.params.HttpParams); method public void write(org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException; method protected abstract void writeHeadLine(org.apache.http.HttpMessage) throws java.io.IOException; @@ -56541,7 +56989,7 @@ package org.apache.http.impl.io { field protected final org.apache.http.io.SessionOutputBuffer sessionBuffer; } - public abstract class AbstractSessionInputBuffer implements org.apache.http.io.SessionInputBuffer { + public abstract deprecated class AbstractSessionInputBuffer implements org.apache.http.io.SessionInputBuffer { ctor public AbstractSessionInputBuffer(); method protected int fillBuffer() throws java.io.IOException; method public org.apache.http.io.HttpTransportMetrics getMetrics(); @@ -56554,7 +57002,7 @@ package org.apache.http.impl.io { method public java.lang.String readLine() throws java.io.IOException; } - public abstract class AbstractSessionOutputBuffer implements org.apache.http.io.SessionOutputBuffer { + public abstract deprecated class AbstractSessionOutputBuffer implements org.apache.http.io.SessionOutputBuffer { ctor public AbstractSessionOutputBuffer(); method public void flush() throws java.io.IOException; method protected void flushBuffer() throws java.io.IOException; @@ -56567,13 +57015,13 @@ package org.apache.http.impl.io { method public void writeLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException; } - public class ChunkedInputStream extends java.io.InputStream { + public deprecated class ChunkedInputStream extends java.io.InputStream { ctor public ChunkedInputStream(org.apache.http.io.SessionInputBuffer); method public org.apache.http.Header[] getFooters(); method public int read() throws java.io.IOException; } - public class ChunkedOutputStream extends java.io.OutputStream { + public deprecated class ChunkedOutputStream extends java.io.OutputStream { ctor public ChunkedOutputStream(org.apache.http.io.SessionOutputBuffer, int) throws java.io.IOException; ctor public ChunkedOutputStream(org.apache.http.io.SessionOutputBuffer) throws java.io.IOException; method public void finish() throws java.io.IOException; @@ -56583,37 +57031,37 @@ package org.apache.http.impl.io { method protected void writeClosingChunk() throws java.io.IOException; } - public class ContentLengthInputStream extends java.io.InputStream { + public deprecated class ContentLengthInputStream extends java.io.InputStream { ctor public ContentLengthInputStream(org.apache.http.io.SessionInputBuffer, long); method public int read() throws java.io.IOException; } - public class ContentLengthOutputStream extends java.io.OutputStream { + public deprecated class ContentLengthOutputStream extends java.io.OutputStream { ctor public ContentLengthOutputStream(org.apache.http.io.SessionOutputBuffer, long); method public void write(int) throws java.io.IOException; } - public class HttpRequestParser extends org.apache.http.impl.io.AbstractMessageParser { + public deprecated class HttpRequestParser extends org.apache.http.impl.io.AbstractMessageParser { ctor public HttpRequestParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.HttpRequestFactory, org.apache.http.params.HttpParams); method protected org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException, org.apache.http.ParseException; } - public class HttpRequestWriter extends org.apache.http.impl.io.AbstractMessageWriter { + public deprecated class HttpRequestWriter extends org.apache.http.impl.io.AbstractMessageWriter { ctor public HttpRequestWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.message.LineFormatter, org.apache.http.params.HttpParams); method protected void writeHeadLine(org.apache.http.HttpMessage) throws java.io.IOException; } - public class HttpResponseParser extends org.apache.http.impl.io.AbstractMessageParser { + public deprecated class HttpResponseParser extends org.apache.http.impl.io.AbstractMessageParser { ctor public HttpResponseParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.HttpResponseFactory, org.apache.http.params.HttpParams); method protected org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException, org.apache.http.ParseException; } - public class HttpResponseWriter extends org.apache.http.impl.io.AbstractMessageWriter { + public deprecated class HttpResponseWriter extends org.apache.http.impl.io.AbstractMessageWriter { ctor public HttpResponseWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.message.LineFormatter, org.apache.http.params.HttpParams); method protected void writeHeadLine(org.apache.http.HttpMessage) throws java.io.IOException; } - public class HttpTransportMetricsImpl implements org.apache.http.io.HttpTransportMetrics { + public deprecated class HttpTransportMetricsImpl implements org.apache.http.io.HttpTransportMetrics { ctor public HttpTransportMetricsImpl(); method public long getBytesTransferred(); method public void incrementBytesTransferred(long); @@ -56621,22 +57069,22 @@ package org.apache.http.impl.io { method public void setBytesTransferred(long); } - public class IdentityInputStream extends java.io.InputStream { + public deprecated class IdentityInputStream extends java.io.InputStream { ctor public IdentityInputStream(org.apache.http.io.SessionInputBuffer); method public int read() throws java.io.IOException; } - public class IdentityOutputStream extends java.io.OutputStream { + public deprecated class IdentityOutputStream extends java.io.OutputStream { ctor public IdentityOutputStream(org.apache.http.io.SessionOutputBuffer); method public void write(int) throws java.io.IOException; } - public class SocketInputBuffer extends org.apache.http.impl.io.AbstractSessionInputBuffer { + public deprecated class SocketInputBuffer extends org.apache.http.impl.io.AbstractSessionInputBuffer { ctor public SocketInputBuffer(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException; method public boolean isDataAvailable(int) throws java.io.IOException; } - public class SocketOutputBuffer extends org.apache.http.impl.io.AbstractSessionOutputBuffer { + public deprecated class SocketOutputBuffer extends org.apache.http.impl.io.AbstractSessionOutputBuffer { ctor public SocketOutputBuffer(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException; } @@ -56644,20 +57092,20 @@ package org.apache.http.impl.io { package org.apache.http.io { - public abstract interface HttpMessageParser { + public abstract deprecated interface HttpMessageParser { method public abstract org.apache.http.HttpMessage parse() throws org.apache.http.HttpException, java.io.IOException; } - public abstract interface HttpMessageWriter { + public abstract deprecated interface HttpMessageWriter { method public abstract void write(org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException; } - public abstract interface HttpTransportMetrics { + public abstract deprecated interface HttpTransportMetrics { method public abstract long getBytesTransferred(); method public abstract void reset(); } - public abstract interface SessionInputBuffer { + public abstract deprecated interface SessionInputBuffer { method public abstract org.apache.http.io.HttpTransportMetrics getMetrics(); method public abstract boolean isDataAvailable(int) throws java.io.IOException; method public abstract int read(byte[], int, int) throws java.io.IOException; @@ -56667,7 +57115,7 @@ package org.apache.http.io { method public abstract java.lang.String readLine() throws java.io.IOException; } - public abstract interface SessionOutputBuffer { + public abstract deprecated interface SessionOutputBuffer { method public abstract void flush() throws java.io.IOException; method public abstract org.apache.http.io.HttpTransportMetrics getMetrics(); method public abstract void write(byte[], int, int) throws java.io.IOException; @@ -56681,7 +57129,7 @@ package org.apache.http.io { package org.apache.http.message { - public abstract class AbstractHttpMessage implements org.apache.http.HttpMessage { + public abstract deprecated class AbstractHttpMessage implements org.apache.http.HttpMessage { ctor protected AbstractHttpMessage(org.apache.http.params.HttpParams); ctor protected AbstractHttpMessage(); method public void addHeader(org.apache.http.Header); @@ -56704,7 +57152,7 @@ package org.apache.http.message { field protected org.apache.http.params.HttpParams params; } - public class BasicHeader implements java.lang.Cloneable org.apache.http.Header { + public deprecated class BasicHeader implements java.lang.Cloneable org.apache.http.Header { ctor public BasicHeader(java.lang.String, java.lang.String); method public java.lang.Object clone() throws java.lang.CloneNotSupportedException; method public org.apache.http.HeaderElement[] getElements() throws org.apache.http.ParseException; @@ -56712,7 +57160,7 @@ package org.apache.http.message { method public java.lang.String getValue(); } - public class BasicHeaderElement implements java.lang.Cloneable org.apache.http.HeaderElement { + public deprecated class BasicHeaderElement implements java.lang.Cloneable org.apache.http.HeaderElement { ctor public BasicHeaderElement(java.lang.String, java.lang.String, org.apache.http.NameValuePair[]); ctor public BasicHeaderElement(java.lang.String, java.lang.String); method public java.lang.Object clone() throws java.lang.CloneNotSupportedException; @@ -56724,7 +57172,7 @@ package org.apache.http.message { method public java.lang.String getValue(); } - public class BasicHeaderElementIterator implements org.apache.http.HeaderElementIterator { + public deprecated class BasicHeaderElementIterator implements org.apache.http.HeaderElementIterator { ctor public BasicHeaderElementIterator(org.apache.http.HeaderIterator, org.apache.http.message.HeaderValueParser); ctor public BasicHeaderElementIterator(org.apache.http.HeaderIterator); method public boolean hasNext(); @@ -56733,7 +57181,7 @@ package org.apache.http.message { method public void remove() throws java.lang.UnsupportedOperationException; } - public class BasicHeaderIterator implements org.apache.http.HeaderIterator { + public deprecated class BasicHeaderIterator implements org.apache.http.HeaderIterator { ctor public BasicHeaderIterator(org.apache.http.Header[], java.lang.String); method protected boolean filterHeader(int); method protected int findNext(int); @@ -56746,7 +57194,7 @@ package org.apache.http.message { field protected java.lang.String headerName; } - public class BasicHeaderValueFormatter implements org.apache.http.message.HeaderValueFormatter { + public deprecated class BasicHeaderValueFormatter implements org.apache.http.message.HeaderValueFormatter { ctor public BasicHeaderValueFormatter(); method protected void doFormatValue(org.apache.http.util.CharArrayBuffer, java.lang.String, boolean); method protected int estimateElementsLen(org.apache.http.HeaderElement[]); @@ -56768,7 +57216,7 @@ package org.apache.http.message { field public static final java.lang.String UNSAFE_CHARS = "\"\\"; } - public class BasicHeaderValueParser implements org.apache.http.message.HeaderValueParser { + public deprecated class BasicHeaderValueParser implements org.apache.http.message.HeaderValueParser { ctor public BasicHeaderValueParser(); method protected org.apache.http.HeaderElement createHeaderElement(java.lang.String, java.lang.String, org.apache.http.NameValuePair[]); method protected org.apache.http.NameValuePair createNameValuePair(java.lang.String, java.lang.String); @@ -56784,7 +57232,7 @@ package org.apache.http.message { field public static final org.apache.http.message.BasicHeaderValueParser DEFAULT; } - public class BasicHttpEntityEnclosingRequest extends org.apache.http.message.BasicHttpRequest implements org.apache.http.HttpEntityEnclosingRequest { + public deprecated class BasicHttpEntityEnclosingRequest extends org.apache.http.message.BasicHttpRequest implements org.apache.http.HttpEntityEnclosingRequest { ctor public BasicHttpEntityEnclosingRequest(java.lang.String, java.lang.String); ctor public BasicHttpEntityEnclosingRequest(java.lang.String, java.lang.String, org.apache.http.ProtocolVersion); ctor public BasicHttpEntityEnclosingRequest(org.apache.http.RequestLine); @@ -56793,7 +57241,7 @@ package org.apache.http.message { method public void setEntity(org.apache.http.HttpEntity); } - public class BasicHttpRequest extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.HttpRequest { + public deprecated class BasicHttpRequest extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.HttpRequest { ctor public BasicHttpRequest(java.lang.String, java.lang.String); ctor public BasicHttpRequest(java.lang.String, java.lang.String, org.apache.http.ProtocolVersion); ctor public BasicHttpRequest(org.apache.http.RequestLine); @@ -56801,7 +57249,7 @@ package org.apache.http.message { method public org.apache.http.RequestLine getRequestLine(); } - public class BasicHttpResponse extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.HttpResponse { + public deprecated class BasicHttpResponse extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.HttpResponse { ctor public BasicHttpResponse(org.apache.http.StatusLine, org.apache.http.ReasonPhraseCatalog, java.util.Locale); ctor public BasicHttpResponse(org.apache.http.StatusLine); ctor public BasicHttpResponse(org.apache.http.ProtocolVersion, int, java.lang.String); @@ -56819,7 +57267,7 @@ package org.apache.http.message { method public void setStatusLine(org.apache.http.ProtocolVersion, int, java.lang.String); } - public class BasicLineFormatter implements org.apache.http.message.LineFormatter { + public deprecated class BasicLineFormatter implements org.apache.http.message.LineFormatter { ctor public BasicLineFormatter(); method public org.apache.http.util.CharArrayBuffer appendProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.ProtocolVersion); method protected void doFormatHeader(org.apache.http.util.CharArrayBuffer, org.apache.http.Header); @@ -56837,7 +57285,7 @@ package org.apache.http.message { field public static final org.apache.http.message.BasicLineFormatter DEFAULT; } - public class BasicLineParser implements org.apache.http.message.LineParser { + public deprecated class BasicLineParser implements org.apache.http.message.LineParser { ctor public BasicLineParser(org.apache.http.ProtocolVersion); ctor public BasicLineParser(); method protected org.apache.http.ProtocolVersion createProtocolVersion(int, int); @@ -56857,7 +57305,7 @@ package org.apache.http.message { field protected final org.apache.http.ProtocolVersion protocol; } - public class BasicListHeaderIterator implements org.apache.http.HeaderIterator { + public deprecated class BasicListHeaderIterator implements org.apache.http.HeaderIterator { ctor public BasicListHeaderIterator(java.util.List, java.lang.String); method protected boolean filterHeader(int); method protected int findNext(int); @@ -56871,14 +57319,14 @@ package org.apache.http.message { field protected int lastIndex; } - public class BasicNameValuePair implements java.lang.Cloneable org.apache.http.NameValuePair { + public deprecated class BasicNameValuePair implements java.lang.Cloneable org.apache.http.NameValuePair { ctor public BasicNameValuePair(java.lang.String, java.lang.String); method public java.lang.Object clone() throws java.lang.CloneNotSupportedException; method public java.lang.String getName(); method public java.lang.String getValue(); } - public class BasicRequestLine implements java.lang.Cloneable org.apache.http.RequestLine { + public deprecated class BasicRequestLine implements java.lang.Cloneable org.apache.http.RequestLine { ctor public BasicRequestLine(java.lang.String, java.lang.String, org.apache.http.ProtocolVersion); method public java.lang.Object clone() throws java.lang.CloneNotSupportedException; method public java.lang.String getMethod(); @@ -56886,7 +57334,7 @@ package org.apache.http.message { method public java.lang.String getUri(); } - public class BasicStatusLine implements java.lang.Cloneable org.apache.http.StatusLine { + public deprecated class BasicStatusLine implements java.lang.Cloneable org.apache.http.StatusLine { ctor public BasicStatusLine(org.apache.http.ProtocolVersion, int, java.lang.String); method public java.lang.Object clone() throws java.lang.CloneNotSupportedException; method public org.apache.http.ProtocolVersion getProtocolVersion(); @@ -56894,7 +57342,7 @@ package org.apache.http.message { method public int getStatusCode(); } - public class BasicTokenIterator implements org.apache.http.TokenIterator { + public deprecated class BasicTokenIterator implements org.apache.http.TokenIterator { ctor public BasicTokenIterator(org.apache.http.HeaderIterator); method protected java.lang.String createToken(java.lang.String, int, int); method protected int findNext(int) throws org.apache.http.ParseException; @@ -56916,7 +57364,7 @@ package org.apache.http.message { field protected int searchPos; } - public class BufferedHeader implements java.lang.Cloneable org.apache.http.FormattedHeader { + public deprecated class BufferedHeader implements java.lang.Cloneable org.apache.http.FormattedHeader { ctor public BufferedHeader(org.apache.http.util.CharArrayBuffer) throws org.apache.http.ParseException; method public java.lang.Object clone() throws java.lang.CloneNotSupportedException; method public org.apache.http.util.CharArrayBuffer getBuffer(); @@ -56926,7 +57374,7 @@ package org.apache.http.message { method public int getValuePos(); } - public class HeaderGroup implements java.lang.Cloneable { + public deprecated class HeaderGroup implements java.lang.Cloneable { ctor public HeaderGroup(); method public void addHeader(org.apache.http.Header); method public void clear(); @@ -56945,28 +57393,28 @@ package org.apache.http.message { method public void updateHeader(org.apache.http.Header); } - public abstract interface HeaderValueFormatter { + public abstract deprecated interface HeaderValueFormatter { method public abstract org.apache.http.util.CharArrayBuffer formatElements(org.apache.http.util.CharArrayBuffer, org.apache.http.HeaderElement[], boolean); method public abstract org.apache.http.util.CharArrayBuffer formatHeaderElement(org.apache.http.util.CharArrayBuffer, org.apache.http.HeaderElement, boolean); method public abstract org.apache.http.util.CharArrayBuffer formatNameValuePair(org.apache.http.util.CharArrayBuffer, org.apache.http.NameValuePair, boolean); method public abstract org.apache.http.util.CharArrayBuffer formatParameters(org.apache.http.util.CharArrayBuffer, org.apache.http.NameValuePair[], boolean); } - public abstract interface HeaderValueParser { + public abstract deprecated interface HeaderValueParser { method public abstract org.apache.http.HeaderElement[] parseElements(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException; method public abstract org.apache.http.HeaderElement parseHeaderElement(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException; method public abstract org.apache.http.NameValuePair parseNameValuePair(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException; method public abstract org.apache.http.NameValuePair[] parseParameters(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException; } - public abstract interface LineFormatter { + public abstract deprecated interface LineFormatter { method public abstract org.apache.http.util.CharArrayBuffer appendProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.ProtocolVersion); method public abstract org.apache.http.util.CharArrayBuffer formatHeader(org.apache.http.util.CharArrayBuffer, org.apache.http.Header); method public abstract org.apache.http.util.CharArrayBuffer formatRequestLine(org.apache.http.util.CharArrayBuffer, org.apache.http.RequestLine); method public abstract org.apache.http.util.CharArrayBuffer formatStatusLine(org.apache.http.util.CharArrayBuffer, org.apache.http.StatusLine); } - public abstract interface LineParser { + public abstract deprecated interface LineParser { method public abstract boolean hasProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor); method public abstract org.apache.http.Header parseHeader(org.apache.http.util.CharArrayBuffer) throws org.apache.http.ParseException; method public abstract org.apache.http.ProtocolVersion parseProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException; @@ -56974,7 +57422,7 @@ package org.apache.http.message { method public abstract org.apache.http.StatusLine parseStatusLine(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException; } - public class ParserCursor { + public deprecated class ParserCursor { ctor public ParserCursor(int, int); method public boolean atEnd(); method public int getLowerBound(); @@ -56987,7 +57435,7 @@ package org.apache.http.message { package org.apache.http.params { - public abstract class AbstractHttpParams implements org.apache.http.params.HttpParams { + public abstract deprecated class AbstractHttpParams implements org.apache.http.params.HttpParams { ctor protected AbstractHttpParams(); method public boolean getBooleanParameter(java.lang.String, boolean); method public double getDoubleParameter(java.lang.String, double); @@ -57001,7 +57449,7 @@ package org.apache.http.params { method public org.apache.http.params.HttpParams setLongParameter(java.lang.String, long); } - public final class BasicHttpParams extends org.apache.http.params.AbstractHttpParams implements java.lang.Cloneable java.io.Serializable { + public final deprecated class BasicHttpParams extends org.apache.http.params.AbstractHttpParams implements java.lang.Cloneable java.io.Serializable { ctor public BasicHttpParams(); method public void clear(); method public java.lang.Object clone() throws java.lang.CloneNotSupportedException; @@ -57015,7 +57463,7 @@ package org.apache.http.params { method public void setParameters(java.lang.String[], java.lang.Object); } - public abstract interface CoreConnectionPNames { + public abstract deprecated interface CoreConnectionPNames { field public static final java.lang.String CONNECTION_TIMEOUT = "http.connection.timeout"; field public static final java.lang.String MAX_HEADER_COUNT = "http.connection.max-header-count"; field public static final java.lang.String MAX_LINE_LENGTH = "http.connection.max-line-length"; @@ -57026,7 +57474,7 @@ package org.apache.http.params { field public static final java.lang.String TCP_NODELAY = "http.tcp.nodelay"; } - public abstract interface CoreProtocolPNames { + public abstract deprecated interface CoreProtocolPNames { field public static final java.lang.String HTTP_CONTENT_CHARSET = "http.protocol.content-charset"; field public static final java.lang.String HTTP_ELEMENT_CHARSET = "http.protocol.element-charset"; field public static final java.lang.String ORIGIN_SERVER = "http.origin-server"; @@ -57037,7 +57485,7 @@ package org.apache.http.params { field public static final java.lang.String WAIT_FOR_CONTINUE = "http.protocol.wait-for-continue"; } - public final class DefaultedHttpParams extends org.apache.http.params.AbstractHttpParams { + public final deprecated class DefaultedHttpParams extends org.apache.http.params.AbstractHttpParams { ctor public DefaultedHttpParams(org.apache.http.params.HttpParams, org.apache.http.params.HttpParams); method public org.apache.http.params.HttpParams copy(); method public org.apache.http.params.HttpParams getDefaults(); @@ -57046,12 +57494,12 @@ package org.apache.http.params { method public org.apache.http.params.HttpParams setParameter(java.lang.String, java.lang.Object); } - public abstract class HttpAbstractParamBean { + public abstract deprecated class HttpAbstractParamBean { ctor public HttpAbstractParamBean(org.apache.http.params.HttpParams); field protected final org.apache.http.params.HttpParams params; } - public class HttpConnectionParamBean extends org.apache.http.params.HttpAbstractParamBean { + public deprecated class HttpConnectionParamBean extends org.apache.http.params.HttpAbstractParamBean { ctor public HttpConnectionParamBean(org.apache.http.params.HttpParams); method public void setConnectionTimeout(int); method public void setLinger(int); @@ -57061,7 +57509,7 @@ package org.apache.http.params { method public void setTcpNoDelay(boolean); } - public final class HttpConnectionParams implements org.apache.http.params.CoreConnectionPNames { + public final deprecated class HttpConnectionParams implements org.apache.http.params.CoreConnectionPNames { method public static int getConnectionTimeout(org.apache.http.params.HttpParams); method public static int getLinger(org.apache.http.params.HttpParams); method public static int getSoTimeout(org.apache.http.params.HttpParams); @@ -57076,7 +57524,7 @@ package org.apache.http.params { method public static void setTcpNoDelay(org.apache.http.params.HttpParams, boolean); } - public abstract interface HttpParams { + public abstract deprecated interface HttpParams { method public abstract org.apache.http.params.HttpParams copy(); method public abstract boolean getBooleanParameter(java.lang.String, boolean); method public abstract double getDoubleParameter(java.lang.String, double); @@ -57093,7 +57541,7 @@ package org.apache.http.params { method public abstract org.apache.http.params.HttpParams setParameter(java.lang.String, java.lang.Object); } - public class HttpProtocolParamBean extends org.apache.http.params.HttpAbstractParamBean { + public deprecated class HttpProtocolParamBean extends org.apache.http.params.HttpAbstractParamBean { ctor public HttpProtocolParamBean(org.apache.http.params.HttpParams); method public void setContentCharset(java.lang.String); method public void setHttpElementCharset(java.lang.String); @@ -57102,7 +57550,7 @@ package org.apache.http.params { method public void setVersion(org.apache.http.HttpVersion); } - public final class HttpProtocolParams implements org.apache.http.params.CoreProtocolPNames { + public final deprecated class HttpProtocolParams implements org.apache.http.params.CoreProtocolPNames { method public static java.lang.String getContentCharset(org.apache.http.params.HttpParams); method public static java.lang.String getHttpElementCharset(org.apache.http.params.HttpParams); method public static java.lang.String getUserAgent(org.apache.http.params.HttpParams); @@ -57119,7 +57567,7 @@ package org.apache.http.params { package org.apache.http.protocol { - public class BasicHttpContext implements org.apache.http.protocol.HttpContext { + public deprecated class BasicHttpContext implements org.apache.http.protocol.HttpContext { ctor public BasicHttpContext(); ctor public BasicHttpContext(org.apache.http.protocol.HttpContext); method public java.lang.Object getAttribute(java.lang.String); @@ -57127,7 +57575,7 @@ package org.apache.http.protocol { method public void setAttribute(java.lang.String, java.lang.Object); } - public final class BasicHttpProcessor implements java.lang.Cloneable org.apache.http.protocol.HttpProcessor org.apache.http.protocol.HttpRequestInterceptorList org.apache.http.protocol.HttpResponseInterceptorList { + public final deprecated class BasicHttpProcessor implements java.lang.Cloneable org.apache.http.protocol.HttpProcessor org.apache.http.protocol.HttpRequestInterceptorList org.apache.http.protocol.HttpResponseInterceptorList { ctor public BasicHttpProcessor(); method public final void addInterceptor(org.apache.http.HttpRequestInterceptor); method public final void addInterceptor(org.apache.http.HttpRequestInterceptor, int); @@ -57156,7 +57604,7 @@ package org.apache.http.protocol { field protected java.util.List responseInterceptors; } - public final class DefaultedHttpContext implements org.apache.http.protocol.HttpContext { + public final deprecated class DefaultedHttpContext implements org.apache.http.protocol.HttpContext { ctor public DefaultedHttpContext(org.apache.http.protocol.HttpContext, org.apache.http.protocol.HttpContext); method public java.lang.Object getAttribute(java.lang.String); method public org.apache.http.protocol.HttpContext getDefaults(); @@ -57164,7 +57612,7 @@ package org.apache.http.protocol { method public void setAttribute(java.lang.String, java.lang.Object); } - public abstract interface ExecutionContext { + public abstract deprecated interface ExecutionContext { field public static final java.lang.String HTTP_CONNECTION = "http.connection"; field public static final java.lang.String HTTP_PROXY_HOST = "http.proxy_host"; field public static final java.lang.String HTTP_REQUEST = "http.request"; @@ -57173,7 +57621,7 @@ package org.apache.http.protocol { field public static final java.lang.String HTTP_TARGET_HOST = "http.target_host"; } - public final class HTTP { + public final deprecated class HTTP { method public static boolean isWhitespace(char); field public static final java.lang.String ASCII = "ASCII"; field public static final java.lang.String CHARSET_PARAM = "; charset="; @@ -57207,28 +57655,28 @@ package org.apache.http.protocol { field public static final java.lang.String UTF_8 = "UTF-8"; } - public abstract interface HttpContext { + public abstract deprecated interface HttpContext { method public abstract java.lang.Object getAttribute(java.lang.String); method public abstract java.lang.Object removeAttribute(java.lang.String); method public abstract void setAttribute(java.lang.String, java.lang.Object); field public static final java.lang.String RESERVED_PREFIX = "http."; } - public class HttpDateGenerator { + public deprecated class HttpDateGenerator { ctor public HttpDateGenerator(); method public synchronized java.lang.String getCurrentDate(); field public static final java.util.TimeZone GMT; field public static final java.lang.String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz"; } - public abstract interface HttpExpectationVerifier { + public abstract deprecated interface HttpExpectationVerifier { method public abstract void verify(org.apache.http.HttpRequest, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException; } - public abstract interface HttpProcessor implements org.apache.http.HttpRequestInterceptor org.apache.http.HttpResponseInterceptor { + public abstract deprecated interface HttpProcessor implements org.apache.http.HttpRequestInterceptor org.apache.http.HttpResponseInterceptor { } - public class HttpRequestExecutor { + public deprecated class HttpRequestExecutor { ctor public HttpRequestExecutor(); method protected boolean canResponseHaveBody(org.apache.http.HttpRequest, org.apache.http.HttpResponse); method protected org.apache.http.HttpResponse doReceiveResponse(org.apache.http.HttpRequest, org.apache.http.HttpClientConnection, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; @@ -57238,11 +57686,11 @@ package org.apache.http.protocol { method public void preProcess(org.apache.http.HttpRequest, org.apache.http.protocol.HttpProcessor, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } - public abstract interface HttpRequestHandler { + public abstract deprecated interface HttpRequestHandler { method public abstract void handle(org.apache.http.HttpRequest, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } - public class HttpRequestHandlerRegistry implements org.apache.http.protocol.HttpRequestHandlerResolver { + public deprecated class HttpRequestHandlerRegistry implements org.apache.http.protocol.HttpRequestHandlerResolver { ctor public HttpRequestHandlerRegistry(); method public org.apache.http.protocol.HttpRequestHandler lookup(java.lang.String); method protected deprecated boolean matchUriRequestPattern(java.lang.String, java.lang.String); @@ -57251,11 +57699,11 @@ package org.apache.http.protocol { method public void unregister(java.lang.String); } - public abstract interface HttpRequestHandlerResolver { + public abstract deprecated interface HttpRequestHandlerResolver { method public abstract org.apache.http.protocol.HttpRequestHandler lookup(java.lang.String); } - public abstract interface HttpRequestInterceptorList { + public abstract deprecated interface HttpRequestInterceptorList { method public abstract void addRequestInterceptor(org.apache.http.HttpRequestInterceptor); method public abstract void addRequestInterceptor(org.apache.http.HttpRequestInterceptor, int); method public abstract void clearRequestInterceptors(); @@ -57265,7 +57713,7 @@ package org.apache.http.protocol { method public abstract void setInterceptors(java.util.List); } - public abstract interface HttpResponseInterceptorList { + public abstract deprecated interface HttpResponseInterceptorList { method public abstract void addResponseInterceptor(org.apache.http.HttpResponseInterceptor); method public abstract void addResponseInterceptor(org.apache.http.HttpResponseInterceptor, int); method public abstract void clearResponseInterceptors(); @@ -57275,7 +57723,7 @@ package org.apache.http.protocol { method public abstract void setInterceptors(java.util.List); } - public class HttpService { + public deprecated class HttpService { ctor public HttpService(org.apache.http.protocol.HttpProcessor, org.apache.http.ConnectionReuseStrategy, org.apache.http.HttpResponseFactory); method protected void doService(org.apache.http.HttpRequest, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; method public org.apache.http.params.HttpParams getParams(); @@ -57289,61 +57737,61 @@ package org.apache.http.protocol { method public void setResponseFactory(org.apache.http.HttpResponseFactory); } - public class RequestConnControl implements org.apache.http.HttpRequestInterceptor { + public deprecated class RequestConnControl implements org.apache.http.HttpRequestInterceptor { ctor public RequestConnControl(); method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } - public class RequestContent implements org.apache.http.HttpRequestInterceptor { + public deprecated class RequestContent implements org.apache.http.HttpRequestInterceptor { ctor public RequestContent(); method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } - public class RequestDate implements org.apache.http.HttpRequestInterceptor { + public deprecated class RequestDate implements org.apache.http.HttpRequestInterceptor { ctor public RequestDate(); method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } - public class RequestExpectContinue implements org.apache.http.HttpRequestInterceptor { + public deprecated class RequestExpectContinue implements org.apache.http.HttpRequestInterceptor { ctor public RequestExpectContinue(); method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } - public class RequestTargetHost implements org.apache.http.HttpRequestInterceptor { + public deprecated class RequestTargetHost implements org.apache.http.HttpRequestInterceptor { ctor public RequestTargetHost(); method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } - public class RequestUserAgent implements org.apache.http.HttpRequestInterceptor { + public deprecated class RequestUserAgent implements org.apache.http.HttpRequestInterceptor { ctor public RequestUserAgent(); method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } - public class ResponseConnControl implements org.apache.http.HttpResponseInterceptor { + public deprecated class ResponseConnControl implements org.apache.http.HttpResponseInterceptor { ctor public ResponseConnControl(); method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } - public class ResponseContent implements org.apache.http.HttpResponseInterceptor { + public deprecated class ResponseContent implements org.apache.http.HttpResponseInterceptor { ctor public ResponseContent(); method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } - public class ResponseDate implements org.apache.http.HttpResponseInterceptor { + public deprecated class ResponseDate implements org.apache.http.HttpResponseInterceptor { ctor public ResponseDate(); method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } - public class ResponseServer implements org.apache.http.HttpResponseInterceptor { + public deprecated class ResponseServer implements org.apache.http.HttpResponseInterceptor { ctor public ResponseServer(); method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException; } - public class SyncBasicHttpContext extends org.apache.http.protocol.BasicHttpContext { + public deprecated class SyncBasicHttpContext extends org.apache.http.protocol.BasicHttpContext { ctor public SyncBasicHttpContext(org.apache.http.protocol.HttpContext); } - public class UriPatternMatcher { + public deprecated class UriPatternMatcher { ctor public UriPatternMatcher(); method public java.lang.Object lookup(java.lang.String); method protected boolean matchUriRequestPattern(java.lang.String, java.lang.String); @@ -57356,7 +57804,7 @@ package org.apache.http.protocol { package org.apache.http.util { - public final class ByteArrayBuffer { + public final deprecated class ByteArrayBuffer { ctor public ByteArrayBuffer(int); method public void append(byte[], int, int); method public void append(int); @@ -57373,7 +57821,7 @@ package org.apache.http.util { method public byte[] toByteArray(); } - public final class CharArrayBuffer { + public final deprecated class CharArrayBuffer { ctor public CharArrayBuffer(int); method public void append(char[], int, int); method public void append(java.lang.String); @@ -57399,7 +57847,7 @@ package org.apache.http.util { method public char[] toCharArray(); } - public final class EncodingUtils { + public final deprecated class EncodingUtils { method public static byte[] getAsciiBytes(java.lang.String); method public static java.lang.String getAsciiString(byte[], int, int); method public static java.lang.String getAsciiString(byte[]); @@ -57408,18 +57856,18 @@ package org.apache.http.util { method public static java.lang.String getString(byte[], java.lang.String); } - public final class EntityUtils { + public final deprecated class EntityUtils { method public static java.lang.String getContentCharSet(org.apache.http.HttpEntity) throws org.apache.http.ParseException; method public static byte[] toByteArray(org.apache.http.HttpEntity) throws java.io.IOException; method public static java.lang.String toString(org.apache.http.HttpEntity, java.lang.String) throws java.io.IOException, org.apache.http.ParseException; method public static java.lang.String toString(org.apache.http.HttpEntity) throws java.io.IOException, org.apache.http.ParseException; } - public final class ExceptionUtils { + public final deprecated class ExceptionUtils { method public static void initCause(java.lang.Throwable, java.lang.Throwable); } - public final class LangUtils { + public final deprecated class LangUtils { method public static boolean equals(java.lang.Object, java.lang.Object); method public static boolean equals(java.lang.Object[], java.lang.Object[]); method public static int hashCode(int, int); @@ -57429,7 +57877,7 @@ package org.apache.http.util { field public static final int HASH_SEED = 17; // 0x11 } - public class VersionInfo { + public deprecated class VersionInfo { ctor protected VersionInfo(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String); method protected static final org.apache.http.util.VersionInfo fromMap(java.lang.String, java.util.Map, java.lang.ClassLoader); method public final java.lang.String getClassloader(); diff --git a/cmds/app_process/Android.mk b/cmds/app_process/Android.mk index 74a2f7bea95a..1ca14a64f88b 100644 --- a/cmds/app_process/Android.mk +++ b/cmds/app_process/Android.mk @@ -2,10 +2,18 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) +# TODO: Trying to link libsigchain as a static library prevents +# static linker from exporting necessary symbols. So as a workaround +# we use sigchain.o LOCAL_SRC_FILES:= \ - app_main.cpp + app_main.cpp \ + sigchain_proxy.cpp + +LOCAL_LDFLAGS := -Wl,--version-script,art/sigchainlib/version-script.txt -Wl,--export-dynamic +LOCAL_CPPFLAGS := -std=c++11 -Iart LOCAL_SHARED_LIBRARIES := \ + libdl \ libcutils \ libutils \ liblog \ @@ -28,8 +36,10 @@ ifeq ($(TARGET_ARCH),arm) include $(CLEAR_VARS) +# see comment above (~l5) LOCAL_SRC_FILES:= \ - app_main.cpp + app_main.cpp \ + sigchain_proxy.cpp LOCAL_SHARED_LIBRARIES := \ libcutils \ @@ -38,6 +48,9 @@ LOCAL_SHARED_LIBRARIES := \ libbinder \ libandroid_runtime +LOCAL_LDFLAGS := -ldl -Wl,--version-script,art/sigchainlib/version-script.txt -Wl,--export-dynamic +LOCAL_CPPFLAGS := -std=c++11 -Iart + LOCAL_MODULE := app_process__asan LOCAL_MODULE_TAGS := eng LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)/asan diff --git a/cmds/app_process/sigchain_proxy.cpp b/cmds/app_process/sigchain_proxy.cpp new file mode 100644 index 000000000000..bb7a678d2bd4 --- /dev/null +++ b/cmds/app_process/sigchain_proxy.cpp @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2014 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. + */ + +#include "sigchainlib/sigchain.cc" diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index 5e9d8f74f342..7fd586f31516 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -96,8 +96,9 @@ public final class Pm { "Error: Could not access the Package Manager. Is the system running?"; public static void main(String[] args) { + int exitCode = 1; try { - new Pm().run(args); + exitCode = new Pm().run(args); } catch (Exception e) { Log.e(TAG, "Error", e); System.err.println("Error: " + e); @@ -105,20 +106,20 @@ public final class Pm { System.err.println(PM_NOT_RUNNING_ERR); } } + System.exit(exitCode); } - public void run(String[] args) throws IOException, RemoteException { + public int run(String[] args) throws IOException, RemoteException { boolean validCommand = false; if (args.length < 1) { - showUsage(); - return; + return showUsage(); } mUm = IUserManager.Stub.asInterface(ServiceManager.getService("user")); mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); if (mPm == null) { System.err.println(PM_NOT_RUNNING_ERR); - return; + return 1; } mInstaller = mPm.getPackageInstaller(); @@ -127,155 +128,129 @@ public final class Pm { mNextArg = 1; if ("list".equals(op)) { - runList(); - return; + return runList(); } if ("path".equals(op)) { - runPath(); - return; + return runPath(); } if ("dump".equals(op)) { - runDump(); - return; + return runDump(); } if ("install".equals(op)) { - runInstall(); - return; + return runInstall(); } if ("install-create".equals(op)) { - runInstallCreate(); - return; + return runInstallCreate(); } if ("install-write".equals(op)) { - runInstallWrite(); - return; + return runInstallWrite(); } if ("install-commit".equals(op)) { - runInstallCommit(); - return; + return runInstallCommit(); } if ("install-abandon".equals(op) || "install-destroy".equals(op)) { - runInstallAbandon(); - return; + return runInstallAbandon(); } if ("set-installer".equals(op)) { - runSetInstaller(); - return; + return runSetInstaller(); } if ("uninstall".equals(op)) { - runUninstall(); - return; + return runUninstall(); } if ("clear".equals(op)) { - runClear(); - return; + return runClear(); } if ("enable".equals(op)) { - runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED); - return; + return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED); } if ("disable".equals(op)) { - runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED); - return; + return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED); } if ("disable-user".equals(op)) { - runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER); - return; + return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER); } if ("disable-until-used".equals(op)) { - runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED); - return; + return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED); } if ("hide".equals(op)) { - runSetHiddenSetting(true); - return; + return runSetHiddenSetting(true); } if ("unhide".equals(op)) { - runSetHiddenSetting(false); - return; + return runSetHiddenSetting(false); } if ("grant".equals(op)) { - runGrantRevokePermission(true); - return; + return runGrantRevokePermission(true); } if ("revoke".equals(op)) { - runGrantRevokePermission(false); - return; + return runGrantRevokePermission(false); } if ("set-permission-enforced".equals(op)) { - runSetPermissionEnforced(); - return; + return runSetPermissionEnforced(); } if ("set-install-location".equals(op)) { - runSetInstallLocation(); - return; + return runSetInstallLocation(); } if ("get-install-location".equals(op)) { - runGetInstallLocation(); - return; + return runGetInstallLocation(); } if ("trim-caches".equals(op)) { - runTrimCaches(); - return; + return runTrimCaches(); } if ("create-user".equals(op)) { - runCreateUser(); - return; + return runCreateUser(); } if ("remove-user".equals(op)) { - runRemoveUser(); - return; + return runRemoveUser(); } if ("get-max-users".equals(op)) { - runGetMaxUsers(); - return; + return runGetMaxUsers(); } if ("force-dex-opt".equals(op)) { - runForceDexOpt(); - return; + return runForceDexOpt(); } try { if (args.length == 1) { if (args[0].equalsIgnoreCase("-l")) { validCommand = true; - runListPackages(false); + return runListPackages(false); } else if (args[0].equalsIgnoreCase("-lf")){ validCommand = true; - runListPackages(true); + return runListPackages(true); } } else if (args.length == 2) { if (args[0].equalsIgnoreCase("-p")) { validCommand = true; - displayPackageFilePath(args[1]); + return displayPackageFilePath(args[1]); } } + return 1; } finally { if (validCommand == false) { if (op != null) { @@ -296,35 +271,36 @@ public final class Pm { * pm list libraries * pm list instrumentation */ - private void runList() { + private int runList() { String type = nextArg(); if (type == null) { System.err.println("Error: didn't specify type of data to list"); - return; + return 1; } if ("package".equals(type) || "packages".equals(type)) { - runListPackages(false); + return runListPackages(false); } else if ("permission-groups".equals(type)) { - runListPermissionGroups(); + return runListPermissionGroups(); } else if ("permissions".equals(type)) { - runListPermissions(); + return runListPermissions(); } else if ("features".equals(type)) { - runListFeatures(); + return runListFeatures(); } else if ("libraries".equals(type)) { - runListLibraries(); + return runListLibraries(); } else if ("instrumentation".equals(type)) { - runListInstrumentation(); + return runListInstrumentation(); } else if ("users".equals(type)) { - runListUsers(); + return runListUsers(); } else { System.err.println("Error: unknown list type '" + type + "'"); + return 1; } } /** * Lists all the installed packages. */ - private void runListPackages(boolean showApplicationPackage) { + private int runListPackages(boolean showApplicationPackage) { int getFlags = 0; boolean listDisabled = false, listEnabled = false; boolean listSystem = false, listThirdParty = false; @@ -355,12 +331,12 @@ public final class Pm { getFlags |= PackageManager.GET_UNINSTALLED_PACKAGES; } else { System.err.println("Error: Unknown option: " + opt); - return; + return 1; } } } catch (RuntimeException ex) { System.err.println("Error: " + ex.toString()); - return; + return 1; } String filter = nextArg(); @@ -393,9 +369,11 @@ public final class Pm { System.out.println(); } } + return 0; } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); + return 1; } } @@ -411,7 +389,7 @@ public final class Pm { * * pm list features */ - private void runListFeatures() { + private int runListFeatures() { try { List<FeatureInfo> list = new ArrayList<FeatureInfo>(); FeatureInfo[] rawList = mPm.getSystemAvailableFeatures(); @@ -438,9 +416,11 @@ public final class Pm { else System.out.println("reqGlEsVersion=0x" + Integer.toHexString(fi.reqGlEsVersion)); } + return 0; } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); + return 1; } } @@ -449,7 +429,7 @@ public final class Pm { * * pm list libraries */ - private void runListLibraries() { + private int runListLibraries() { try { List<String> list = new ArrayList<String>(); String[] rawList = mPm.getSystemSharedLibraryNames(); @@ -474,9 +454,11 @@ public final class Pm { System.out.print("library:"); System.out.println(lib); } + return 0; } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); + return 1; } } @@ -485,7 +467,7 @@ public final class Pm { * * pm list instrumentation [package] [-f] */ - private void runListInstrumentation() { + private int runListInstrumentation() { int flags = 0; // flags != 0 is only used to request meta-data boolean showPackage = false; String targetPackage = null; @@ -499,12 +481,12 @@ public final class Pm { targetPackage = opt; } else { System.err.println("Error: Unknown option: " + opt); - return; + return 1; } } } catch (RuntimeException ex) { System.err.println("Error: " + ex.toString()); - return; + return 1; } try { @@ -531,16 +513,18 @@ public final class Pm { System.out.print(ii.targetPackage); System.out.println(")"); } + return 0; } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); + return 1; } } /** * Lists all the known permission groups. */ - private void runListPermissionGroups() { + private int runListPermissionGroups() { try { List<PermissionGroupInfo> pgs = mPm.getAllPermissionGroups(0); @@ -550,9 +534,11 @@ public final class Pm { System.out.print("permission group:"); System.out.println(pgi.name); } + return 0; } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); + return 1; } } @@ -572,7 +558,7 @@ public final class Pm { /** * Lists all the permissions in a group. */ - private void runListPermissions() { + private int runListPermissions() { try { boolean labels = false; boolean groups = false; @@ -595,7 +581,7 @@ public final class Pm { dangerousOnly = true; } else { System.err.println("Error: Unknown option: " + opt); - return; + return 1; } } @@ -637,9 +623,11 @@ public final class Pm { doListPermissions(groupList, groups, labels, summary, -10000, 10000); } + return 0; } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); + return 1; } } @@ -739,22 +727,23 @@ public final class Pm { } } - private void runPath() { + private int runPath() { String pkg = nextArg(); if (pkg == null) { System.err.println("Error: no package specified"); - return; + return 1; } - displayPackageFilePath(pkg); + return displayPackageFilePath(pkg); } - private void runDump() { + private int runDump() { String pkg = nextArg(); if (pkg == null) { System.err.println("Error: no package specified"); - return; + return 1; } ActivityManager.dumpPackageStateStatic(FileDescriptor.out, pkg); + return 0; } class LocalPackageInstallObserver extends PackageInstallObserver { @@ -822,31 +811,34 @@ public final class Pm { return Integer.toString(result); } - private void runSetInstallLocation() { + private int runSetInstallLocation() { int loc; String arg = nextArg(); if (arg == null) { System.err.println("Error: no install location specified."); - return; + return 1; } try { loc = Integer.parseInt(arg); } catch (NumberFormatException e) { System.err.println("Error: install location has to be a number."); - return; + return 1; } try { if (!mPm.setInstallLocation(loc)) { System.err.println("Error: install location has to be a number."); + return 1; } + return 0; } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); + return 1; } } - private void runGetInstallLocation() { + private int runGetInstallLocation() { try { int loc = mPm.getInstallLocation(); String locStr = "invalid"; @@ -858,13 +850,15 @@ public final class Pm { locStr = "external"; } System.out.println(loc + "[" + locStr + "]"); + return 0; } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); + return 1; } } - private void runInstall() { + private int runInstall() { int installFlags = 0; int userId = UserHandle.USER_ALL; String installerPackageName = null; @@ -884,7 +878,7 @@ public final class Pm { installerPackageName = nextOptionData(); if (installerPackageName == null) { System.err.println("Error: no value specified for -i"); - return; + return 1; } } else if (opt.equals("-t")) { installFlags |= PackageManager.INSTALL_ALLOW_TEST; @@ -900,13 +894,13 @@ public final class Pm { originatingUriString = nextOptionData(); if (originatingUriString == null) { System.err.println("Error: must supply argument for --originating-uri"); - return; + return 1; } } else if (opt.equals("--referrer")) { referrer = nextOptionData(); if (referrer == null) { System.err.println("Error: must supply argument for --referrer"); - return; + return 1; } } else if (opt.equals("--abi")) { abi = checkAbiArgument(nextOptionData()); @@ -914,7 +908,7 @@ public final class Pm { userId = Integer.parseInt(nextOptionData()); } else { System.err.println("Error: Unknown option: " + opt); - return; + return 1; } } @@ -944,7 +938,7 @@ public final class Pm { System.err.println("\tpkg: " + apkFilePath); if (apkFilePath == null) { System.err.println("Error: no package specified"); - return; + return 1; } // Populate verificationURI, optionally present @@ -973,19 +967,22 @@ public final class Pm { } if (obs.result == PackageManager.INSTALL_SUCCEEDED) { System.out.println("Success"); + return 0; } else { System.err.println("Failure [" + installFailureToString(obs) + "]"); + return 1; } } } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); + return 1; } } - private void runInstallCreate() throws RemoteException { + private int runInstallCreate() throws RemoteException { int userId = UserHandle.USER_ALL; String installerPackageName = null; @@ -1040,9 +1037,10 @@ public final class Pm { // NOTE: adb depends on parsing this string System.out.println("Success: created install session [" + sessionId + "]"); + return 0; } - private void runInstallWrite() throws IOException, RemoteException { + private int runInstallWrite() throws IOException, RemoteException { long sizeBytes = -1; String opt; @@ -1097,6 +1095,7 @@ public final class Pm { session.fsync(out); System.out.println("Success: streamed " + total + " bytes"); + return 0; } finally { IoUtils.closeQuietly(out); IoUtils.closeQuietly(in); @@ -1104,7 +1103,7 @@ public final class Pm { } } - private void runInstallCommit() throws RemoteException { + private int runInstallCommit() throws RemoteException { final int sessionId = Integer.parseInt(nextArg()); PackageInstaller.Session session = null; @@ -1119,18 +1118,19 @@ public final class Pm { PackageInstaller.STATUS_FAILURE); if (status == PackageInstaller.STATUS_SUCCESS) { System.out.println("Success"); + return 0; } else { Log.e(TAG, "Failure details: " + result.getExtras()); - System.out.println("Failure [" + System.err.println("Failure [" + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]"); - return; + return 1; } } finally { IoUtils.closeQuietly(session); } } - private void runInstallAbandon() throws RemoteException { + private int runInstallAbandon() throws RemoteException { final int sessionId = Integer.parseInt(nextArg()); PackageInstaller.Session session = null; @@ -1138,12 +1138,13 @@ public final class Pm { session = new PackageInstaller.Session(mInstaller.openSession(sessionId)); session.abandon(); System.out.println("Success"); + return 0; } finally { IoUtils.closeQuietly(session); } } - private void runSetInstaller() throws RemoteException { + private int runSetInstaller() throws RemoteException { final String targetPackage = nextArg(); final String installerPackageName = nextArg(); @@ -1154,9 +1155,10 @@ public final class Pm { mPm.setInstallerPackageName(targetPackage, installerPackageName); System.out.println("Success"); + return 0; } - public void runCreateUser() { + public int runCreateUser() { String name; int userId = -1; int flags = 0; @@ -1167,7 +1169,7 @@ public final class Pm { if (optionData == null || !isNumber(optionData)) { System.err.println("Error: no USER_ID specified"); showUsage(); - return; + return 1; } else { userId = Integer.parseInt(optionData); } @@ -1176,13 +1178,13 @@ public final class Pm { } else { System.err.println("Error: unknown option " + opt); showUsage(); - return; + return 1; } } String arg = nextArg(); if (arg == null) { System.err.println("Error: no user name specified."); - return; + return 1; } name = arg; try { @@ -1194,75 +1196,85 @@ public final class Pm { } if (info != null) { System.out.println("Success: created user id " + info.id); + return 1; } else { System.err.println("Error: couldn't create User."); + return 1; } } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); + return 1; } - } - public void runRemoveUser() { + public int runRemoveUser() { int userId; String arg = nextArg(); if (arg == null) { System.err.println("Error: no user id specified."); - return; + return 1; } try { userId = Integer.parseInt(arg); } catch (NumberFormatException e) { System.err.println("Error: user id '" + arg + "' is not a number."); - return; + return 1; } try { if (mUm.removeUser(userId)) { System.out.println("Success: removed user"); + return 0; } else { System.err.println("Error: couldn't remove user id " + userId); + return 1; } } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); + return 1; } } - public void runListUsers() { + public int runListUsers() { try { IActivityManager am = ActivityManagerNative.getDefault(); List<UserInfo> users = mUm.getUsers(false); if (users == null) { System.err.println("Error: couldn't get users"); + return 1; } else { System.out.println("Users:"); for (int i = 0; i < users.size(); i++) { String running = am.isUserRunning(users.get(i).id, false) ? " running" : ""; System.out.println("\t" + users.get(i).toString() + running); } + return 0; } } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); + return 1; } } - public void runGetMaxUsers() { + public int runGetMaxUsers() { System.out.println("Maximum supported users: " + UserManager.getMaxSupportedUsers()); + return 0; } - public void runForceDexOpt() { + public int runForceDexOpt() { final String packageName = nextArg(); try { mPm.forceDexOpt(packageName); + return 0; } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } } - private void runUninstall() throws RemoteException { + private int runUninstall() throws RemoteException { int flags = 0; int userId = UserHandle.USER_ALL; @@ -1277,11 +1289,11 @@ public final class Pm { } else { showUsage(); System.err.println("Error: Invalid user: " + param); - return; + return 1; } } else { System.err.println("Error: Unknown option: " + opt); - return; + return 1; } } @@ -1289,7 +1301,7 @@ public final class Pm { if (pkg == null) { System.err.println("Error: no package specified"); showUsage(); - return; + return 1; } if (userId == UserHandle.USER_ALL) { @@ -1302,11 +1314,11 @@ public final class Pm { } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); - return; + return 1; } if (info == null) { System.err.println("Failure - not installed for " + userId); - return; + return 1; } final boolean isSystem = (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; @@ -1326,10 +1338,12 @@ public final class Pm { PackageInstaller.STATUS_FAILURE); if (status == PackageInstaller.STATUS_SUCCESS) { System.out.println("Success"); + return 0; } else { Log.e(TAG, "Failure details: " + result.getExtras()); - System.out.println("Failure [" + System.err.println("Failure [" + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]"); + return 1; } } @@ -1347,7 +1361,7 @@ public final class Pm { } } - private void runClear() { + private int runClear() { int userId = 0; String option = nextOption(); if (option != null && option.equals("--user")) { @@ -1355,7 +1369,7 @@ public final class Pm { if (optionData == null || !isNumber(optionData)) { System.err.println("Error: no USER_ID specified"); showUsage(); - return; + return 1; } else { userId = Integer.parseInt(optionData); } @@ -1365,7 +1379,7 @@ public final class Pm { if (pkg == null) { System.err.println("Error: no package specified"); showUsage(); - return; + return 1; } ClearDataObserver obs = new ClearDataObserver(); @@ -1381,13 +1395,16 @@ public final class Pm { } if (obs.result) { - System.err.println("Success"); + System.out.println("Success"); + return 0; } else { System.err.println("Failed"); + return 1; } } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); + return 1; } } @@ -1416,7 +1433,7 @@ public final class Pm { return true; } - private void runSetEnabledSetting(int state) { + private int runSetEnabledSetting(int state) { int userId = 0; String option = nextOption(); if (option != null && option.equals("--user")) { @@ -1424,7 +1441,7 @@ public final class Pm { if (optionData == null || !isNumber(optionData)) { System.err.println("Error: no USER_ID specified"); showUsage(); - return; + return 1; } else { userId = Integer.parseInt(optionData); } @@ -1434,34 +1451,38 @@ public final class Pm { if (pkg == null) { System.err.println("Error: no package or component specified"); showUsage(); - return; + return 1; } ComponentName cn = ComponentName.unflattenFromString(pkg); if (cn == null) { try { mPm.setApplicationEnabledSetting(pkg, state, 0, userId, "shell:" + android.os.Process.myUid()); - System.err.println("Package " + pkg + " new state: " + System.out.println("Package " + pkg + " new state: " + enabledSettingToString( mPm.getApplicationEnabledSetting(pkg, userId))); + return 0; } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); + return 1; } } else { try { mPm.setComponentEnabledSetting(cn, state, 0, userId); - System.err.println("Component " + cn.toShortString() + " new state: " + System.out.println("Component " + cn.toShortString() + " new state: " + enabledSettingToString( mPm.getComponentEnabledSetting(cn, userId))); + return 0; } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); + return 1; } } } - private void runSetHiddenSetting(boolean state) { + private int runSetHiddenSetting(boolean state) { int userId = 0; String option = nextOption(); if (option != null && option.equals("--user")) { @@ -1469,7 +1490,7 @@ public final class Pm { if (optionData == null || !isNumber(optionData)) { System.err.println("Error: no USER_ID specified"); showUsage(); - return; + return 1; } else { userId = Integer.parseInt(optionData); } @@ -1479,30 +1500,32 @@ public final class Pm { if (pkg == null) { System.err.println("Error: no package or component specified"); showUsage(); - return; + return 1; } try { mPm.setApplicationHiddenSettingAsUser(pkg, state, userId); - System.err.println("Package " + pkg + " new hidden state: " + System.out.println("Package " + pkg + " new hidden state: " + mPm.getApplicationHiddenSettingAsUser(pkg, userId)); + return 0; } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); + return 1; } } - private void runGrantRevokePermission(boolean grant) { + private int runGrantRevokePermission(boolean grant) { String pkg = nextArg(); if (pkg == null) { System.err.println("Error: no package specified"); showUsage(); - return; + return 1; } String perm = nextArg(); if (perm == null) { System.err.println("Error: no permission specified"); showUsage(); - return; + return 1; } try { if (grant) { @@ -1510,41 +1533,49 @@ public final class Pm { } else { mPm.revokePermission(pkg, perm); } + return 0; } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); + return 1; } catch (IllegalArgumentException e) { System.err.println("Bad argument: " + e.toString()); showUsage(); + return 1; } catch (SecurityException e) { System.err.println("Operation not allowed: " + e.toString()); + return 1; } } - private void runSetPermissionEnforced() { + private int runSetPermissionEnforced() { final String permission = nextArg(); if (permission == null) { System.err.println("Error: no permission specified"); showUsage(); - return; + return 1; } final String enforcedRaw = nextArg(); if (enforcedRaw == null) { System.err.println("Error: no enforcement specified"); showUsage(); - return; + return 1; } final boolean enforced = Boolean.parseBoolean(enforcedRaw); try { mPm.setPermissionEnforced(permission, enforced); + return 0; } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); + return 1; } catch (IllegalArgumentException e) { System.err.println("Bad argument: " + e.toString()); showUsage(); + return 1; } catch (SecurityException e) { System.err.println("Operation not allowed: " + e.toString()); + return 1; } } @@ -1563,12 +1594,12 @@ public final class Pm { } - private void runTrimCaches() { + private int runTrimCaches() { String size = nextArg(); if (size == null) { System.err.println("Error: no size specified"); showUsage(); - return; + return 1; } int len = size.length(); long multiplier = 1; @@ -1583,7 +1614,7 @@ public final class Pm { } else { System.err.println("Invalid suffix: " + c); showUsage(); - return; + return 1; } size = size.substring(0, len-1); } @@ -1593,7 +1624,7 @@ public final class Pm { } catch (NumberFormatException e) { System.err.println("Error: expected number at: " + size); showUsage(); - return; + return 1; } ClearDataObserver obs = new ClearDataObserver(); try { @@ -1606,14 +1637,18 @@ public final class Pm { } } } + return 0; } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); + return 1; } catch (IllegalArgumentException e) { System.err.println("Bad argument: " + e.toString()); showUsage(); + return 1; } catch (SecurityException e) { System.err.println("Operation not allowed: " + e.toString()); + return 1; } } @@ -1621,7 +1656,7 @@ public final class Pm { * Displays the package file for a package. * @param pckg */ - private void displayPackageFilePath(String pckg) { + private int displayPackageFilePath(String pckg) { try { PackageInfo info = mPm.getPackageInfo(pckg, 0, 0); if (info != null && info.applicationInfo != null) { @@ -1632,12 +1667,14 @@ public final class Pm { System.out.print("package:"); System.out.println(splitSourceDir); } + return 0; } } } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); } + return 1; } private Resources getResources(PackageItemInfo pii) { @@ -1752,7 +1789,7 @@ public final class Pm { return arg; } - private static void showUsage() { + private static int showUsage() { System.err.println("usage: pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]"); System.err.println(" pm list permission-groups"); System.err.println(" pm list permissions [-g] [-f] [-d] [-u] [GROUP]"); @@ -1873,5 +1910,6 @@ public final class Pm { System.err.println("pm remove-user: remove the user with the given USER_IDENTIFIER,"); System.err.println(" deleting all data associated with that user"); System.err.println(""); + return 1; } } diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java index 13ceb4adfcdd..1e1b33f67496 100644 --- a/core/java/android/accessibilityservice/AccessibilityService.java +++ b/core/java/android/accessibilityservice/AccessibilityService.java @@ -24,13 +24,18 @@ import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.util.Log; +import android.view.Display; import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityInteractionClient; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityWindowInfo; import com.android.internal.os.HandlerCaller; +import com.android.internal.os.SomeArgs; import java.util.List; @@ -366,7 +371,7 @@ public abstract class AccessibilityService extends Service { public void onAccessibilityEvent(AccessibilityEvent event); public void onInterrupt(); public void onServiceConnected(); - public void onSetConnectionId(int connectionId); + public void init(int connectionId, IBinder windowToken); public boolean onGesture(int gestureId); public boolean onKeyEvent(KeyEvent event); } @@ -375,6 +380,10 @@ public abstract class AccessibilityService extends Service { private AccessibilityServiceInfo mInfo; + private IBinder mWindowToken; + + private WindowManager mWindowManager; + /** * Callback for {@link android.view.accessibility.AccessibilityEvent}s. * @@ -611,6 +620,18 @@ public abstract class AccessibilityService extends Service { } } + @Override + public Object getSystemService(String name) { + if (Context.WINDOW_SERVICE.equals(name)) { + if (mWindowManager == null) { + WindowManager wrapped = (WindowManager) super.getSystemService(name); + mWindowManager = new LocalWindowManager(wrapped); + } + return mWindowManager; + } + return super.getSystemService(name); + } + /** * Implement to return the implementation of the internal accessibility * service interface. @@ -634,8 +655,9 @@ public abstract class AccessibilityService extends Service { } @Override - public void onSetConnectionId( int connectionId) { + public void init(int connectionId, IBinder windowToken) { mConnectionId = connectionId; + mWindowToken = windowToken; } @Override @@ -658,7 +680,7 @@ public abstract class AccessibilityService extends Service { */ public static class IAccessibilityServiceClientWrapper extends IAccessibilityServiceClient.Stub implements HandlerCaller.Callback { - private static final int DO_SET_SET_CONNECTION = 1; + private static final int DO_INIT = 1; private static final int DO_ON_INTERRUPT = 2; private static final int DO_ON_ACCESSIBILITY_EVENT = 3; private static final int DO_ON_GESTURE = 4; @@ -677,9 +699,10 @@ public abstract class AccessibilityService extends Service { mCaller = new HandlerCaller(context, looper, this, true /*asyncHandler*/); } - public void setConnection(IAccessibilityServiceConnection connection, int connectionId) { - Message message = mCaller.obtainMessageIO(DO_SET_SET_CONNECTION, connectionId, - connection); + public void init(IAccessibilityServiceConnection connection, int connectionId, + IBinder windowToken) { + Message message = mCaller.obtainMessageIOO(DO_INIT, connectionId, + connection, windowToken); mCaller.sendMessage(message); } @@ -730,20 +753,24 @@ public abstract class AccessibilityService extends Service { mCallback.onInterrupt(); } return; - case DO_SET_SET_CONNECTION: { + case DO_INIT: { mConnectionId = message.arg1; + SomeArgs args = (SomeArgs) message.obj; IAccessibilityServiceConnection connection = - (IAccessibilityServiceConnection) message.obj; + (IAccessibilityServiceConnection) args.arg1; + IBinder windowToken = (IBinder) args.arg2; + args.recycle(); if (connection != null) { AccessibilityInteractionClient.getInstance().addConnection(mConnectionId, connection); - mCallback.onSetConnectionId(mConnectionId); + mCallback.init(mConnectionId, windowToken); mCallback.onServiceConnected(); } else { AccessibilityInteractionClient.getInstance().removeConnection( mConnectionId); + mConnectionId = AccessibilityInteractionClient.NO_ID; AccessibilityInteractionClient.getInstance().clearCache(); - mCallback.onSetConnectionId(AccessibilityInteractionClient.NO_ID); + mCallback.init(AccessibilityInteractionClient.NO_ID, null); } } return; @@ -785,4 +812,53 @@ public abstract class AccessibilityService extends Service { } } } + + private class LocalWindowManager implements WindowManager { + private final WindowManager mImpl; + + private LocalWindowManager(WindowManager impl) { + mImpl = impl; + } + + @Override + public Display getDefaultDisplay() { + return mImpl.getDefaultDisplay(); + } + + @Override + public void addView(View view, ViewGroup.LayoutParams params) { + if (!(params instanceof WindowManager.LayoutParams)) { + throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); + } + WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params; + if (windowParams.type == LayoutParams.TYPE_ACCESSIBILITY_OVERLAY + && windowParams.token == null) { + windowParams.token = mWindowToken; + } + mImpl.addView(view, params); + } + + @Override + public void updateViewLayout(View view, ViewGroup.LayoutParams params) { + if (!(params instanceof WindowManager.LayoutParams)) { + throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); + } + WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params; + if (windowParams.type == LayoutParams.TYPE_ACCESSIBILITY_OVERLAY + && windowParams.token == null) { + windowParams.token = mWindowToken; + } + mImpl.updateViewLayout(view, params); + } + + @Override + public void removeViewImmediate(View view) { + mImpl.removeViewImmediate(view); + } + + @Override + public void removeView(View view) { + mImpl.removeView(view); + } + } } diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl index 6ce0219b81f5..8b503ddad947 100644 --- a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl +++ b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl @@ -28,7 +28,7 @@ import android.view.KeyEvent; */ oneway interface IAccessibilityServiceClient { - void setConnection(in IAccessibilityServiceConnection connection, int connectionId); + void init(in IAccessibilityServiceConnection connection, int connectionId, IBinder windowToken); void onAccessibilityEvent(in AccessibilityEvent event); diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java index 3720c8191e77..da4870901db9 100644 --- a/core/java/android/animation/Animator.java +++ b/core/java/android/animation/Animator.java @@ -16,6 +16,8 @@ package android.animation; +import android.content.res.ConstantState; + import java.util.ArrayList; /** @@ -41,6 +43,18 @@ public abstract class Animator implements Cloneable { boolean mPaused = false; /** + * A set of flags which identify the type of configuration changes that can affect this + * Animator. Used by the Animator cache. + */ + int mChangingConfigurations = 0; + + /** + * If this animator is inflated from a constant state, keep a reference to it so that + * ConstantState will not be garbage collected until this animator is collected + */ + private AnimatorConstantState mConstantState; + + /** * Starts this animation. If the animation has a nonzero startDelay, the animation will start * running after that delay elapses. A non-delayed animation will have its initial * value(s) set immediately, followed by calls to @@ -295,25 +309,71 @@ public abstract class Animator implements Cloneable { } } + /** + * Return a mask of the configuration parameters for which this animator may change, requiring + * that it should be re-created from Resources. The default implementation returns whatever + * value was provided through setChangingConfigurations(int) or 0 by default. + * + * @return Returns a mask of the changing configuration parameters, as defined by + * {@link android.content.pm.ActivityInfo}. + * @see android.content.pm.ActivityInfo + * @hide + */ + public int getChangingConfigurations() { + return mChangingConfigurations; + } + + /** + * Set a mask of the configuration parameters for which this animator may change, requiring + * that it be re-created from resource. + * + * @param configs A mask of the changing configuration parameters, as + * defined by {@link android.content.pm.ActivityInfo}. + * + * @see android.content.pm.ActivityInfo + * @hide + */ + public void setChangingConfigurations(int configs) { + mChangingConfigurations = configs; + } + + /** + * Sets the changing configurations value to the union of the current changing configurations + * and the provided configs. + * This method is called while loading the animator. + * @hide + */ + public void appendChangingConfigurations(int configs) { + mChangingConfigurations |= configs; + } + + /** + * Return a {@link android.content.res.ConstantState} instance that holds the shared state of + * this Animator. + * <p> + * This constant state is used to create new instances of this animator when needed, instead + * of re-loading it from resources. Default implementation creates a new + * {@link AnimatorConstantState}. You can override this method to provide your custom logic or + * return null if you don't want this animator to be cached. + * + * @return The ConfigurationBoundResourceCache.BaseConstantState associated to this Animator. + * @see android.content.res.ConstantState + * @see #clone() + * @hide + */ + public ConstantState<Animator> createConstantState() { + return new AnimatorConstantState(this); + } + @Override public Animator clone() { try { final Animator anim = (Animator) super.clone(); if (mListeners != null) { - ArrayList<AnimatorListener> oldListeners = mListeners; - anim.mListeners = new ArrayList<AnimatorListener>(); - int numListeners = oldListeners.size(); - for (int i = 0; i < numListeners; ++i) { - anim.mListeners.add(oldListeners.get(i)); - } + anim.mListeners = new ArrayList<AnimatorListener>(mListeners); } if (mPauseListeners != null) { - ArrayList<AnimatorPauseListener> oldListeners = mPauseListeners; - anim.mPauseListeners = new ArrayList<AnimatorPauseListener>(); - int numListeners = oldListeners.size(); - for (int i = 0; i < numListeners; ++i) { - anim.mPauseListeners.add(oldListeners.get(i)); - } + anim.mPauseListeners = new ArrayList<AnimatorPauseListener>(mPauseListeners); } return anim; } catch (CloneNotSupportedException e) { @@ -469,4 +529,35 @@ public abstract class Animator implements Cloneable { public void setAllowRunningAsynchronously(boolean mayRunAsync) { // It is up to subclasses to support this, if they can. } + + /** + * Creates a {@link ConstantState} which holds changing configurations information associated + * with the given Animator. + * <p> + * When {@link #newInstance()} is called, default implementation clones the Animator. + */ + private static class AnimatorConstantState extends ConstantState<Animator> { + + final Animator mAnimator; + int mChangingConf; + + public AnimatorConstantState(Animator animator) { + mAnimator = animator; + // ensure a reference back to here so that constante state is not gc'ed. + mAnimator.mConstantState = this; + mChangingConf = mAnimator.getChangingConfigurations(); + } + + @Override + public int getChangingConfigurations() { + return mChangingConf; + } + + @Override + public Animator newInstance() { + final Animator clone = mAnimator.clone(); + clone.mConstantState = this; + return clone; + } + } } diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java index 25417edb6f62..688d7e42dd36 100644 --- a/core/java/android/animation/AnimatorInflater.java +++ b/core/java/android/animation/AnimatorInflater.java @@ -16,6 +16,8 @@ package android.animation; import android.content.Context; +import android.content.res.ConfigurationBoundResourceCache; +import android.content.res.ConstantState; import android.content.res.Resources; import android.content.res.Resources.NotFoundException; import android.content.res.Resources.Theme; @@ -30,6 +32,8 @@ import android.util.TypedValue; import android.util.Xml; import android.view.InflateException; import android.view.animation.AnimationUtils; +import android.view.animation.BaseInterpolator; +import android.view.animation.Interpolator; import com.android.internal.R; @@ -67,6 +71,9 @@ public class AnimatorInflater { private static final boolean DBG_ANIMATOR_INFLATER = false; + // used to calculate changing configs for resource references + private static final TypedValue sTmpTypedValue = new TypedValue(); + /** * Loads an {@link Animator} object from a resource * @@ -98,11 +105,34 @@ public class AnimatorInflater { /** @hide */ public static Animator loadAnimator(Resources resources, Theme theme, int id, float pathErrorScale) throws NotFoundException { - + final ConfigurationBoundResourceCache<Animator> animatorCache = resources + .getAnimatorCache(); + Animator animator = animatorCache.get(id, theme); + if (animator != null) { + if (DBG_ANIMATOR_INFLATER) { + Log.d(TAG, "loaded animator from cache, " + resources.getResourceName(id)); + } + return animator; + } else if (DBG_ANIMATOR_INFLATER) { + Log.d(TAG, "cache miss for animator " + resources.getResourceName(id)); + } XmlResourceParser parser = null; try { parser = resources.getAnimation(id); - return createAnimatorFromXml(resources, theme, parser, pathErrorScale); + animator = createAnimatorFromXml(resources, theme, parser, pathErrorScale); + if (animator != null) { + animator.appendChangingConfigurations(getChangingConfigs(resources, id)); + final ConstantState<Animator> constantState = animator.createConstantState(); + if (constantState != null) { + if (DBG_ANIMATOR_INFLATER) { + Log.d(TAG, "caching animator for res " + resources.getResourceName(id)); + } + animatorCache.put(id, theme, constantState); + // create a new animator so that cached version is never used by the user + animator = constantState.newInstance(resources, theme); + } + } + return animator; } catch (XmlPullParserException ex) { Resources.NotFoundException rnf = new Resources.NotFoundException("Can't load animation resource ID #0x" + @@ -122,10 +152,29 @@ public class AnimatorInflater { public static StateListAnimator loadStateListAnimator(Context context, int id) throws NotFoundException { + final Resources resources = context.getResources(); + final ConfigurationBoundResourceCache<StateListAnimator> cache = resources + .getStateListAnimatorCache(); + final Theme theme = context.getTheme(); + StateListAnimator animator = cache.get(id, theme); + if (animator != null) { + return animator; + } XmlResourceParser parser = null; try { - parser = context.getResources().getAnimation(id); - return createStateListAnimatorFromXml(context, parser, Xml.asAttributeSet(parser)); + parser = resources.getAnimation(id); + animator = createStateListAnimatorFromXml(context, parser, Xml.asAttributeSet(parser)); + if (animator != null) { + animator.appendChangingConfigurations(getChangingConfigs(resources, id)); + final ConstantState<StateListAnimator> constantState = animator + .createConstantState(); + if (constantState != null) { + cache.put(id, theme, constantState); + // return a clone so that the animator in constant state is never used. + animator = constantState.newInstance(resources, theme); + } + } + return animator; } catch (XmlPullParserException ex) { Resources.NotFoundException rnf = new Resources.NotFoundException( @@ -172,14 +221,13 @@ public class AnimatorInflater { for (int i = 0; i < attributeCount; i++) { int attrName = attributeSet.getAttributeNameResource(i); if (attrName == R.attr.animation) { - animator = loadAnimator(context, - attributeSet.getAttributeResourceValue(i, 0)); + final int animId = attributeSet.getAttributeResourceValue(i, 0); + animator = loadAnimator(context, animId); } else { states[stateIndex++] = attributeSet.getAttributeBooleanValue(i, false) ? attrName : -attrName; } - } if (animator == null) { animator = createAnimatorFromXml(context.getResources(), @@ -192,7 +240,6 @@ public class AnimatorInflater { } stateListAnimator .addState(StateSet.trimStateSet(states, stateIndex), animator); - } break; } @@ -508,7 +555,6 @@ public class AnimatorInflater { private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser, AttributeSet attrs, AnimatorSet parent, int sequenceOrdering, float pixelSize) throws XmlPullParserException, IOException { - Animator anim = null; ArrayList<Animator> childAnims = null; @@ -537,8 +583,8 @@ public class AnimatorInflater { } else { a = res.obtainAttributes(attrs, R.styleable.AnimatorSet); } - int ordering = a.getInt(R.styleable.AnimatorSet_ordering, - TOGETHER); + anim.appendChangingConfigurations(a.getChangingConfigurations()); + int ordering = a.getInt(R.styleable.AnimatorSet_ordering, TOGETHER); createAnimatorFromXml(res, theme, parser, attrs, (AnimatorSet) anim, ordering, pixelSize); a.recycle(); @@ -565,7 +611,6 @@ public class AnimatorInflater { parent.playSequentially(animsArray); } } - return anim; } @@ -591,7 +636,6 @@ public class AnimatorInflater { private static ValueAnimator loadAnimator(Resources res, Theme theme, AttributeSet attrs, ValueAnimator anim, float pathErrorScale) throws NotFoundException { - TypedArray arrayAnimator = null; TypedArray arrayObjectAnimator = null; @@ -609,25 +653,37 @@ public class AnimatorInflater { } else { arrayObjectAnimator = res.obtainAttributes(attrs, R.styleable.PropertyAnimator); } + anim.appendChangingConfigurations(arrayObjectAnimator.getChangingConfigurations()); } if (anim == null) { anim = new ValueAnimator(); } + anim.appendChangingConfigurations(arrayAnimator.getChangingConfigurations()); parseAnimatorFromTypeArray(anim, arrayAnimator, arrayObjectAnimator, pathErrorScale); - final int resID = - arrayAnimator.getResourceId(R.styleable.Animator_interpolator, 0); + final int resID = arrayAnimator.getResourceId(R.styleable.Animator_interpolator, 0); if (resID > 0) { - anim.setInterpolator(AnimationUtils.loadInterpolator(res, theme, resID)); + final Interpolator interpolator = AnimationUtils.loadInterpolator(res, theme, resID); + if (interpolator instanceof BaseInterpolator) { + anim.appendChangingConfigurations( + ((BaseInterpolator) interpolator).getChangingConfiguration()); + } + anim.setInterpolator(interpolator); } arrayAnimator.recycle(); if (arrayObjectAnimator != null) { arrayObjectAnimator.recycle(); } - return anim; } + + private static int getChangingConfigs(Resources resources, int id) { + synchronized (sTmpTypedValue) { + resources.getValue(id, sTmpTypedValue, true); + return sTmpTypedValue.changingConfigurations; + } + } } diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java index 0aa8fdd06e23..92762c33674f 100644 --- a/core/java/android/animation/AnimatorSet.java +++ b/core/java/android/animation/AnimatorSet.java @@ -241,6 +241,19 @@ public final class AnimatorSet extends Animator { } /** + * @hide + */ + @Override + public int getChangingConfigurations() { + int conf = super.getChangingConfigurations(); + final int nodeCount = mNodes.size(); + for (int i = 0; i < nodeCount; i ++) { + conf |= mNodes.get(i).animation.getChangingConfigurations(); + } + return conf; + } + + /** * Sets the TimeInterpolator for all current {@link #getChildAnimations() child animations} * of this AnimatorSet. The default value is null, which means that no interpolator * is set on this AnimatorSet. Setting the interpolator to any non-null value @@ -628,23 +641,25 @@ public final class AnimatorSet extends Animator { * manually, as we clone each Node (and its animation). The clone will then be sorted, * and will populate any appropriate lists, when it is started. */ + final int nodeCount = mNodes.size(); anim.mNeedsSort = true; anim.mTerminated = false; anim.mStarted = false; anim.mPlayingSet = new ArrayList<Animator>(); anim.mNodeMap = new HashMap<Animator, Node>(); - anim.mNodes = new ArrayList<Node>(); - anim.mSortedNodes = new ArrayList<Node>(); + anim.mNodes = new ArrayList<Node>(nodeCount); + anim.mSortedNodes = new ArrayList<Node>(nodeCount); anim.mReversible = mReversible; anim.mSetListener = null; // Walk through the old nodes list, cloning each node and adding it to the new nodemap. // One problem is that the old node dependencies point to nodes in the old AnimatorSet. // We need to track the old/new nodes in order to reconstruct the dependencies in the clone. - HashMap<Node, Node> nodeCloneMap = new HashMap<Node, Node>(); // <old, new> - for (Node node : mNodes) { + + for (int n = 0; n < nodeCount; n++) { + final Node node = mNodes.get(n); Node nodeClone = node.clone(); - nodeCloneMap.put(node, nodeClone); + node.mTmpClone = nodeClone; anim.mNodes.add(nodeClone); anim.mNodeMap.put(nodeClone.animation, nodeClone); // Clear out the dependencies in the clone; we'll set these up manually later @@ -652,40 +667,50 @@ public final class AnimatorSet extends Animator { nodeClone.tmpDependencies = null; nodeClone.nodeDependents = null; nodeClone.nodeDependencies = null; + // clear out any listeners that were set up by the AnimatorSet; these will // be set up when the clone's nodes are sorted - ArrayList<AnimatorListener> cloneListeners = nodeClone.animation.getListeners(); + final ArrayList<AnimatorListener> cloneListeners = nodeClone.animation.getListeners(); if (cloneListeners != null) { - ArrayList<AnimatorListener> listenersToRemove = null; - for (AnimatorListener listener : cloneListeners) { + for (int i = cloneListeners.size() - 1; i >= 0; i--) { + final AnimatorListener listener = cloneListeners.get(i); if (listener instanceof AnimatorSetListener) { - if (listenersToRemove == null) { - listenersToRemove = new ArrayList<AnimatorListener>(); - } - listenersToRemove.add(listener); - } - } - if (listenersToRemove != null) { - for (AnimatorListener listener : listenersToRemove) { - cloneListeners.remove(listener); + cloneListeners.remove(i); } } } } // Now that we've cloned all of the nodes, we're ready to walk through their // dependencies, mapping the old dependencies to the new nodes - for (Node node : mNodes) { - Node nodeClone = nodeCloneMap.get(node); + for (int n = 0; n < nodeCount; n++) { + final Node node = mNodes.get(n); + final Node clone = node.mTmpClone; if (node.dependencies != null) { - for (Dependency dependency : node.dependencies) { - Node clonedDependencyNode = nodeCloneMap.get(dependency.node); - Dependency cloneDependency = new Dependency(clonedDependencyNode, + clone.dependencies = new ArrayList<Dependency>(node.dependencies.size()); + final int depSize = node.dependencies.size(); + for (int i = 0; i < depSize; i ++) { + final Dependency dependency = node.dependencies.get(i); + Dependency cloneDependency = new Dependency(dependency.node.mTmpClone, dependency.rule); - nodeClone.addDependency(cloneDependency); + clone.dependencies.add(cloneDependency); + } + } + if (node.nodeDependents != null) { + clone.nodeDependents = new ArrayList<Node>(node.nodeDependents.size()); + for (Node dep : node.nodeDependents) { + clone.nodeDependents.add(dep.mTmpClone); + } + } + if (node.nodeDependencies != null) { + clone.nodeDependencies = new ArrayList<Node>(node.nodeDependencies.size()); + for (Node dep : node.nodeDependencies) { + clone.nodeDependencies.add(dep.mTmpClone); } } } - + for (int n = 0; n < nodeCount; n++) { + mNodes.get(n).mTmpClone = null; + } return anim; } @@ -1017,6 +1042,11 @@ public final class AnimatorSet extends Animator { public boolean done = false; /** + * Temporary field to hold the clone in AnimatorSet#clone. Cleaned after clone is complete + */ + private Node mTmpClone = null; + + /** * Constructs the Node with the animation that it encapsulates. A Node has no * dependencies by default; dependencies are added via the addDependency() * method. diff --git a/core/java/android/animation/FloatKeyframeSet.java b/core/java/android/animation/FloatKeyframeSet.java index 12e586293005..abac24671c87 100644 --- a/core/java/android/animation/FloatKeyframeSet.java +++ b/core/java/android/animation/FloatKeyframeSet.java @@ -19,6 +19,7 @@ package android.animation; import android.animation.Keyframe.FloatKeyframe; import java.util.ArrayList; +import java.util.List; /** * This class holds a collection of FloatKeyframe objects and is called by ValueAnimator to calculate @@ -47,8 +48,8 @@ class FloatKeyframeSet extends KeyframeSet implements Keyframes.FloatKeyframes { @Override public FloatKeyframeSet clone() { - ArrayList<Keyframe> keyframes = mKeyframes; - int numKeyframes = mKeyframes.size(); + final List<Keyframe> keyframes = mKeyframes; + final int numKeyframes = mKeyframes.size(); FloatKeyframe[] newKeyframes = new FloatKeyframe[numKeyframes]; for (int i = 0; i < numKeyframes; ++i) { newKeyframes[i] = (FloatKeyframe) keyframes.get(i).clone(); diff --git a/core/java/android/animation/IntKeyframeSet.java b/core/java/android/animation/IntKeyframeSet.java index 7a5b0ece4bae..0ec5138922be 100644 --- a/core/java/android/animation/IntKeyframeSet.java +++ b/core/java/android/animation/IntKeyframeSet.java @@ -19,6 +19,7 @@ package android.animation; import android.animation.Keyframe.IntKeyframe; import java.util.ArrayList; +import java.util.List; /** * This class holds a collection of IntKeyframe objects and is called by ValueAnimator to calculate @@ -47,7 +48,7 @@ class IntKeyframeSet extends KeyframeSet implements Keyframes.IntKeyframes { @Override public IntKeyframeSet clone() { - ArrayList<Keyframe> keyframes = mKeyframes; + List<Keyframe> keyframes = mKeyframes; int numKeyframes = mKeyframes.size(); IntKeyframe[] newKeyframes = new IntKeyframe[numKeyframes]; for (int i = 0; i < numKeyframes; ++i) { diff --git a/core/java/android/animation/KeyframeSet.java b/core/java/android/animation/KeyframeSet.java index 8d15db2fbdf8..0e99bff257ff 100644 --- a/core/java/android/animation/KeyframeSet.java +++ b/core/java/android/animation/KeyframeSet.java @@ -18,6 +18,8 @@ package android.animation; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; + import android.animation.Keyframe.IntKeyframe; import android.animation.Keyframe.FloatKeyframe; import android.animation.Keyframe.ObjectKeyframe; @@ -36,16 +38,16 @@ class KeyframeSet implements Keyframes { Keyframe mFirstKeyframe; Keyframe mLastKeyframe; TimeInterpolator mInterpolator; // only used in the 2-keyframe case - ArrayList<Keyframe> mKeyframes; // only used when there are not 2 keyframes + List<Keyframe> mKeyframes; // only used when there are not 2 keyframes TypeEvaluator mEvaluator; public KeyframeSet(Keyframe... keyframes) { mNumKeyframes = keyframes.length; - mKeyframes = new ArrayList<Keyframe>(); - mKeyframes.addAll(Arrays.asList(keyframes)); - mFirstKeyframe = mKeyframes.get(0); - mLastKeyframe = mKeyframes.get(mNumKeyframes - 1); + // immutable list + mKeyframes = Arrays.asList(keyframes); + mFirstKeyframe = keyframes[0]; + mLastKeyframe = keyframes[mNumKeyframes - 1]; mInterpolator = mLastKeyframe.getInterpolator(); } @@ -57,7 +59,7 @@ class KeyframeSet implements Keyframes { public void invalidateCache() { } - public ArrayList<Keyframe> getKeyframes() { + public List<Keyframe> getKeyframes() { return mKeyframes; } @@ -177,9 +179,9 @@ class KeyframeSet implements Keyframes { @Override public KeyframeSet clone() { - ArrayList<Keyframe> keyframes = mKeyframes; + List<Keyframe> keyframes = mKeyframes; int numKeyframes = mKeyframes.size(); - Keyframe[] newKeyframes = new Keyframe[numKeyframes]; + final Keyframe[] newKeyframes = new Keyframe[numKeyframes]; for (int i = 0; i < numKeyframes; ++i) { newKeyframes[i] = keyframes.get(i).clone(); } diff --git a/core/java/android/animation/Keyframes.java b/core/java/android/animation/Keyframes.java index 6611c6caf4a5..c921466b328f 100644 --- a/core/java/android/animation/Keyframes.java +++ b/core/java/android/animation/Keyframes.java @@ -16,6 +16,7 @@ package android.animation; import java.util.ArrayList; +import java.util.List; /** * This interface abstracts a collection of Keyframe objects and is called by @@ -62,7 +63,7 @@ interface Keyframes extends Cloneable { * @return A list of all Keyframes contained by this. This may return null if this is * not made up of Keyframes. */ - ArrayList<Keyframe> getKeyframes(); + List<Keyframe> getKeyframes(); Keyframes clone(); diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java index d372933e0265..97426c381cdf 100644 --- a/core/java/android/animation/PropertyValuesHolder.java +++ b/core/java/android/animation/PropertyValuesHolder.java @@ -27,6 +27,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.concurrent.locks.ReentrantReadWriteLock; /** @@ -791,7 +792,7 @@ public class PropertyValuesHolder implements Cloneable { // check to make sure that mProperty is on the class of target try { Object testValue = null; - ArrayList<Keyframe> keyframes = mKeyframes.getKeyframes(); + List<Keyframe> keyframes = mKeyframes.getKeyframes(); int keyframeCount = keyframes == null ? 0 : keyframes.size(); for (int i = 0; i < keyframeCount; i++) { Keyframe kf = keyframes.get(i); @@ -814,7 +815,7 @@ public class PropertyValuesHolder implements Cloneable { if (mSetter == null) { setupSetter(targetClass); } - ArrayList<Keyframe> keyframes = mKeyframes.getKeyframes(); + List<Keyframe> keyframes = mKeyframes.getKeyframes(); int keyframeCount = keyframes == null ? 0 : keyframes.size(); for (int i = 0; i < keyframeCount; i++) { Keyframe kf = keyframes.get(i); @@ -890,7 +891,7 @@ public class PropertyValuesHolder implements Cloneable { * @param target The object which holds the start values that should be set. */ void setupStartValue(Object target) { - ArrayList<Keyframe> keyframes = mKeyframes.getKeyframes(); + List<Keyframe> keyframes = mKeyframes.getKeyframes(); if (!keyframes.isEmpty()) { setupValue(target, keyframes.get(0)); } @@ -905,7 +906,7 @@ public class PropertyValuesHolder implements Cloneable { * @param target The object which holds the start values that should be set. */ void setupEndValue(Object target) { - ArrayList<Keyframe> keyframes = mKeyframes.getKeyframes(); + List<Keyframe> keyframes = mKeyframes.getKeyframes(); if (!keyframes.isEmpty()) { setupValue(target, keyframes.get(keyframes.size() - 1)); } diff --git a/core/java/android/animation/StateListAnimator.java b/core/java/android/animation/StateListAnimator.java index 7256a0638e10..d49e914cf5cc 100644 --- a/core/java/android/animation/StateListAnimator.java +++ b/core/java/android/animation/StateListAnimator.java @@ -16,6 +16,7 @@ package android.animation; +import android.content.res.ConstantState; import android.util.StateSet; import android.view.View; @@ -44,25 +45,31 @@ import java.util.ArrayList; * @attr ref android.R.styleable#DrawableStates_state_pressed * @attr ref android.R.styleable#StateListAnimatorItem_animation */ -public class StateListAnimator { - - private final ArrayList<Tuple> mTuples = new ArrayList<Tuple>(); +public class StateListAnimator implements Cloneable { + private ArrayList<Tuple> mTuples = new ArrayList<Tuple>(); private Tuple mLastMatch = null; - private Animator mRunningAnimator = null; - private WeakReference<View> mViewRef; + private StateListAnimatorConstantState mConstantState; + private AnimatorListenerAdapter mAnimatorListener; + private int mChangingConfigurations; - private AnimatorListenerAdapter mAnimatorListener = new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - animation.setTarget(null); - if (mRunningAnimator == animation) { - mRunningAnimator = null; + public StateListAnimator() { + initAnimatorListener(); + } + + private void initAnimatorListener() { + mAnimatorListener = new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + animation.setTarget(null); + if (mRunningAnimator == animation) { + mRunningAnimator = null; + } } - } - }; + }; + } /** * Associates the given animator with the provided drawable state specs so that it will be run @@ -75,6 +82,7 @@ public class StateListAnimator { Tuple tuple = new Tuple(specs, animator); tuple.mAnimator.addListener(mAnimatorListener); mTuples.add(tuple); + mChangingConfigurations |= animator.getChangingConfigurations(); } /** @@ -118,12 +126,35 @@ public class StateListAnimator { for (int i = 0; i < size; i++) { mTuples.get(i).mAnimator.setTarget(null); } - mViewRef = null; mLastMatch = null; mRunningAnimator = null; } + @Override + public StateListAnimator clone() { + try { + StateListAnimator clone = (StateListAnimator) super.clone(); + clone.mTuples = new ArrayList<Tuple>(mTuples.size()); + clone.mLastMatch = null; + clone.mRunningAnimator = null; + clone.mViewRef = null; + clone.mAnimatorListener = null; + clone.initAnimatorListener(); + final int tupleSize = mTuples.size(); + for (int i = 0; i < tupleSize; i++) { + final Tuple tuple = mTuples.get(i); + final Animator animatorClone = tuple.mAnimator.clone(); + animatorClone.removeListener(mAnimatorListener); + clone.addState(tuple.mSpecs, animatorClone); + } + clone.setChangingConfigurations(getChangingConfigurations()); + return clone; + } catch (CloneNotSupportedException e) { + throw new AssertionError("cannot clone state list animator", e); + } + } + /** * Called by View * @hide @@ -182,6 +213,63 @@ public class StateListAnimator { } /** + * Return a mask of the configuration parameters for which this animator may change, requiring + * that it be re-created. The default implementation returns whatever was provided through + * {@link #setChangingConfigurations(int)} or 0 by default. + * + * @return Returns a mask of the changing configuration parameters, as defined by + * {@link android.content.pm.ActivityInfo}. + * + * @see android.content.pm.ActivityInfo + * @hide + */ + public int getChangingConfigurations() { + return mChangingConfigurations; + } + + /** + * Set a mask of the configuration parameters for which this animator may change, requiring + * that it should be recreated from resources instead of being cloned. + * + * @param configs A mask of the changing configuration parameters, as + * defined by {@link android.content.pm.ActivityInfo}. + * + * @see android.content.pm.ActivityInfo + * @hide + */ + public void setChangingConfigurations(int configs) { + mChangingConfigurations = configs; + } + + /** + * Sets the changing configurations value to the union of the current changing configurations + * and the provided configs. + * This method is called while loading the animator. + * @hide + */ + public void appendChangingConfigurations(int configs) { + mChangingConfigurations |= configs; + } + + /** + * Return a {@link android.content.res.ConstantState} instance that holds the shared state of + * this Animator. + * <p> + * This constant state is used to create new instances of this animator when needed. Default + * implementation creates a new {@link StateListAnimatorConstantState}. You can override this + * method to provide your custom logic or return null if you don't want this animator to be + * cached. + * + * @return The {@link android.content.res.ConstantState} associated to this Animator. + * @see android.content.res.ConstantState + * @see #clone() + * @hide + */ + public ConstantState<StateListAnimator> createConstantState() { + return new StateListAnimatorConstantState(this); + } + + /** * @hide */ public static class Tuple { @@ -209,4 +297,36 @@ public class StateListAnimator { return mAnimator; } } + + /** + * Creates a constant state which holds changing configurations information associated with the + * given Animator. + * <p> + * When new instance is called, default implementation clones the Animator. + */ + private static class StateListAnimatorConstantState + extends ConstantState<StateListAnimator> { + + final StateListAnimator mAnimator; + + int mChangingConf; + + public StateListAnimatorConstantState(StateListAnimator animator) { + mAnimator = animator; + mAnimator.mConstantState = this; + mChangingConf = mAnimator.getChangingConfigurations(); + } + + @Override + public int getChangingConfigurations() { + return mChangingConf; + } + + @Override + public StateListAnimator newInstance() { + final StateListAnimator clone = mAnimator.clone(); + clone.mConstantState = this; + return clone; + } + } } diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java index 0d17d6716d6d..07f79b8b33a2 100644 --- a/core/java/android/animation/ValueAnimator.java +++ b/core/java/android/animation/ValueAnimator.java @@ -16,6 +16,7 @@ package android.animation; +import android.content.res.ConfigurationBoundResourceCache; import android.os.Looper; import android.os.Trace; import android.util.AndroidRuntimeException; @@ -1289,12 +1290,7 @@ public class ValueAnimator extends Animator { public ValueAnimator clone() { final ValueAnimator anim = (ValueAnimator) super.clone(); if (mUpdateListeners != null) { - ArrayList<AnimatorUpdateListener> oldListeners = mUpdateListeners; - anim.mUpdateListeners = new ArrayList<AnimatorUpdateListener>(); - int numListeners = oldListeners.size(); - for (int i = 0; i < numListeners; ++i) { - anim.mUpdateListeners.add(oldListeners.get(i)); - } + anim.mUpdateListeners = new ArrayList<AnimatorUpdateListener>(mUpdateListeners); } anim.mSeekTime = -1; anim.mPlayingBackwards = false; diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index dd49009281f3..fa15ad758cc6 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -2513,7 +2513,12 @@ public final class ActivityThread { } public void handleInstallProvider(ProviderInfo info) { - installContentProviders(mInitialApplication, Lists.newArrayList(info)); + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + installContentProviders(mInitialApplication, Lists.newArrayList(info)); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } } private void handleEnterAnimationComplete(IBinder token) { diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java index 540376ec5fb7..9062892efde9 100644 --- a/core/java/android/app/ActivityTransitionCoordinator.java +++ b/core/java/android/app/ActivityTransitionCoordinator.java @@ -206,6 +206,8 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { private ArrayList<GhostViewListeners> mGhostViewListeners = new ArrayList<GhostViewListeners>(); private ArrayMap<View, Float> mOriginalAlphas = new ArrayMap<View, Float>(); + final private ArrayList<View> mRootSharedElements = new ArrayList<View>(); + private ArrayList<Matrix> mSharedElementParentMatrices; public ActivityTransitionCoordinator(Window window, ArrayList<String> allSharedElementNames, @@ -222,8 +224,7 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { if (mListener != null) { mListener.onMapSharedElements(mAllSharedElementNames, sharedElements); } - mSharedElementNames.addAll(sharedElements.keySet()); - mSharedElements.addAll(sharedElements.values()); + setSharedElements(sharedElements); if (getViewsTransition() != null && mTransitioningViews != null) { ViewGroup decorView = getDecor(); if (decorView != null) { @@ -234,6 +235,58 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { setEpicenter(); } + /** + * Iterates over the shared elements and adds them to the members in order. + * Shared elements that are nested in other shared elements are placed after the + * elements that they are nested in. This means that layout ordering can be done + * from first to last. + * + * @param sharedElements The map of transition names to shared elements to set into + * the member fields. + */ + private void setSharedElements(ArrayMap<String, View> sharedElements) { + boolean isFirstRun = true; + while (!sharedElements.isEmpty()) { + final int numSharedElements = sharedElements.size(); + for (int i = numSharedElements - 1; i >= 0; i--) { + final View view = sharedElements.valueAt(i); + final String name = sharedElements.keyAt(i); + if (isFirstRun && (view == null || !view.isAttachedToWindow() || name == null)) { + sharedElements.removeAt(i); + } else { + if (!isNested(view, sharedElements)) { + mSharedElementNames.add(name); + mSharedElements.add(view); + sharedElements.removeAt(i); + if (isFirstRun) { + // We need to keep track which shared elements are roots + // and which are nested. + mRootSharedElements.add(view); + } + } + } + } + isFirstRun = false; + } + } + + /** + * Returns true when view is nested in any of the values of sharedElements. + */ + private static boolean isNested(View view, ArrayMap<String, View> sharedElements) { + ViewParent parent = view.getParent(); + boolean isNested = false; + while (parent instanceof View) { + View parentView = (View) parent; + if (sharedElements.containsValue(parentView)) { + isNested = true; + break; + } + parent = parentView.getParent(); + } + return isNested; + } + protected void stripOffscreenViews() { if (mTransitioningViews == null) { return; @@ -449,11 +502,50 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { view.layout(x, y, x + width, y + height); } - protected void getSharedElementParentMatrix(View view, Matrix matrix) { - // Find the location in the view's parent - ViewGroup parent = (ViewGroup) view.getParent(); - matrix.reset(); - parent.transformMatrixToLocal(matrix); + private void setSharedElementMatrices() { + int numSharedElements = mSharedElements.size(); + if (numSharedElements > 0) { + mSharedElementParentMatrices = new ArrayList<Matrix>(numSharedElements); + } + for (int i = 0; i < numSharedElements; i++) { + View view = mSharedElements.get(i); + + // Find the location in the view's parent + ViewGroup parent = (ViewGroup) view.getParent(); + Matrix matrix = new Matrix(); + parent.transformMatrixToLocal(matrix); + + mSharedElementParentMatrices.add(matrix); + } + } + + private void getSharedElementParentMatrix(View view, Matrix matrix) { + final boolean isNestedInOtherSharedElement = !mRootSharedElements.contains(view); + final boolean useParentMatrix; + if (isNestedInOtherSharedElement) { + useParentMatrix = true; + } else { + final int index = mSharedElementParentMatrices == null ? -1 + : mSharedElements.indexOf(view); + if (index < 0) { + useParentMatrix = true; + } else { + // The indices of mSharedElementParentMatrices matches the + // mSharedElement matrices. + Matrix parentMatrix = mSharedElementParentMatrices.get(index); + matrix.set(parentMatrix); + useParentMatrix = false; + } + } + if (useParentMatrix) { + matrix.reset(); + ViewParent viewParent = view.getParent(); + if (viewParent instanceof ViewGroup) { + // Find the location in the view's parent + ViewGroup parent = (ViewGroup) viewParent; + parent.transformMatrixToLocal(matrix); + } + } } protected ArrayList<SharedElementOriginalState> setSharedElementState( @@ -536,16 +628,17 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { protected ArrayList<View> createSnapshots(Bundle state, Collection<String> names) { int numSharedElements = names.size(); + ArrayList<View> snapshots = new ArrayList<View>(numSharedElements); if (numSharedElements == 0) { - return null; + return snapshots; } - ArrayList<View> snapshots = new ArrayList<View>(numSharedElements); Context context = getWindow().getContext(); int[] decorLoc = new int[2]; ViewGroup decorView = getDecor(); if (decorView != null) { decorView.getLocationOnScreen(decorLoc); } + Matrix tempMatrix = new Matrix(); for (String name: names) { Bundle sharedElementBundle = state.getBundle(name); if (sharedElementBundle != null) { @@ -555,7 +648,7 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { snapshot = mListener.onCreateSnapshotView(context, parcelable); } if (snapshot != null) { - setSharedElementState(snapshot, name, state, null, null, decorLoc); + setSharedElementState(snapshot, name, state, tempMatrix, null, decorLoc); } snapshots.add(snapshot); } @@ -607,6 +700,8 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { mResultReceiver = null; mPendingTransition = null; mListener = null; + mRootSharedElements.clear(); + mSharedElementParentMatrices = null; } protected long getFadeDuration() { @@ -704,9 +799,10 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { } protected void moveSharedElementsToOverlay() { - if (!mWindow.getSharedElementsUseOverlay()) { + if (mWindow == null || !mWindow.getSharedElementsUseOverlay()) { return; } + setSharedElementMatrices(); int numSharedElements = mSharedElements.size(); ViewGroup decor = getDecor(); if (decor != null) { diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 1e1a6130bb18..967e97e5af66 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -1609,6 +1609,18 @@ final class ApplicationPackageManager extends PackageManager { return null; } + /** + * @hide + */ + @Override + public boolean isUpgrade() { + try { + return mPM.isUpgrade(); + } catch (RemoteException e) { + return false; + } + } + @Override public PackageInstaller getPackageInstaller() { synchronized (mLock) { @@ -1664,6 +1676,17 @@ final class ApplicationPackageManager extends PackageManager { * @hide */ public Drawable loadItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) { + Drawable dr = loadUnbadgedItemIcon(itemInfo, appInfo); + if (itemInfo.showUserIcon != UserHandle.USER_NULL) { + return dr; + } + return getUserBadgedIcon(dr, new UserHandle(mContext.getUserId())); + } + + /** + * @hide + */ + public Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) { if (itemInfo.showUserIcon != UserHandle.USER_NULL) { Bitmap bitmap = getUserManager().getUserIcon(itemInfo.showUserIcon); if (bitmap == null) { @@ -1678,7 +1701,7 @@ final class ApplicationPackageManager extends PackageManager { if (dr == null) { dr = itemInfo.loadDefaultIcon(this); } - return getUserBadgedIcon(dr, new UserHandle(mContext.getUserId())); + return dr; } private Drawable getBadgedDrawable(Drawable drawable, Drawable badgeDrawable, diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java index add67f2ec8a5..ecf19c783e83 100644 --- a/core/java/android/app/EnterTransitionCoordinator.java +++ b/core/java/android/app/EnterTransitionCoordinator.java @@ -57,7 +57,6 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { private boolean mIsViewsTransitionStarted; private boolean mIsViewsTransitionComplete; private boolean mIsSharedElementTransitionComplete; - private ArrayList<Matrix> mSharedElementParentMatrices; private Transition mEnterViewsTransition; public EnterTransitionCoordinator(Activity activity, ResultReceiver resultReceiver, @@ -122,7 +121,6 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { if (mIsReturning) { sendSharedElementDestination(); } else { - setSharedElementMatrices(); moveSharedElementsToOverlay(); } if (mSharedElementsBundle != null) { @@ -135,16 +133,17 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { return; } mAreViewsReady = true; + final ViewGroup decor = getDecor(); // Ensure the views have been laid out before capturing the views -- we need the epicenter. - if (sharedElements.isEmpty() || !sharedElements.valueAt(0).isLayoutRequested()) { + if (decor == null || (decor.isAttachedToWindow() && + (sharedElements.isEmpty() || !sharedElements.valueAt(0).isLayoutRequested()))) { viewsReady(sharedElements); } else { - final View sharedElement = sharedElements.valueAt(0); - sharedElement.getViewTreeObserver() + decor.getViewTreeObserver() .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { - sharedElement.getViewTreeObserver().removeOnPreDrawListener(this); + decor.getViewTreeObserver().removeOnPreDrawListener(this); viewsReady(sharedElements); return true; } @@ -194,7 +193,6 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { } if (allReady) { Bundle state = captureSharedElementState(); - setSharedElementMatrices(); moveSharedElementsToOverlay(); mResultReceiver.send(MSG_SHARED_ELEMENT_DESTINATION, state); } else if (decorView != null) { @@ -205,7 +203,6 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { decorView.getViewTreeObserver().removeOnPreDrawListener(this); if (mResultReceiver != null) { Bundle state = captureSharedElementState(); - setSharedElementMatrices(); moveSharedElementsToOverlay(); mResultReceiver.send(MSG_SHARED_ELEMENT_DESTINATION, state); } @@ -322,6 +319,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { if (mListener != null) { mListener.onRejectSharedElements(rejectedSnapshots); } + removeNullViews(rejectedSnapshots); startRejectedAnimations(rejectedSnapshots); // Now start shared element transition @@ -370,6 +368,16 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { } } + private static void removeNullViews(ArrayList<View> views) { + if (views != null) { + for (int i = views.size() - 1; i >= 0; i--) { + if (views.get(i) == null) { + views.remove(i); + } + } + } + } + private void onTakeSharedElements() { if (!mIsReadyForTransition || mSharedElementsBundle == null) { return; @@ -634,30 +642,4 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { }); } - private void setSharedElementMatrices() { - int numSharedElements = mSharedElements.size(); - if (numSharedElements > 0) { - mSharedElementParentMatrices = new ArrayList<Matrix>(numSharedElements); - } - for (int i = 0; i < numSharedElements; i++) { - View view = mSharedElements.get(i); - - // Find the location in the view's parent - ViewGroup parent = (ViewGroup) view.getParent(); - Matrix matrix = new Matrix(); - parent.transformMatrixToLocal(matrix); - - mSharedElementParentMatrices.add(matrix); - } - } - - @Override - protected void getSharedElementParentMatrix(View view, Matrix matrix) { - int index = mSharedElementParentMatrices == null ? -1 : mSharedElements.indexOf(view); - if (index < 0) { - super.getSharedElementParentMatrix(view, matrix); - } else { - matrix.set(mSharedElementParentMatrices.get(index)); - } - } } diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java index cc9aed8ccdbc..5038df93192d 100644 --- a/core/java/android/app/KeyguardManager.java +++ b/core/java/android/app/KeyguardManager.java @@ -16,10 +16,14 @@ package android.app; +import android.app.trust.ITrustManager; +import android.content.Context; import android.content.Intent; import android.os.Binder; import android.os.RemoteException; import android.os.IBinder; +import android.os.ServiceManager; +import android.os.UserHandle; import android.view.IWindowManager; import android.view.IOnKeyguardExitResult; import android.view.WindowManagerGlobal; @@ -33,6 +37,7 @@ import android.view.WindowManagerGlobal; */ public class KeyguardManager { private IWindowManager mWM; + private ITrustManager mTrustManager; /** * Intent used to prompt user for device credentials. @@ -151,6 +156,8 @@ public class KeyguardManager { KeyguardManager() { mWM = WindowManagerGlobal.getWindowManagerService(); + mTrustManager = ITrustManager.Stub.asInterface( + ServiceManager.getService(Context.TRUST_SERVICE)); } /** @@ -218,6 +225,34 @@ public class KeyguardManager { } /** + * Return whether unlocking the device is currently not requiring a password + * because of a trust agent. + * + * @return true if the keyguard can currently be unlocked without entering credentials + * because the device is in a trusted environment. + */ + public boolean isKeyguardInTrustedState() { + return isKeyguardInTrustedState(UserHandle.getCallingUserId()); + } + + /** + * Return whether unlocking the device is currently not requiring a password + * because of a trust agent. + * + * @param userId the user for which the trusted state should be reported. + * @return true if the keyguard can currently be unlocked without entering credentials + * because the device is in a trusted environment. + * @hide + */ + public boolean isKeyguardInTrustedState(int userId) { + try { + return mTrustManager.isTrusted(userId); + } catch (RemoteException e) { + return false; + } + } + + /** * @deprecated Use {@link android.view.WindowManager.LayoutParams#FLAG_DISMISS_KEYGUARD} * and/or {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} * instead; this allows you to seamlessly hide the keyguard as your application diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index fb10e17adb00..9849c517b53b 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -23,6 +23,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.ColorStateList; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.PorterDuff; @@ -2773,6 +2774,14 @@ public class Notification implements Parcelable contentView.setViewVisibility(R.id.progress, View.VISIBLE); contentView.setProgressBar( R.id.progress, mProgressMax, mProgress, mProgressIndeterminate); + contentView.setProgressBackgroundTintList( + R.id.progress, ColorStateList.valueOf(mContext.getResources().getColor( + R.color.notification_progress_background_color))); + if (mColor != COLOR_DEFAULT) { + ColorStateList colorStateList = ColorStateList.valueOf(mColor); + contentView.setProgressTintList(R.id.progress, colorStateList); + contentView.setProgressIndeterminateTintList(R.id.progress, colorStateList); + } showLine2 = true; } else { contentView.setViewVisibility(R.id.progress, View.GONE); diff --git a/core/java/android/app/SharedElementCallback.java b/core/java/android/app/SharedElementCallback.java index 060bbe61e407..6ac24013672c 100644 --- a/core/java/android/app/SharedElementCallback.java +++ b/core/java/android/app/SharedElementCallback.java @@ -18,13 +18,16 @@ package android.app; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; -import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Bundle; import android.os.Parcelable; import android.transition.TransitionUtils; import android.view.View; +import android.widget.ImageView; +import android.widget.ImageView.ScaleType; import java.util.List; import java.util.Map; @@ -40,6 +43,9 @@ import java.util.Map; */ public abstract class SharedElementCallback { private Matrix mTempMatrix; + private static final String BUNDLE_SNAPSHOT_BITMAP = "sharedElement:snapshot:bitmap"; + private static final String BUNDLE_SNAPSHOT_IMAGE_SCALETYPE = "sharedElement:snapshot:imageScaleType"; + private static final String BUNDLE_SNAPSHOT_IMAGE_MATRIX = "sharedElement:snapshot:imageMatrix"; static final SharedElementCallback NULL_CALLBACK = new SharedElementCallback() { }; @@ -142,6 +148,27 @@ public abstract class SharedElementCallback { */ public Parcelable onCaptureSharedElementSnapshot(View sharedElement, Matrix viewToGlobalMatrix, RectF screenBounds) { + if (sharedElement instanceof ImageView) { + ImageView imageView = ((ImageView) sharedElement); + Drawable d = imageView.getDrawable(); + Drawable bg = imageView.getBackground(); + if (d != null && (bg == null || bg.getAlpha() == 0)) { + Bitmap bitmap = TransitionUtils.createDrawableBitmap(d); + if (bitmap != null) { + Bundle bundle = new Bundle(); + bundle.putParcelable(BUNDLE_SNAPSHOT_BITMAP, bitmap); + bundle.putString(BUNDLE_SNAPSHOT_IMAGE_SCALETYPE, + imageView.getScaleType().toString()); + if (imageView.getScaleType() == ScaleType.MATRIX) { + Matrix matrix = imageView.getImageMatrix(); + float[] values = new float[9]; + matrix.getValues(values); + bundle.putFloatArray(BUNDLE_SNAPSHOT_IMAGE_MATRIX, values); + } + return bundle; + } + } + } if (mTempMatrix == null) { mTempMatrix = new Matrix(viewToGlobalMatrix); } else { @@ -169,7 +196,24 @@ public abstract class SharedElementCallback { */ public View onCreateSnapshotView(Context context, Parcelable snapshot) { View view = null; - if (snapshot instanceof Bitmap) { + if (snapshot instanceof Bundle) { + Bundle bundle = (Bundle) snapshot; + Bitmap bitmap = (Bitmap) bundle.getParcelable(BUNDLE_SNAPSHOT_BITMAP); + if (bitmap == null) { + return null; + } + ImageView imageView = new ImageView(context); + view = imageView; + imageView.setImageBitmap(bitmap); + imageView.setScaleType( + ScaleType.valueOf(bundle.getString(BUNDLE_SNAPSHOT_IMAGE_SCALETYPE))); + if (imageView.getScaleType() == ScaleType.MATRIX) { + float[] values = bundle.getFloatArray(BUNDLE_SNAPSHOT_IMAGE_MATRIX); + Matrix matrix = new Matrix(); + matrix.setValues(values); + imageView.setImageMatrix(matrix); + } + } else if (snapshot instanceof Bitmap) { Bitmap bitmap = (Bitmap) snapshot; view = new View(context); Resources resources = context.getResources(); diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java index 4aec9e00e56f..b0dd70f34fd2 100644 --- a/core/java/android/app/UiAutomation.java +++ b/core/java/android/app/UiAutomation.java @@ -25,6 +25,7 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Point; import android.hardware.display.DisplayManagerGlobal; +import android.os.IBinder; import android.os.Looper; import android.os.ParcelFileDescriptor; import android.os.RemoteException; @@ -919,7 +920,7 @@ public final class UiAutomation { public IAccessibilityServiceClientImpl(Looper looper) { super(null, looper, new Callbacks() { @Override - public void onSetConnectionId(int connectionId) { + public void init(int connectionId, IBinder windowToken) { synchronized (mLock) { mConnectionId = connectionId; mLock.notifyAll(); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index a30ae573066d..74502fce9a52 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -3133,9 +3133,10 @@ public class DevicePolicyManager { } /** - * Called by a profile owner to disable account management for a specific type of account. + * Called by a device owner or profile owner to disable account management for a specific type + * of account. * - * <p>The calling device admin must be a profile owner. If it is not, a + * <p>The calling device admin must be a device owner or profile owner. If it is not, a * security exception will be thrown. * * <p>When account management is disabled for an account type, adding or removing an account diff --git a/core/java/android/app/trust/ITrustManager.aidl b/core/java/android/app/trust/ITrustManager.aidl index 6fbf87d2d335..0193711fd588 100644 --- a/core/java/android/app/trust/ITrustManager.aidl +++ b/core/java/android/app/trust/ITrustManager.aidl @@ -29,4 +29,5 @@ interface ITrustManager { void reportRequireCredentialEntry(int userId); void registerTrustListener(in ITrustListener trustListener); void unregisterTrustListener(in ITrustListener trustListener); + boolean isTrusted(int userId); } diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index f2e03cf89285..c262baed4f23 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -1445,7 +1445,7 @@ public final class BluetoothAdapter { if (VDBG) Log.d(TAG, "onBluetoothServiceDown: " + mService); synchronized (mManagerCallback) { mService = null; - mLeScanClients.clear(); + if (mLeScanClients != null) mLeScanClients.clear(); if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup(); if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup(); for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){ diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index af6f1816ae8c..7676e4b8d6fc 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -876,12 +876,44 @@ public class Intent implements Parcelable, Cloneable { * related methods. */ public static Intent createChooser(Intent target, CharSequence title) { + return createChooser(target, title, null); + } + + /** + * Convenience function for creating a {@link #ACTION_CHOOSER} Intent. + * + * <p>Builds a new {@link #ACTION_CHOOSER} Intent that wraps the given + * target intent, also optionally supplying a title. If the target + * intent has specified {@link #FLAG_GRANT_READ_URI_PERMISSION} or + * {@link #FLAG_GRANT_WRITE_URI_PERMISSION}, then these flags will also be + * set in the returned chooser intent, with its ClipData set appropriately: + * either a direct reflection of {@link #getClipData()} if that is non-null, + * or a new ClipData built from {@link #getData()}.</p> + * + * <p>The caller may optionally supply an {@link IntentSender} to receive a callback + * when the user makes a choice. This can be useful if the calling application wants + * to remember the last chosen target and surface it as a more prominent or one-touch + * affordance elsewhere in the UI for next time.</p> + * + * @param target The Intent that the user will be selecting an activity + * to perform. + * @param title Optional title that will be displayed in the chooser. + * @param sender Optional IntentSender to be called when a choice is made. + * @return Return a new Intent object that you can hand to + * {@link Context#startActivity(Intent) Context.startActivity()} and + * related methods. + */ + public static Intent createChooser(Intent target, CharSequence title, IntentSender sender) { Intent intent = new Intent(ACTION_CHOOSER); intent.putExtra(EXTRA_INTENT, target); if (title != null) { intent.putExtra(EXTRA_TITLE, title); } + if (sender != null) { + intent.putExtra(EXTRA_CHOSEN_COMPONENT_INTENT_SENDER, sender); + } + // Migrate any clip data and flags from target. int permFlags = target.getFlags() & (FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION | FLAG_GRANT_PERSISTABLE_URI_PERMISSION @@ -3140,6 +3172,26 @@ public class Intent implements Parcelable, Cloneable { "android.intent.extra.REPLACEMENT_EXTRAS"; /** + * An {@link IntentSender} that will be notified if a user successfully chooses a target + * component to handle an action in an {@link #ACTION_CHOOSER} activity. The IntentSender + * will have the extra {@link #EXTRA_CHOSEN_COMPONENT} appended to it containing the + * {@link ComponentName} of the chosen component. + * + * <p>In some situations this callback may never come, for example if the user abandons + * the chooser, switches to another task or any number of other reasons. Apps should not + * be written assuming that this callback will always occur.</p> + */ + public static final String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER = + "android.intent.extra.CHOSEN_COMPONENT_INTENT_SENDER"; + + /** + * The {@link ComponentName} chosen by the user to complete an action. + * + * @see #EXTRA_CHOSEN_COMPONENT_INTENT_SENDER + */ + public static final String EXTRA_CHOSEN_COMPONENT = "android.intent.extra.CHOSEN_COMPONENT"; + + /** * A {@link android.view.KeyEvent} object containing the event that * triggered the creation of the Intent it is in. */ diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index c37534aa0334..0dc86ad0cabf 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -436,6 +436,7 @@ interface IPackageManager { boolean isFirstBoot(); boolean isOnlyCoreApps(); + boolean isUpgrade(); void setPermissionEnforced(String permission, boolean enforced); boolean isPermissionEnforced(String permission); diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index 5ee0b673e3e5..c16434073a78 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -499,20 +499,4 @@ public class LauncherApps { obtainMessage(MSG_UNAVAILABLE, info).sendToTarget(); } } - - /** - * TODO Remove after 2014-09-22 - * @hide - */ - public void addCallback(Callback callback) { - registerCallback(callback); - } - - /** - * TODO Remove after 2014-09-22 - * @hide - */ - public void removeCallback(Callback callback) { - unregisterCallback(callback); - } } diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java index cacdf8e36250..22a899cda05b 100644 --- a/core/java/android/content/pm/PackageItemInfo.java +++ b/core/java/android/content/pm/PackageItemInfo.java @@ -138,7 +138,7 @@ public class PackageItemInfo { } return packageName; } - + /** * Retrieve the current graphical icon associated with this item. This * will call back on the given PackageManager to load the icon from @@ -156,6 +156,23 @@ public class PackageItemInfo { } /** + * Retrieve the current graphical icon associated with this item without + * the addition of a work badge if applicable. + * This will call back on the given PackageManager to load the icon from + * the application. + * + * @param pm A PackageManager from which the icon can be loaded; usually + * the PackageManager from which you originally retrieved this item. + * + * @return Returns a Drawable containing the item's icon. If the + * item does not have an icon, the item's default icon is returned + * such as the default activity icon. + */ + public Drawable loadUnbadgedIcon(PackageManager pm) { + return pm.loadUnbadgedItemIcon(this, getApplicationInfo()); + } + + /** * Retrieve the current graphical banner associated with this item. This * will call back on the given PackageManager to load the banner from * the application. diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index e5191630fa60..e9f7c50431b5 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -3867,6 +3867,13 @@ public abstract class PackageManager { public abstract VerifierDeviceIdentity getVerifierDeviceIdentity(); /** + * Returns true if the device is upgrading, such as first boot after OTA. + * + * @hide + */ + public abstract boolean isUpgrade(); + + /** * Return interface that offers the ability to install, upgrade, and remove * applications on the device. */ @@ -3911,6 +3918,11 @@ public abstract class PackageManager { */ public abstract Drawable loadItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo); + /** + * @hide + */ + public abstract Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo); + /** {@hide} */ public abstract boolean isPackageAvailable(String packageName); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index ca4ff6a49c6c..8515520c0d0a 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -74,7 +74,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; @@ -380,7 +379,7 @@ public class PackageParser { */ public static PackageInfo generatePackageInfo(PackageParser.Package p, int gids[], int flags, long firstInstallTime, long lastUpdateTime, - HashSet<String> grantedPermissions, PackageUserState state) { + ArraySet<String> grantedPermissions, PackageUserState state) { return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime, grantedPermissions, state, UserHandle.getCallingUserId()); @@ -401,7 +400,7 @@ public class PackageParser { public static PackageInfo generatePackageInfo(PackageParser.Package p, int gids[], int flags, long firstInstallTime, long lastUpdateTime, - HashSet<String> grantedPermissions, PackageUserState state, int userId) { + ArraySet<String> grantedPermissions, PackageUserState state, int userId) { if (!checkUseInstalledOrHidden(flags, state)) { return null; diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java index 4dcad6f16195..a9c7be376656 100644 --- a/core/java/android/content/pm/PackageUserState.java +++ b/core/java/android/content/pm/PackageUserState.java @@ -18,7 +18,7 @@ package android.content.pm; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; -import java.util.HashSet; +import android.util.ArraySet; /** * Per-user state information about a package. @@ -34,8 +34,8 @@ public class PackageUserState { public String lastDisableAppCaller; - public HashSet<String> disabledComponents; - public HashSet<String> enabledComponents; + public ArraySet<String> disabledComponents; + public ArraySet<String> enabledComponents; public PackageUserState() { installed = true; @@ -51,9 +51,9 @@ public class PackageUserState { hidden = o.hidden; lastDisableAppCaller = o.lastDisableAppCaller; disabledComponents = o.disabledComponents != null - ? new HashSet<String>(o.disabledComponents) : null; + ? new ArraySet<String>(o.disabledComponents) : null; enabledComponents = o.enabledComponents != null - ? new HashSet<String>(o.enabledComponents) : null; + ? new ArraySet<String>(o.enabledComponents) : null; blockUninstall = o.blockUninstall; } -}
\ No newline at end of file +} diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index 27bbb242f575..14af58481f05 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -1365,13 +1365,13 @@ public final class Configuration implements Parcelable, Comparable<Configuration ArrayList<String> parts = new ArrayList<String>(); if (config.mcc != 0) { - parts.add(config.mcc + "mcc"); + parts.add("mcc" + config.mcc); if (config.mnc != 0) { - parts.add(config.mnc + "mnc"); + parts.add("mnc" + config.mnc); } } - if (!config.locale.getLanguage().isEmpty()) { + if (config.locale != null && !config.locale.getLanguage().isEmpty()) { parts.add(localeToResourceQualifier(config.locale)); } diff --git a/core/java/android/content/res/ConfigurationBoundResourceCache.java b/core/java/android/content/res/ConfigurationBoundResourceCache.java new file mode 100644 index 000000000000..cde7e84b70ce --- /dev/null +++ b/core/java/android/content/res/ConfigurationBoundResourceCache.java @@ -0,0 +1,138 @@ +/* +* Copyright (C) 2014 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package android.content.res; + +import android.util.ArrayMap; +import android.util.LongSparseArray; +import java.lang.ref.WeakReference; + +/** + * A Cache class which can be used to cache resource objects that are easy to clone but more + * expensive to inflate. + * @hide + */ +public class ConfigurationBoundResourceCache<T> { + + private final ArrayMap<String, LongSparseArray<WeakReference<ConstantState<T>>>> mCache = + new ArrayMap<String, LongSparseArray<WeakReference<ConstantState<T>>>>(); + + final Resources mResources; + + /** + * Creates a Resource cache for the given Resources instance. + * + * @param resources The Resource which can be used when creating new instances. + */ + public ConfigurationBoundResourceCache(Resources resources) { + mResources = resources; + } + + /** + * Adds a new item to the cache. + * + * @param key A custom key that uniquely identifies the resource. + * @param theme The Theme instance where this resource was loaded. + * @param constantState The constant state that can create new instances of the resource. + * + */ + public void put(long key, Resources.Theme theme, ConstantState<T> constantState) { + if (constantState == null) { + return; + } + final String themeKey = theme == null ? "" : theme.getKey(); + LongSparseArray<WeakReference<ConstantState<T>>> themedCache; + synchronized (this) { + themedCache = mCache.get(themeKey); + if (themedCache == null) { + themedCache = new LongSparseArray<WeakReference<ConstantState<T>>>(1); + mCache.put(themeKey, themedCache); + } + themedCache.put(key, new WeakReference<ConstantState<T>>(constantState)); + } + } + + /** + * If the resource is cached, creates a new instance of it and returns. + * + * @param key The long key which can be used to uniquely identify the resource. + * @param theme The The Theme instance where we want to load this resource. + * + * @return If this resources was loaded before, returns a new instance of it. Otherwise, returns + * null. + */ + public T get(long key, Resources.Theme theme) { + final String themeKey = theme != null ? theme.getKey() : ""; + final LongSparseArray<WeakReference<ConstantState<T>>> themedCache; + final WeakReference<ConstantState<T>> wr; + synchronized (this) { + themedCache = mCache.get(themeKey); + if (themedCache == null) { + return null; + } + wr = themedCache.get(key); + } + if (wr == null) { + return null; + } + final ConstantState entry = wr.get(); + if (entry != null) { + return (T) entry.newInstance(mResources, theme); + } else { // our entry has been purged + synchronized (this) { + // there is a potential race condition here where this entry may be put in + // another thread. But we prefer it to minimize lock duration + themedCache.delete(key); + } + } + return null; + } + + /** + * Users of ConfigurationBoundResourceCache must call this method whenever a configuration + * change happens. On this callback, the cache invalidates all resources that are not valid + * anymore. + * + * @param configChanges The configuration changes + */ + public void onConfigurationChange(final int configChanges) { + synchronized (this) { + final int size = mCache.size(); + for (int i = size - 1; i >= 0; i--) { + final LongSparseArray<WeakReference<ConstantState<T>>> + themeCache = mCache.valueAt(i); + onConfigurationChangeInt(themeCache, configChanges); + if (themeCache.size() == 0) { + mCache.removeAt(i); + } + } + } + } + + private void onConfigurationChangeInt( + final LongSparseArray<WeakReference<ConstantState<T>>> themeCache, + final int configChanges) { + final int size = themeCache.size(); + for (int i = size - 1; i >= 0; i--) { + final WeakReference<ConstantState<T>> wr = themeCache.valueAt(i); + final ConstantState<T> constantState = wr.get(); + if (constantState == null || Configuration.needNewResources( + configChanges, constantState.getChangingConfigurations())) { + themeCache.removeAt(i); + } + } + } + +} diff --git a/core/java/android/content/res/ConstantState.java b/core/java/android/content/res/ConstantState.java new file mode 100644 index 000000000000..ee609df2e232 --- /dev/null +++ b/core/java/android/content/res/ConstantState.java @@ -0,0 +1,61 @@ +/* +* Copyright (C) 2014 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package android.content.res; + +/** + * A cache class that can provide new instances of a particular resource which may change + * depending on the current {@link Resources.Theme} or {@link Configuration}. + * <p> + * A constant state should be able to return a bitmask of changing configurations, which + * identifies the type of configuration changes that may invalidate this resource. These + * configuration changes can be obtained from {@link android.util.TypedValue}. Entities such as + * {@link android.animation.Animator} also provide a changing configuration method to include + * their dependencies (e.g. An AnimatorSet's changing configuration is the union of the + * changing configurations of each Animator in the set) + * @hide + */ +abstract public class ConstantState<T> { + + /** + * Return a bit mask of configuration changes that will impact + * this resource (and thus require completely reloading it). + */ + abstract public int getChangingConfigurations(); + + /** + * Create a new instance without supplying resources the caller + * is running in. + */ + public abstract T newInstance(); + + /** + * Create a new instance from its constant state. This + * must be implemented for resources that change based on the target + * density of their caller (that is depending on whether it is + * in compatibility mode). + */ + public T newInstance(Resources res) { + return newInstance(); + } + + /** + * Create a new instance from its constant state. This must be + * implemented for resources that can have a theme applied. + */ + public T newInstance(Resources res, Resources.Theme theme) { + return newInstance(res); + } +} diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 7f276c24dc71..0145e05a86e4 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -16,6 +16,9 @@ package android.content.res; +import android.animation.Animator; +import android.animation.StateListAnimator; +import android.annotation.NonNull; import android.util.Pools.SynchronizedPool; import android.view.ViewDebug; import com.android.internal.util.XmlUtils; @@ -115,6 +118,10 @@ public class Resources { new ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>>(); private final LongSparseArray<WeakReference<ColorStateList>> mColorStateListCache = new LongSparseArray<WeakReference<ColorStateList>>(); + private final ConfigurationBoundResourceCache<Animator> mAnimatorCache = + new ConfigurationBoundResourceCache<Animator>(this); + private final ConfigurationBoundResourceCache<StateListAnimator> mStateListAnimatorCache = + new ConfigurationBoundResourceCache<StateListAnimator>(this); private TypedValue mTmpValue = new TypedValue(); private boolean mPreloading; @@ -183,6 +190,24 @@ public class Resources { } /** + * Used by AnimatorInflater. + * + * @hide + */ + public ConfigurationBoundResourceCache<Animator> getAnimatorCache() { + return mAnimatorCache; + } + + /** + * Used by AnimatorInflater. + * + * @hide + */ + public ConfigurationBoundResourceCache<StateListAnimator> getStateListAnimatorCache() { + return mStateListAnimatorCache; + } + + /** * This exception is thrown by the resource APIs when a requested resource * can not be found. */ @@ -1524,20 +1549,21 @@ public class Resources { * contents of the typed array are ultimately filled in by * {@link Resources#getValue}. * - * @param values The base set of attribute values, must be equal - * in length to {@code attrs} or {@code null}. All values - * must be of type {@link TypedValue#TYPE_ATTRIBUTE}. + * @param values The base set of attribute values, must be equal in + * length to {@code attrs}. All values must be of type + * {@link TypedValue#TYPE_ATTRIBUTE}. * @param attrs The desired attributes to be retrieved. * @return Returns a TypedArray holding an array of the attribute * values. Be sure to call {@link TypedArray#recycle()} * when done with it. * @hide */ - public TypedArray resolveAttributes(int[] values, int[] attrs) { + @NonNull + public TypedArray resolveAttributes(@NonNull int[] values, @NonNull int[] attrs) { final int len = attrs.length; - if (values != null && len != values.length) { + if (values == null || len != values.length) { throw new IllegalArgumentException( - "Base attribute values must be null or the same length as attrs"); + "Base attribute values must the same length as attrs"); } final TypedArray array = TypedArray.obtain(Resources.this, len); @@ -1761,23 +1787,7 @@ public class Resources { // the framework. mCompatibilityInfo.applyToDisplayMetrics(mMetrics); - int configChanges = 0xfffffff; - if (config != null) { - mTmpConfig.setTo(config); - int density = config.densityDpi; - if (density == Configuration.DENSITY_DPI_UNDEFINED) { - density = mMetrics.noncompatDensityDpi; - } - - mCompatibilityInfo.applyToConfiguration(density, mTmpConfig); - - if (mTmpConfig.locale == null) { - mTmpConfig.locale = Locale.getDefault(); - mTmpConfig.setLayoutDirection(mTmpConfig.locale); - } - configChanges = mConfiguration.updateFrom(mTmpConfig); - configChanges = ActivityInfo.activityInfoConfigToNative(configChanges); - } + int configChanges = calcConfigChanges(config); if (mConfiguration.locale == null) { mConfiguration.locale = Locale.getDefault(); mConfiguration.setLayoutDirection(mConfiguration.locale); @@ -1825,6 +1835,8 @@ public class Resources { clearDrawableCachesLocked(mDrawableCache, configChanges); clearDrawableCachesLocked(mColorDrawableCache, configChanges); + mAnimatorCache.onConfigurationChange(configChanges); + mStateListAnimatorCache.onConfigurationChange(configChanges); mColorStateListCache.clear(); @@ -1837,6 +1849,30 @@ public class Resources { } } + /** + * Called by ConfigurationBoundResourceCacheTest via reflection. + */ + private int calcConfigChanges(Configuration config) { + int configChanges = 0xfffffff; + if (config != null) { + mTmpConfig.setTo(config); + int density = config.densityDpi; + if (density == Configuration.DENSITY_DPI_UNDEFINED) { + density = mMetrics.noncompatDensityDpi; + } + + mCompatibilityInfo.applyToConfiguration(density, mTmpConfig); + + if (mTmpConfig.locale == null) { + mTmpConfig.locale = Locale.getDefault(); + mTmpConfig.setLayoutDirection(mTmpConfig.locale); + } + configChanges = mConfiguration.updateFrom(mTmpConfig); + configChanges = ActivityInfo.activityInfoConfigToNative(configChanges); + } + return configChanges; + } + private void clearDrawableCachesLocked( ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> caches, int configChanges) { @@ -2323,7 +2359,14 @@ public class Resources { final Drawable dr; if (cs != null) { - dr = cs.newDrawable(this, theme); + final Drawable clonedDr = cs.newDrawable(this); + if (theme != null) { + dr = clonedDr.mutate(); + dr.applyTheme(theme); + dr.clearMutated(); + } else { + dr = clonedDr; + } } else if (isColorDrawable) { dr = new ColorDrawable(value.data); } else { diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java index 73b93c64d524..02602fb67f2a 100644 --- a/core/java/android/content/res/TypedArray.java +++ b/core/java/android/content/res/TypedArray.java @@ -807,6 +807,9 @@ public class TypedArray { /** * Determines whether there is an attribute at <var>index</var>. + * <p> + * <strong>Note:</strong> If the attribute was set to {@code @empty} or + * {@code @undefined}, this method returns {@code false}. * * @param index Index of attribute to retrieve. * @@ -824,6 +827,27 @@ public class TypedArray { } /** + * Determines whether there is an attribute at <var>index</var>, returning + * {@code true} if the attribute was explicitly set to {@code @empty} and + * {@code false} only if the attribute was undefined. + * + * @param index Index of attribute to retrieve. + * + * @return True if the attribute has a value or is empty, false otherwise. + */ + public boolean hasValueOrEmpty(int index) { + if (mRecycled) { + throw new RuntimeException("Cannot make calls to a recycled instance!"); + } + + index *= AssetManager.STYLE_NUM_ENTRIES; + final int[] data = mData; + final int type = data[index+AssetManager.STYLE_TYPE]; + return type != TypedValue.TYPE_NULL + || data[index+AssetManager.STYLE_DATA] == TypedValue.DATA_NULL_EMPTY; + } + + /** * Retrieve the raw TypedValue for the attribute at <var>index</var> * and return a temporary object holding its data. This object is only * valid until the next call on to {@link TypedArray}. diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java index f514e428e525..cf6a779f1fed 100644 --- a/core/java/android/hardware/Sensor.java +++ b/core/java/android/hardware/Sensor.java @@ -329,7 +329,11 @@ public final class Sensor { * A sensor of this type triggers an event each time a step is taken by the user. The only * allowed value to return is 1.0 and an event is generated for each step. Like with any other * event, the timestamp indicates when the event (here the step) occurred, this corresponds to - * when the foot hit the ground, generating a high variation in acceleration. + * when the foot hit the ground, generating a high variation in acceleration. This sensor is + * only for detecting every individual step as soon as it is taken, for example to perform dead + * reckoning. If you only need aggregate number of steps taken over a period of time, register + * for {@link #TYPE_STEP_COUNTER} instead. It is defined as a + * {@link Sensor#REPORTING_MODE_SPECIAL_TRIGGER} sensor. * <p> * See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details. */ @@ -349,7 +353,12 @@ public final class Sensor { * while activated. The value is returned as a float (with the fractional part set to zero) and * is reset to zero only on a system reboot. The timestamp of the event is set to the time when * the last step for that event was taken. This sensor is implemented in hardware and is - * expected to be low power. + * expected to be low power. If you want to continuously track the number of steps over a long + * period of time, do NOT unregister for this sensor, so that it keeps counting steps in the + * background even when the AP is in suspend mode and report the aggregate count when the AP + * is awake. Application needs to stay registered for this sensor because step counter does not + * count steps if it is not activated. This sensor is ideal for fitness tracking applications. + * It is defined as an {@link Sensor#REPORTING_MODE_ON_CHANGE} sensor. * <p> * See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details. */ @@ -750,31 +759,41 @@ public final class Sensor { } /** - * Returns whether this sensor is a wake-up sensor. + * Returns true if the sensor is a wake-up sensor. * <p> - * Wake up sensors wake the application processor up when they have events to deliver. When a - * wake up sensor is registered to without batching enabled, each event will wake the - * application processor up. - * <p> - * When a wake up sensor is registered to with batching enabled, it - * wakes the application processor up when maxReportingLatency has elapsed or when the hardware - * FIFO storing the events from wake up sensors is getting full. - * <p> - * Non-wake up sensors never wake the application processor up. Their events are only reported - * when the application processor is awake, for example because the application holds a wake - * lock, or another source woke the application processor up. + * <b>Application Processor Power modes</b> <p> + * Application Processor(AP), is the processor on which applications run. When no wake lock is held + * and the user is not interacting with the device, this processor can enter a “Suspend” mode, + * reducing the power consumption by 10 times or more. + * </p> * <p> - * When a non-wake up sensor is registered to without batching enabled, the measurements made - * while the application processor is asleep might be lost and never returned. + * <b>Non-wake-up sensors</b> <p> + * Non-wake-up sensors are sensors that do not wake the AP out of suspend to report data. While + * the AP is in suspend mode, the sensors continue to function and generate events, which are + * put in a hardware FIFO. The events in the FIFO are delivered to the application when the AP + * wakes up. If the FIFO was too small to store all events generated while the AP was in + * suspend mode, the older events are lost: the oldest data is dropped to accommodate the newer + * data. In the extreme case where the FIFO is non-existent {@code maxFifoEventCount() == 0}, + * all events generated while the AP was in suspend mode are lost. Applications using + * non-wake-up sensors should usually: + * <ul> + * <li>Either unregister from the sensors when they do not need them, usually in the activity’s + * {@code onPause} method. This is the most common case. + * <li>Or realize that the sensors are consuming some power while the AP is in suspend mode and + * that even then, some events might be lost. + * </ul> + * </p> * <p> - * When a non-wake up sensor is registered to with batching enabled, the measurements made while - * the application processor is asleep are stored in the hardware FIFO for non-wake up sensors. - * When this FIFO gets full, new events start overwriting older events. When the application - * then wakes up, the latest events are returned, and some old events might be lost. The number - * of events actually returned depends on the hardware FIFO size, as well as on what other - * sensors are activated. If losing sensor events is not acceptable during batching, you must - * use the wake-up version of the sensor. - * @return true if this is a wake up sensor, false otherwise. + * <b>Wake-up sensors</b> <p> + * In opposition to non-wake-up sensors, wake-up sensors ensure that their data is delivered + * independently of the state of the AP. While the AP is awake, the wake-up sensors behave + * like non-wake-up-sensors. When the AP is asleep, wake-up sensors wake up the AP to deliver + * events. That is, the AP will wake up and the sensor will deliver the events before the + * maximum reporting latency is elapsed or the hardware FIFO gets full. See {@link + * SensorManager#registerListener(SensorEventListener, Sensor, int, int)} for more details. + * </p> + * + * @return <code>true</code> if this is a wake-up sensor, <code>false</code> otherwise. */ public boolean isWakeUpSensor() { return (mFlags & SENSOR_FLAG_WAKE_UP_SENSOR) != 0; diff --git a/core/java/android/hardware/SensorEventListener2.java b/core/java/android/hardware/SensorEventListener2.java index 70eff08d7ca2..fd3e62b2b3cb 100644 --- a/core/java/android/hardware/SensorEventListener2.java +++ b/core/java/android/hardware/SensorEventListener2.java @@ -21,15 +21,16 @@ package android.hardware; */ public interface SensorEventListener2 extends SensorEventListener { /** - * Called after flush() is completed. All the events in the batch at the point when - * the flush was called have been delivered to the applications registered for those - * sensor events. Flush Complete Events are sent ONLY to the application that has - * explicitly called flush(). If the hardware FIFO is flushed due to some other - * application calling flush(), flush complete event is not delivered to this application. + * Called after flush() is completed. All the events in the batch at the point when the flush + * was called have been delivered to the applications registered for those sensor events. In + * {@link android.os.Build.VERSION_CODES#KITKAT}, applications may receive flush complete events + * even if some other application has called flush() on the same sensor. Starting with + * {@link android.os.Build.VERSION_CODES#LOLLIPOP}, flush Complete events are sent ONLY to the + * application that has explicitly called flush(). If the hardware FIFO is flushed due to some + * other application calling flush(), flush complete event is not delivered to this application. * <p> * * @param sensor The {@link android.hardware.Sensor Sensor} on which flush was called. - * * @see android.hardware.SensorManager#flush(SensorEventListener) */ public void onFlushCompleted(Sensor sensor); diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java index cccd62495b1b..e4e5a8cd8e73 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -626,73 +626,90 @@ public abstract class SensorManager { protected abstract void unregisterListenerImpl(SensorEventListener listener, Sensor sensor); /** - * Registers a {@link android.hardware.SensorEventListener - * SensorEventListener} for the given sensor. - * - * <p class="note"></p> - * Note: Don't use this method with a one shot trigger sensor such as - * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. - * Use {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. + * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given + * sensor at the given sampling frequency. + * <p> + * The events will be delivered to the provided {@code SensorEventListener} as soon as they are + * available. To reduce the power consumption, applications can use + * {@link #registerListener(SensorEventListener, Sensor, int, int)} instead and specify a + * positive non-zero maximum reporting latency. + * </p> + * <p> + * In the case of non-wake-up sensors, the events are only delivered while the Application + * Processor (AP) is not in suspend mode. See {@link Sensor#isWakeUpSensor()} for more details. + * To ensure delivery of events from non-wake-up sensors even when the screen is OFF, the + * application registering to the sensor must hold a partial wake-lock to keep the AP awake, + * otherwise some events might be lost while the AP is asleep. Note that although events might + * be lost while the AP is asleep, the sensor will still consume power if it is not explicitly + * deactivated by the application. Applications must unregister their {@code + * SensorEventListener}s in their activity's {@code onPause()} method to avoid consuming power + * while the device is inactive. See {@link #registerListener(SensorEventListener, Sensor, int, + * int)} for more details on hardware FIFO (queueing) capabilities and when some sensor events + * might be lost. + * </p> + * <p> + * In the case of wake-up sensors, each event generated by the sensor will cause the AP to + * wake-up, ensuring that each event can be delivered. Because of this, registering to a wake-up + * sensor has very significant power implications. Call {@link Sensor#isWakeUpSensor()} to check + * whether a sensor is a wake-up sensor. See + * {@link #registerListener(SensorEventListener, Sensor, int, int)} for information on how to + * reduce the power impact of registering to wake-up sensors. + * </p> + * <p class="note"> + * Note: Don't use this method with one-shot trigger sensors such as + * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use + * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. Use + * {@link Sensor#getReportingMode()} to obtain the reporting mode of a given sensor. * </p> * - * @param listener - * A {@link android.hardware.SensorEventListener SensorEventListener} - * object. - * - * @param sensor - * The {@link android.hardware.Sensor Sensor} to register to. - * - * @param rateUs - * The rate {@link android.hardware.SensorEvent sensor events} are - * delivered at. This is only a hint to the system. Events may be - * received faster or slower than the specified rate. Usually events - * are received faster. The value must be one of - * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, - * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST} - * or, the desired delay between events in microseconds. - * Specifying the delay in microseconds only works from Android - * 2.3 (API level 9) onwards. For earlier releases, you must use - * one of the {@code SENSOR_DELAY_*} constants. - * - * @return <code>true</code> if the sensor is supported and successfully - * enabled. - * + * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object. + * @param sensor The {@link android.hardware.Sensor Sensor} to register to. + * @param samplingPeriodUs The rate {@link android.hardware.SensorEvent sensor events} are + * delivered at. This is only a hint to the system. Events may be received faster or + * slower than the specified rate. Usually events are received faster. The value must + * be one of {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, + * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST} or, the desired delay + * between events in microseconds. Specifying the delay in microseconds only works + * from Android 2.3 (API level 9) onwards. For earlier releases, you must use one of + * the {@code SENSOR_DELAY_*} constants. + * @return <code>true</code> if the sensor is supported and successfully enabled. * @see #registerListener(SensorEventListener, Sensor, int, Handler) * @see #unregisterListener(SensorEventListener) * @see #unregisterListener(SensorEventListener, Sensor) - * */ - public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs) { - return registerListener(listener, sensor, rateUs, null); + public boolean registerListener(SensorEventListener listener, Sensor sensor, + int samplingPeriodUs) { + return registerListener(listener, sensor, samplingPeriodUs, null); } /** - * Enables batch mode for a sensor with the given rate and maxBatchReportLatency. If the - * underlying hardware does not support batch mode, this defaults to - * {@link #registerListener(SensorEventListener, Sensor, int)} and other parameters are - * ignored. In non-batch mode, all sensor events must be reported as soon as they are detected. - * While in batch mode, sensor events do not need to be reported as soon as they are detected. - * They can be temporarily stored in batches and reported in batches, as long as no event is - * delayed by more than "maxBatchReportLatency" microseconds. That is, all events since the - * previous batch are recorded and returned all at once. This allows to reduce the amount of - * interrupts sent to the SoC, and allows the SoC to switch to a lower power state (Idle) while - * the sensor is capturing and batching data. - * <p> - * Registering to a sensor in batch mode will not prevent the SoC from going to suspend mode. In - * this case, the sensor will continue to gather events and store it in a hardware FIFO. If the - * FIFO gets full before the AP wakes up again, some events will be lost, as the older events - * get overwritten by new events in the hardware FIFO. This can be avoided by holding a wake - * lock. If the application holds a wake lock, the SoC will not go to suspend mode, so no events - * will be lost, as the events will be reported before the FIFO gets full. - * </p> + * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given + * sensor at the given sampling frequency and the given maximum reporting latency. * <p> - * Batching is always best effort. If a different application requests updates in continuous - * mode, this application will also get events in continuous mode. Batch mode updates can be - * unregistered by calling {@link #unregisterListener(SensorEventListener)}. + * This function is similar to {@link #registerListener(SensorEventListener, Sensor, int)} but + * it allows events to stay temporarily in the hardware FIFO (queue) before being delivered. The + * events can be stored in the hardware FIFO up to {@code maxReportLatencyUs} microseconds. Once + * one of the events in the FIFO needs to be reported, all of the events in the FIFO are + * reported sequentially. This means that some events will be reported before the maximum + * reporting latency has elapsed. + * </p><p> + * When {@code maxReportLatencyUs} is 0, the call is equivalent to a call to + * {@link #registerListener(SensorEventListener, Sensor, int)}, as it requires the events to be + * delivered as soon as possible. + * </p><p> + * When {@code sensor.maxFifoEventCount()} is 0, the sensor does not use a FIFO, so the call + * will also be equivalent to {@link #registerListener(SensorEventListener, Sensor, int)}. + * </p><p> + * Setting {@code maxReportLatencyUs} to a positive value allows to reduce the number of + * interrupts the AP (Application Processor) receives, hence reducing power consumption, as the + * AP can switch to a lower power state while the sensor is capturing the data. This is + * especially important when registering to wake-up sensors, for which each interrupt causes the + * AP to wake up if it was in suspend mode. See {@link Sensor#isWakeUpSensor()} for more + * information on wake-up sensors. * </p> * <p class="note"> * </p> - * Note: Don't use this method with a one shot trigger sensor such as + * Note: Don't use this method with one-shot trigger sensors such as * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. </p> * @@ -701,118 +718,104 @@ public abstract class SensorManager { * flush complete notifications, it should register with * {@link android.hardware.SensorEventListener SensorEventListener2} instead. * @param sensor The {@link android.hardware.Sensor Sensor} to register to. - * @param rateUs The desired delay between two consecutive events in microseconds. This is only - * a hint to the system. Events may be received faster or slower than the specified - * rate. Usually events are received faster. Can be one of + * @param samplingPeriodUs The desired delay between two consecutive events in microseconds. + * This is only a hint to the system. Events may be received faster or slower than + * the specified rate. Usually events are received faster. Can be one of * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, * {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in * microseconds. - * @param maxBatchReportLatencyUs An event in the batch can be delayed by at most - * maxBatchReportLatency microseconds. More events can be batched if this value is - * large. If this is set to zero, batch mode is disabled and events are delivered in - * continuous mode as soon as they are available which is equivalent to calling + * @param maxReportLatencyUs Maximum time in microseconds that events can be delayed before + * being reported to the application. A large value allows reducing the power + * consumption associated with the sensor. If maxReportLatencyUs is set to zero, + * events are delivered as soon as they are available, which is equivalent to calling * {@link #registerListener(SensorEventListener, Sensor, int)}. - * @return <code>true</code> if batch mode is successfully enabled for this sensor, - * <code>false</code> otherwise. + * @return <code>true</code> if the sensor is supported and successfully enabled. * @see #registerListener(SensorEventListener, Sensor, int) * @see #unregisterListener(SensorEventListener) * @see #flush(SensorEventListener) */ - public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs, - int maxBatchReportLatencyUs) { - int delay = getDelay(rateUs); - return registerListenerImpl(listener, sensor, delay, null, maxBatchReportLatencyUs, 0); + public boolean registerListener(SensorEventListener listener, Sensor sensor, + int samplingPeriodUs, int maxReportLatencyUs) { + int delay = getDelay(samplingPeriodUs); + return registerListenerImpl(listener, sensor, delay, null, maxReportLatencyUs, 0); } /** * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given * sensor. Events are delivered in continuous mode as soon as they are available. To reduce the - * battery usage, use {@link #registerListener(SensorEventListener, Sensor, int, int)} which - * enables batch mode for the sensor. - * - * <p class="note"></p> - * Note: Don't use this method with a one shot trigger sensor such as - * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. - * Use {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. + * power consumption, applications can use + * {@link #registerListener(SensorEventListener, Sensor, int, int)} instead and specify a + * positive non-zero maximum reporting latency. + * <p class="note"> * </p> + * Note: Don't use this method with a one shot trigger sensor such as + * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use + * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. </p> * - * @param listener - * A {@link android.hardware.SensorEventListener SensorEventListener} - * object. - * - * @param sensor - * The {@link android.hardware.Sensor Sensor} to register to. - * - * @param rateUs - * The rate {@link android.hardware.SensorEvent sensor events} are - * delivered at. This is only a hint to the system. Events may be - * received faster or slower than the specified rate. Usually events - * are received faster. The value must be one of - * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, - * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}. - * or, the desired delay between events in microseconds. - * Specifying the delay in microseconds only works from Android - * 2.3 (API level 9) onwards. For earlier releases, you must use - * one of the {@code SENSOR_DELAY_*} constants. - * - * @param handler - * The {@link android.os.Handler Handler} the - * {@link android.hardware.SensorEvent sensor events} will be - * delivered to. - * + * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object. + * @param sensor The {@link android.hardware.Sensor Sensor} to register to. + * @param samplingPeriodUs The rate {@link android.hardware.SensorEvent sensor events} are + * delivered at. This is only a hint to the system. Events may be received faster or + * slower than the specified rate. Usually events are received faster. The value must + * be one of {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, + * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST} or, the desired + * delay between events in microseconds. Specifying the delay in microseconds only + * works from Android 2.3 (API level 9) onwards. For earlier releases, you must use + * one of the {@code SENSOR_DELAY_*} constants. + * @param handler The {@link android.os.Handler Handler} the {@link android.hardware.SensorEvent + * sensor events} will be delivered to. * @return <code>true</code> if the sensor is supported and successfully enabled. - * * @see #registerListener(SensorEventListener, Sensor, int) * @see #unregisterListener(SensorEventListener) * @see #unregisterListener(SensorEventListener, Sensor) */ - public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs, - Handler handler) { - int delay = getDelay(rateUs); + public boolean registerListener(SensorEventListener listener, Sensor sensor, + int samplingPeriodUs, Handler handler) { + int delay = getDelay(samplingPeriodUs); return registerListenerImpl(listener, sensor, delay, handler, 0, 0); } /** - * Enables batch mode for a sensor with the given rate and maxBatchReportLatency. + * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given + * sensor at the given sampling frequency and the given maximum reporting latency. + * * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object * that will receive the sensor events. If the application is interested in receiving * flush complete notifications, it should register with * {@link android.hardware.SensorEventListener SensorEventListener2} instead. * @param sensor The {@link android.hardware.Sensor Sensor} to register to. - * @param rateUs The desired delay between two consecutive events in microseconds. This is only - * a hint to the system. Events may be received faster or slower than the specified - * rate. Usually events are received faster. Can be one of + * @param samplingPeriodUs The desired delay between two consecutive events in microseconds. + * This is only a hint to the system. Events may be received faster or slower than + * the specified rate. Usually events are received faster. Can be one of * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, * {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in * microseconds. - * @param maxBatchReportLatencyUs An event in the batch can be delayed by at most - * maxBatchReportLatency microseconds. More events can be batched if this value is - * large. If this is set to zero, batch mode is disabled and events are delivered in - * continuous mode as soon as they are available which is equivalent to calling + * @param maxReportLatencyUs Maximum time in microseconds that events can be delayed before + * being reported to the application. A large value allows reducing the power + * consumption associated with the sensor. If maxReportLatencyUs is set to zero, + * events are delivered as soon as they are available, which is equivalent to calling * {@link #registerListener(SensorEventListener, Sensor, int)}. - * @param handler The {@link android.os.Handler Handler} the - * {@link android.hardware.SensorEvent sensor events} will be delivered to. - * - * @return <code>true</code> if batch mode is successfully enabled for this sensor, - * <code>false</code> otherwise. + * @param handler The {@link android.os.Handler Handler} the {@link android.hardware.SensorEvent + * sensor events} will be delivered to. + * @return <code>true</code> if the sensor is supported and successfully enabled. * @see #registerListener(SensorEventListener, Sensor, int, int) */ - public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs, - int maxBatchReportLatencyUs, Handler handler) { - int delayUs = getDelay(rateUs); - return registerListenerImpl(listener, sensor, delayUs, handler, maxBatchReportLatencyUs, 0); + public boolean registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs, + int maxReportLatencyUs, Handler handler) { + int delayUs = getDelay(samplingPeriodUs); + return registerListenerImpl(listener, sensor, delayUs, handler, maxReportLatencyUs, 0); } /** @hide */ protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor, - int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags); + int delayUs, Handler handler, int maxReportLatencyUs, int reservedFlags); /** - * Flushes the batch FIFO of all the sensors registered for this listener. If there are events - * in the FIFO of the sensor, they are returned as if the batch timeout in the FIFO of the - * sensors had expired. Events are returned in the usual way through the SensorEventListener. - * This call doesn't affect the batch timeout for this sensor. This call is asynchronous and + * Flushes the FIFO of all the sensors registered for this listener. If there are events + * in the FIFO of the sensor, they are returned as if the maxReportLantecy of the FIFO has + * expired. Events are returned in the usual way through the SensorEventListener. + * This call doesn't affect the maxReportLantecy for this sensor. This call is asynchronous and * returns immediately. * {@link android.hardware.SensorEventListener2#onFlushCompleted onFlushCompleted} is called * after all the events in the batch at the time of calling this method have been delivered diff --git a/core/java/android/hardware/hdmi/HdmiClient.java b/core/java/android/hardware/hdmi/HdmiClient.java index aba90e47dd9c..45a79e1f3cae 100644 --- a/core/java/android/hardware/hdmi/HdmiClient.java +++ b/core/java/android/hardware/hdmi/HdmiClient.java @@ -3,13 +3,12 @@ package android.hardware.hdmi; import android.annotation.NonNull; import android.annotation.SystemApi; import android.hardware.hdmi.HdmiControlManager.VendorCommandListener; -import android.hardware.hdmi.IHdmiVendorCommandListener; import android.os.RemoteException; import android.util.Log; /** * Parent for classes of various HDMI-CEC device type used to access - * {@link HdmiControlService}. Contains methods and data used in common. + * the HDMI control system service. Contains methods and data used in common. * * @hide */ @@ -17,11 +16,13 @@ import android.util.Log; public abstract class HdmiClient { private static final String TAG = "HdmiClient"; - protected final IHdmiControlService mService; + /* package */ final IHdmiControlService mService; - protected abstract int getDeviceType(); + private IHdmiVendorCommandListener mIHdmiVendorCommandListener; - public HdmiClient(IHdmiControlService service) { + /* package */ abstract int getDeviceType(); + + /* package */ HdmiClient(IHdmiControlService service) { mService = service; } @@ -41,7 +42,7 @@ public abstract class HdmiClient { } /** - * Send a key event to other logical device. + * Sends a key event to other logical device. * * @param keyCode key code to send. Defined in {@link android.view.KeyEvent}. * @param isPressed true if this is key press event @@ -55,7 +56,7 @@ public abstract class HdmiClient { } /** - * Send vendor-specific command. + * Sends vendor-specific command. * * @param targetAddress address of the target device * @param params vendor-specific parameter. For <Vendor Command With ID> do not @@ -72,18 +73,23 @@ public abstract class HdmiClient { } /** - * Add a listener used to receive incoming vendor-specific command. + * Sets a listener used to receive incoming vendor-specific command. * * @param listener listener object */ - public void addVendorCommandListener(@NonNull VendorCommandListener listener) { + public void setVendorCommandListener(@NonNull VendorCommandListener listener) { if (listener == null) { throw new IllegalArgumentException("listener cannot be null"); } + if (mIHdmiVendorCommandListener != null) { + throw new IllegalStateException("listener was already set"); + } try { - mService.addVendorCommandListener(getListenerWrapper(listener), getDeviceType()); + IHdmiVendorCommandListener wrappedListener = getListenerWrapper(listener); + mService.addVendorCommandListener(wrappedListener, getDeviceType()); + mIHdmiVendorCommandListener = wrappedListener; } catch (RemoteException e) { - Log.e(TAG, "failed to add vendor command listener: ", e); + Log.e(TAG, "failed to set vendor command listener: ", e); } } @@ -91,8 +97,13 @@ public abstract class HdmiClient { final VendorCommandListener listener) { return new IHdmiVendorCommandListener.Stub() { @Override - public void onReceived(int srcAddress, byte[] params, boolean hasVendorId) { - listener.onReceived(srcAddress, params, hasVendorId); + public void onReceived(int srcAddress, int destAddress, byte[] params, + boolean hasVendorId) { + listener.onReceived(srcAddress, destAddress, params, hasVendorId); + } + @Override + public void onControlStateChanged(boolean enabled, int reason) { + listener.onControlStateChanged(enabled, reason); } }; } diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java index 30f3576648c1..308a21918ba9 100644 --- a/core/java/android/hardware/hdmi/HdmiControlManager.java +++ b/core/java/android/hardware/hdmi/HdmiControlManager.java @@ -21,6 +21,8 @@ import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.os.RemoteException; +import android.util.ArrayMap; +import android.util.Log; /** * The {@link HdmiControlManager} class is used to send HDMI control messages @@ -36,6 +38,8 @@ import android.os.RemoteException; */ @SystemApi public final class HdmiControlManager { + private static final String TAG = "HdmiControlManager"; + @Nullable private final IHdmiControlService mService; /** @@ -56,7 +60,7 @@ public final class HdmiControlManager { /** * Message used by TV to receive volume status from Audio Receiver. It should check volume value - * that is retrieved from extra value with the key {@link #EXTRA_MESSAGE_EXTRAM_PARAM1}. If the + * that is retrieved from extra value with the key {@link #EXTRA_MESSAGE_EXTRA_PARAM1}. If the * value is in range of [0,100], it is current volume of Audio Receiver. And there is another * value, {@link #AVR_VOLUME_MUTED}, which is used to inform volume mute. */ @@ -71,7 +75,7 @@ public final class HdmiControlManager { * Used as an extra field in the intent {@link #ACTION_OSD_MESSAGE}. Contains the extra value * of the message. */ - public static final String EXTRA_MESSAGE_EXTRAM_PARAM1 = + public static final String EXTRA_MESSAGE_EXTRA_PARAM1 = "android.hardware.hdmi.extra.MESSAGE_EXTRA_PARAM1"; /** @@ -236,16 +240,24 @@ public final class HdmiControlManager { /** Clear timer error - CEC is disabled. */ public static final int CLEAR_TIMER_STATUS_CEC_DISABLE = 0xA2; + /** The HdmiControlService is started. */ + public static final int CONTROL_STATE_CHANGED_REASON_START = 0; + /** The state of HdmiControlService is changed by changing of settings. */ + public static final int CONTROL_STATE_CHANGED_REASON_SETTING = 1; + /** The HdmiControlService is enabled to wake up. */ + public static final int CONTROL_STATE_CHANGED_REASON_WAKEUP = 2; + /** The HdmiControlService will be disabled to standby. */ + public static final int CONTROL_STATE_CHANGED_REASON_STANDBY = 3; + // True if we have a logical device of type playback hosted in the system. private final boolean mHasPlaybackDevice; // True if we have a logical device of type TV hosted in the system. private final boolean mHasTvDevice; /** - * @hide - hide this constructor because it has a parameter of type - * IHdmiControlService, which is a system private class. The right way - * to create an instance of this class is using the factory - * Context.getSystemService. + * {@hide} - hide this constructor because it has a parameter of type IHdmiControlService, + * which is a system private class. The right way to create an instance of this class is + * using the factory Context.getSystemService. */ public HdmiControlManager(IHdmiControlService service) { mService = service; @@ -331,6 +343,9 @@ public final class HdmiControlManager { void onReceived(HdmiHotplugEvent event); } + private final ArrayMap<HotplugEventListener, IHdmiHotplugEventListener> + mHotplugEventListeners = new ArrayMap<>(); + /** * Listener used to get vendor-specific commands. */ @@ -339,11 +354,29 @@ public final class HdmiControlManager { * Called when a vendor command is received. * * @param srcAddress source logical address + * @param destAddress destination logical address * @param params vendor-specific parameters * @param hasVendorId {@code true} if the command is <Vendor Command * With ID>. The first 3 bytes of params is vendor id. */ - void onReceived(int srcAddress, byte[] params, boolean hasVendorId); + void onReceived(int srcAddress, int destAddress, byte[] params, boolean hasVendorId); + + /** + * The callback is called: + * <ul> + * <li> before HdmiControlService is disabled. + * <li> after HdmiControlService is enabled and the local address is assigned. + * </ul> + * The client shouldn't hold the thread too long since this is a blocking call. + * + * @param enabled {@code true} if HdmiControlService is enabled. + * @param reason the reason code why the state of HdmiControlService is changed. + * @see #CONTROL_STATE_CHANGED_REASON_START + * @see #CONTROL_STATE_CHANGED_REASON_SETTING + * @see #CONTROL_STATE_CHANGED_REASON_WAKEUP + * @see #CONTROL_STATE_CHANGED_REASON_STANDBY + */ + void onControlStateChanged(boolean enabled, int reason); } /** @@ -357,12 +390,19 @@ public final class HdmiControlManager { */ public void addHotplugEventListener(HotplugEventListener listener) { if (mService == null) { + Log.e(TAG, "HdmiControlService is not available"); + return; + } + if (mHotplugEventListeners.containsKey(listener)) { + Log.e(TAG, "listener is already registered"); return; } + IHdmiHotplugEventListener wrappedListener = getHotplugEventListenerWrapper(listener); + mHotplugEventListeners.put(listener, wrappedListener); try { - mService.addHotplugEventListener(getHotplugEventListenerWrapper(listener)); + mService.addHotplugEventListener(wrappedListener); } catch (RemoteException e) { - // Do nothing. + Log.e(TAG, "failed to add hotplug event listener: ", e); } } @@ -373,12 +413,18 @@ public final class HdmiControlManager { */ public void removeHotplugEventListener(HotplugEventListener listener) { if (mService == null) { + Log.e(TAG, "HdmiControlService is not available"); + return; + } + IHdmiHotplugEventListener wrappedListener = mHotplugEventListeners.remove(listener); + if (wrappedListener == null) { + Log.e(TAG, "tried to remove not-registered listener"); return; } try { - mService.removeHotplugEventListener(getHotplugEventListenerWrapper(listener)); + mService.removeHotplugEventListener(wrappedListener); } catch (RemoteException e) { - // Do nothing. + Log.e(TAG, "failed to remove hotplug event listener: ", e); } } diff --git a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java index 7abea3696f44..fe414e6b11b5 100644 --- a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java +++ b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java @@ -237,14 +237,14 @@ public class HdmiDeviceInfo implements Parcelable { } /** - * Return the id of the device. + * Returns the id of the device. */ public int getId() { return mId; } /** - * Return the id to be used for CEC device. + * Returns the id to be used for CEC device. * * @param address logical address of CEC device * @return id for CEC device @@ -255,7 +255,7 @@ public class HdmiDeviceInfo implements Parcelable { } /** - * Return the id to be used for MHL device. + * Returns the id to be used for MHL device. * * @param portId port which the MHL device is connected to * @return id for MHL device @@ -266,7 +266,7 @@ public class HdmiDeviceInfo implements Parcelable { } /** - * Return the id to be used for hardware port. + * Returns the id to be used for hardware port. * * @param portId port id * @return id for hardware port @@ -276,28 +276,28 @@ public class HdmiDeviceInfo implements Parcelable { } /** - * Return the CEC logical address of the device. + * Returns the CEC logical address of the device. */ public int getLogicalAddress() { return mLogicalAddress; } /** - * Return the physical address of the device. + * Returns the physical address of the device. */ public int getPhysicalAddress() { return mPhysicalAddress; } /** - * Return the port ID. + * Returns the port ID. */ public int getPortId() { return mPortId; } /** - * Return CEC type of the device. For more details, refer constants between {@link #DEVICE_TV} + * Returns CEC type of the device. For more details, refer constants between {@link #DEVICE_TV} * and {@link #DEVICE_INACTIVE}. */ public int getDeviceType() { @@ -305,7 +305,7 @@ public class HdmiDeviceInfo implements Parcelable { } /** - * Return device's power status. It should be one of the following values. + * Returns device's power status. It should be one of the following values. * <ul> * <li>{@link HdmiControlManager#POWER_STATUS_ON} * <li>{@link HdmiControlManager#POWER_STATUS_STANDBY} @@ -319,21 +319,21 @@ public class HdmiDeviceInfo implements Parcelable { } /** - * Return MHL device id. Return -1 for non-MHL device. + * Returns MHL device id. Return -1 for non-MHL device. */ public int getDeviceId() { return mDeviceId; } /** - * Return MHL adopter id. Return -1 for non-MHL device. + * Returns MHL adopter id. Return -1 for non-MHL device. */ public int getAdopterId() { return mAdopterId; } /** - * Return {@code true} if the device is of a type that can be an input source. + * Returns {@code true} if the device is of a type that can be an input source. */ public boolean isSourceType() { return mDeviceType == DEVICE_PLAYBACK @@ -342,7 +342,7 @@ public class HdmiDeviceInfo implements Parcelable { } /** - * Return {@code true} if the device represents an HDMI-CEC device. {@code false} if the device + * Returns {@code true} if the device represents an HDMI-CEC device. {@code false} if the device * is either MHL or other device. */ public boolean isCecDevice() { @@ -350,7 +350,7 @@ public class HdmiDeviceInfo implements Parcelable { } /** - * Return {@code true} if the device represents an MHL device. {@code false} if the device is + * Returns {@code true} if the device represents an MHL device. {@code false} if the device is * either CEC or other device. */ public boolean isMhlDevice() { @@ -358,14 +358,14 @@ public class HdmiDeviceInfo implements Parcelable { } /** - * Return display (OSD) name of the device. + * Returns display (OSD) name of the device. */ public String getDisplayName() { return mDisplayName; } /** - * Return vendor id of the device. Vendor id is used to distinguish devices built by other + * Returns vendor id of the device. Vendor id is used to distinguish devices built by other * manufactures. This is required for vendor-specific command on CEC standard. */ public int getVendorId() { @@ -373,7 +373,7 @@ public class HdmiDeviceInfo implements Parcelable { } /** - * Describe the kinds of special objects contained in this Parcelable's marshalled + * Describes the kinds of special objects contained in this Parcelable's marshalled * representation. */ @Override @@ -382,7 +382,7 @@ public class HdmiDeviceInfo implements Parcelable { } /** - * Serialize this object into a {@link Parcel}. + * Serializes this object into a {@link Parcel}. * * @param dest The Parcel in which the object should be written. * @param flags Additional flags about how the object should be written. May be 0 or diff --git a/core/java/android/hardware/hdmi/HdmiHotplugEvent.java b/core/java/android/hardware/hdmi/HdmiHotplugEvent.java index 7be4bc57a329..94767428d031 100644 --- a/core/java/android/hardware/hdmi/HdmiHotplugEvent.java +++ b/core/java/android/hardware/hdmi/HdmiHotplugEvent.java @@ -44,7 +44,7 @@ public final class HdmiHotplugEvent implements Parcelable { } /** - * Return the port number for which the event occurred. + * Returns the port number for which the event occurred. * * @return port number */ @@ -53,7 +53,7 @@ public final class HdmiHotplugEvent implements Parcelable { } /** - * Return the connection status associated with this event + * Returns the connection status associated with this event * * @return true if the device gets connected; otherwise false */ @@ -62,7 +62,7 @@ public final class HdmiHotplugEvent implements Parcelable { } /** - * Describe the kinds of special objects contained in this Parcelable's + * Describes the kinds of special objects contained in this Parcelable's * marshalled representation. */ @Override @@ -71,7 +71,7 @@ public final class HdmiHotplugEvent implements Parcelable { } /** - * Flatten this object in to a Parcel. + * Flattens this object in to a Parcel. * * @param dest The Parcel in which the object should be written. * @param flags Additional flags about how the object should be written. @@ -86,17 +86,19 @@ public final class HdmiHotplugEvent implements Parcelable { public static final Parcelable.Creator<HdmiHotplugEvent> CREATOR = new Parcelable.Creator<HdmiHotplugEvent>() { /** - * Rebuild a {@link HdmiHotplugEvent} previously stored with + * Rebuilds a {@link HdmiHotplugEvent} previously stored with * {@link Parcelable#writeToParcel(Parcel, int)}. * * @param p {@link HdmiHotplugEvent} object to read the Rating from * @return a new {@link HdmiHotplugEvent} created from the data in the parcel */ + @Override public HdmiHotplugEvent createFromParcel(Parcel p) { int port = p.readInt(); boolean connected = p.readByte() == 1; return new HdmiHotplugEvent(port, connected); } + @Override public HdmiHotplugEvent[] newArray(int size) { return new HdmiHotplugEvent[size]; } diff --git a/core/java/android/hardware/hdmi/HdmiPlaybackClient.java b/core/java/android/hardware/hdmi/HdmiPlaybackClient.java index 85ccb7455216..263d6b1872ff 100644 --- a/core/java/android/hardware/hdmi/HdmiPlaybackClient.java +++ b/core/java/android/hardware/hdmi/HdmiPlaybackClient.java @@ -64,12 +64,12 @@ public final class HdmiPlaybackClient extends HdmiClient { public void onComplete(int status); } - HdmiPlaybackClient(IHdmiControlService service) { + /* package */ HdmiPlaybackClient(IHdmiControlService service) { super(service); } /** - * Perform the feature 'one touch play' from playback device to turn on display + * Performs the feature 'one touch play' from playback device to turn on display * and switch the input. * * @param callback {@link OneTouchPlayCallback} object to get informed @@ -90,7 +90,7 @@ public final class HdmiPlaybackClient extends HdmiClient { } /** - * Get the status of display device connected through HDMI bus. + * Gets the status of display device connected through HDMI bus. * * @param callback {@link DisplayStatusCallback} object to get informed * of the result diff --git a/core/java/android/hardware/hdmi/HdmiPortInfo.java b/core/java/android/hardware/hdmi/HdmiPortInfo.java index 2ec6126eb7b1..e52baed525a1 100644 --- a/core/java/android/hardware/hdmi/HdmiPortInfo.java +++ b/core/java/android/hardware/hdmi/HdmiPortInfo.java @@ -114,7 +114,7 @@ public final class HdmiPortInfo implements Parcelable { } /** - * Describe the kinds of special objects contained in this Parcelable's + * Describes the kinds of special objects contained in this Parcelable's * marshalled representation. */ @Override @@ -146,7 +146,7 @@ public final class HdmiPortInfo implements Parcelable { }; /** - * Serialize this object into a {@link Parcel}. + * Serializes this object into a {@link Parcel}. * * @param dest The Parcel in which the object should be written. * @param flags Additional flags about how the object should be written. diff --git a/core/java/android/hardware/hdmi/HdmiRecordListener.java b/core/java/android/hardware/hdmi/HdmiRecordListener.java index f6a348a65f68..29f6cfc3a29a 100644 --- a/core/java/android/hardware/hdmi/HdmiRecordListener.java +++ b/core/java/android/hardware/hdmi/HdmiRecordListener.java @@ -25,7 +25,7 @@ import android.hardware.hdmi.HdmiRecordSources.RecordSource; */ @SystemApi public abstract class HdmiRecordListener { - protected HdmiRecordListener() {} + public HdmiRecordListener() {} /** * Called when TV received one touch record request from record device. The client of this @@ -34,7 +34,7 @@ public abstract class HdmiRecordListener { * @param recorderAddress * @return record source to be used for recording. Null if no device is available. */ - public abstract RecordSource getOneTouchRecordSource(int recorderAddress); + public abstract RecordSource onOneTouchRecordSourceRequested(int recorderAddress); /** * Called when one touch record is started or failed during initialization. diff --git a/core/java/android/hardware/hdmi/HdmiRecordSources.java b/core/java/android/hardware/hdmi/HdmiRecordSources.java index dcc41fadfa38..922b8e7ae14f 100644 --- a/core/java/android/hardware/hdmi/HdmiRecordSources.java +++ b/core/java/android/hardware/hdmi/HdmiRecordSources.java @@ -55,23 +55,25 @@ public final class HdmiRecordSources { /** * Base class for each record source. + * @hide */ - static abstract class RecordSource { - protected final int mSourceType; - protected final int mExtraDataSize; + @SystemApi + public static abstract class RecordSource { + /* package */ final int mSourceType; + /* package */ final int mExtraDataSize; - protected RecordSource(int sourceType, int extraDataSize) { + /* package */ RecordSource(int sourceType, int extraDataSize) { mSourceType = sourceType; mExtraDataSize = extraDataSize; } - abstract int extraParamToByteArray(byte[] data, int index); + /* package */ abstract int extraParamToByteArray(byte[] data, int index); - final int getDataSize(boolean includeType) { + /* package */ final int getDataSize(boolean includeType) { return includeType ? mExtraDataSize + 1 : mExtraDataSize; } - final int toByteArray(boolean includeType, byte[] data, int index) { + /* package */ final int toByteArray(boolean includeType, byte[] data, int index) { if (includeType) { // 1 to 8 bytes (depends on source). // {[Record Source Type]} | @@ -92,7 +94,7 @@ public final class HdmiRecordSources { // ---- Own source ----------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------- /** - * Create {@link OwnSource} of own source. + * Creates {@link OwnSource} of own source. */ public static OwnSource ofOwnSource() { return new OwnSource(); @@ -309,7 +311,7 @@ public final class HdmiRecordSources { */ public static final class DigitalChannelData implements DigitalServiceIdentification { /** Identifies the logical or virtual channel number of a service. */ - private ChannelIdentifier mChannelIdentifier; + private final ChannelIdentifier mChannelIdentifier; public static DigitalChannelData ofTwoNumbers(int majorNumber, int minorNumber) { return new DigitalChannelData( @@ -336,7 +338,7 @@ public final class HdmiRecordSources { } /** - * Create {@link DigitalServiceSource} with channel type. + * Creates {@link DigitalServiceSource} with channel type. * * @param broadcastSystem digital broadcast system. It should be one of * <ul> @@ -387,7 +389,7 @@ public final class HdmiRecordSources { } /** - * Create {@link DigitalServiceSource} of ARIB type. + * Creates {@link DigitalServiceSource} of ARIB type. * * @param aribType ARIB type. It should be one of * <ul> @@ -418,7 +420,7 @@ public final class HdmiRecordSources { } /** - * Create {@link DigitalServiceSource} of ATSC type. + * Creates {@link DigitalServiceSource} of ATSC type. * * @param atscType ATSC type. It should be one of * <ul> @@ -449,7 +451,7 @@ public final class HdmiRecordSources { } /** - * Create {@link DigitalServiceSource} of ATSC type. + * Creates {@link DigitalServiceSource} of ATSC type. * * @param dvbType DVB type. It should be one of * <ul> @@ -570,7 +572,7 @@ public final class HdmiRecordSources { public static final int BROADCAST_SYSTEM_PAL_OTHER_SYSTEM = 31; /** - * Create {@link AnalogueServiceSource} of analogue service. + * Creates {@link AnalogueServiceSource} of analogue service. * * @param broadcastType * @param frequency @@ -613,7 +615,7 @@ public final class HdmiRecordSources { */ @SystemApi public static final class AnalogueServiceSource extends RecordSource { - static final int EXTRA_DATA_SIZE = 4; + /* package */ static final int EXTRA_DATA_SIZE = 4; /** Indicates the Analogue broadcast type. */ private final int mBroadcastType; @@ -633,7 +635,7 @@ public final class HdmiRecordSources { } @Override - protected int extraParamToByteArray(byte[] data, int index) { + /* package */ int extraParamToByteArray(byte[] data, int index) { // [Analogue Broadcast Type] - 1 byte data[index] = (byte) mBroadcastType; // [Analogue Frequency] - 2 bytes @@ -649,7 +651,7 @@ public final class HdmiRecordSources { // ---- External plug data --------------------------------------------------------------------- // --------------------------------------------------------------------------------------------- /** - * Create {@link ExternalPlugData} of external plug type. + * Creates {@link ExternalPlugData} of external plug type. * * @param plugNumber plug number. It should be in range of [1, 255] * @hide @@ -693,7 +695,7 @@ public final class HdmiRecordSources { // ---- External physical address -------------------------------------------------------------- // --------------------------------------------------------------------------------------------- /** - * Create {@link ExternalPhysicalAddress} of external physical address. + * Creates {@link ExternalPhysicalAddress} of external physical address. * * @param physicalAddress * @hide @@ -752,7 +754,7 @@ public final class HdmiRecordSources { } /** - * Check the byte array of record source. + * Checks the byte array of record source. * @hide */ @SystemApi diff --git a/core/java/android/hardware/hdmi/HdmiTimerRecordSources.java b/core/java/android/hardware/hdmi/HdmiTimerRecordSources.java index 178070762ba7..bf97375c8f95 100644 --- a/core/java/android/hardware/hdmi/HdmiTimerRecordSources.java +++ b/core/java/android/hardware/hdmi/HdmiTimerRecordSources.java @@ -67,7 +67,7 @@ public class HdmiTimerRecordSources { private HdmiTimerRecordSources() {} /** - * Create {@link TimerRecordSource} for digital source which is used for <Set Digital + * Creates {@link TimerRecordSource} for digital source which is used for <Set Digital * Timer>. * * @param timerInfo timer info used for timer recording @@ -82,7 +82,7 @@ public class HdmiTimerRecordSources { } /** - * Create {@link TimerRecordSource} for analogue source which is used for <Set Analogue + * Creates {@link TimerRecordSource} for analogue source which is used for <Set Analogue * Timer>. * * @param timerInfo timer info used for timer recording @@ -97,7 +97,7 @@ public class HdmiTimerRecordSources { } /** - * Create {@link TimerRecordSource} for external plug which is used for <Set External + * Creates {@link TimerRecordSource} for external plug which is used for <Set External * Timer>. * * @param timerInfo timer info used for timer recording @@ -112,7 +112,7 @@ public class HdmiTimerRecordSources { } /** - * Create {@link TimerRecordSource} for external physical address which is used for <Set + * Creates {@link TimerRecordSource} for external physical address which is used for <Set * External Timer>. * * @param timerInfo timer info used for timer recording @@ -140,7 +140,7 @@ public class HdmiTimerRecordSources { } /** - * Create {@link Duration} for time value. + * Creates {@link Duration} for time value. * * @param hour hour in range of [0, 23] * @param minute minute in range of [0, 60] @@ -162,7 +162,7 @@ public class HdmiTimerRecordSources { } /** - * Create {@link Duration} for duration value. + * Creates {@link Duration} for duration value. * * @param hour hour in range of [0, 99] * @param minute minute in range of [0, 59] @@ -184,21 +184,21 @@ public class HdmiTimerRecordSources { } private static class TimeUnit { - protected final int mHour; - protected final int mMinute; + /* package */ final int mHour; + /* package */ final int mMinute; - protected TimeUnit(int hour, int minute) { + /* package */ TimeUnit(int hour, int minute) { mHour = hour; mMinute = minute; } - protected int toByteArray(byte[] data, int index) { + /* package */ int toByteArray(byte[] data, int index) { data[index] = toBcdByte(mHour); data[index + 1] = toBcdByte(mMinute); return 2; } - protected static byte toBcdByte(int value) { + /* package */ static byte toBcdByte(int value) { int digitOfTen = (value / 10) % 10; int digitOfOne = value % 10; return (byte) ((digitOfTen << 4) | digitOfOne); @@ -247,7 +247,7 @@ public class HdmiTimerRecordSources { RECORDING_SEQUENCE_REPEAT_SATUREDAY); /** - * Create {@link TimerInfo} with the given information. + * Creates {@link TimerInfo} with the given information. * * @param dayOfMonth day of month * @param monthOfYear month of year @@ -426,7 +426,7 @@ public class HdmiTimerRecordSources { } /** - * Check the byte array of timer record source. + * Checks the byte array of timer record source. * @param sourcetype * @param recordSource * @hide diff --git a/core/java/android/hardware/hdmi/HdmiTvClient.java b/core/java/android/hardware/hdmi/HdmiTvClient.java index 9d92fd9c7fbd..dbfb4efe52a3 100644 --- a/core/java/android/hardware/hdmi/HdmiTvClient.java +++ b/core/java/android/hardware/hdmi/HdmiTvClient.java @@ -24,6 +24,9 @@ import android.util.Log; import libcore.util.EmptyArray; +import java.util.Collections; +import java.util.List; + /** * HdmiTvClient represents HDMI-CEC logical device of type TV in the Android system * which acts as TV/Display. It provides with methods that manage, interact with other @@ -40,13 +43,13 @@ public final class HdmiTvClient extends HdmiClient { */ public static final int VENDOR_DATA_SIZE = 16; - HdmiTvClient(IHdmiControlService service) { + /* package */ HdmiTvClient(IHdmiControlService service) { super(service); } // Factory method for HdmiTvClient. // Declared package-private. Accessed by HdmiControlManager only. - static HdmiTvClient create(IHdmiControlService service) { + /* package */ static HdmiTvClient create(IHdmiControlService service) { return new HdmiTvClient(service); } @@ -68,7 +71,7 @@ public final class HdmiTvClient extends HdmiClient { } /** - * Select a CEC logical device to be a new active source. + * Selects a CEC logical device to be a new active source. * * @param logicalAddress logical address of the device to select * @param callback callback to get the result with @@ -95,7 +98,7 @@ public final class HdmiTvClient extends HdmiClient { } /** - * Select a HDMI port to be a new route path. + * Selects a HDMI port to be a new route path. * * @param portId HDMI port to select * @param callback callback to get the result with @@ -125,7 +128,7 @@ public final class HdmiTvClient extends HdmiClient { } /** - * Set the listener used to get informed of the input change event. + * Sets the listener used to get informed of the input change event. * * @param listener listener object */ @@ -150,7 +153,22 @@ public final class HdmiTvClient extends HdmiClient { } /** - * Set system audio volume + * Returns all the CEC devices connected to TV. + * + * @return list of {@link HdmiDeviceInfo} for connected CEC devices. + * Empty list is returned if there is none. + */ + public List<HdmiDeviceInfo> getDeviceList() { + try { + return mService.getDeviceList(); + } catch (RemoteException e) { + Log.e("TAG", "Failed to call getDeviceList():", e); + return Collections.<HdmiDeviceInfo>emptyList(); + } + } + + /** + * Sets system audio volume * * @param oldIndex current volume index * @param newIndex volume index to be set @@ -165,7 +183,7 @@ public final class HdmiTvClient extends HdmiClient { } /** - * Set system audio mute status + * Sets system audio mute status * * @param mute {@code true} if muted; otherwise, {@code false} */ @@ -178,7 +196,7 @@ public final class HdmiTvClient extends HdmiClient { } /** - * Set record listener + * Sets record listener * * @param listener */ @@ -198,7 +216,7 @@ public final class HdmiTvClient extends HdmiClient { @Override public byte[] getOneTouchRecordSource(int recorderAddress) { HdmiRecordSources.RecordSource source = - callback.getOneTouchRecordSource(recorderAddress); + callback.onOneTouchRecordSourceRequested(recorderAddress); if (source == null) { return EmptyArray.BYTE; } @@ -226,13 +244,13 @@ public final class HdmiTvClient extends HdmiClient { } /** - * Start one touch recording with the given recorder address and recorder source. + * Starts one touch recording with the given recorder address and recorder source. * <p> * Usage * <pre> * HdmiTvClient tvClient = ....; * // for own source. - * OwnSource ownSource = ownHdmiRecordSources.ownSource(); + * OwnSource ownSource = HdmiRecordSources.ofOwnSource(); * tvClient.startOneTouchRecord(recorderAddress, ownSource); * </pre> */ @@ -251,7 +269,7 @@ public final class HdmiTvClient extends HdmiClient { } /** - * Stop one touch record. + * Stops one touch record. * * @param recorderAddress recorder address where recoding will be stopped */ @@ -264,7 +282,7 @@ public final class HdmiTvClient extends HdmiClient { } /** - * Start timer recording with the given recoder address and recorder source. + * Starts timer recording with the given recoder address and recorder source. * <p> * Usage * <pre> @@ -313,7 +331,7 @@ public final class HdmiTvClient extends HdmiClient { } /** - * Clear timer recording with the given recorder address and recording source. + * Clears timer recording with the given recorder address and recording source. * For more details, please refer {@link #startTimerRecording(int, int, TimerRecordSource)}. */ public void clearTimerRecording(int recorderAddress, int sourceType, TimerRecordSource source) { @@ -339,7 +357,7 @@ public final class HdmiTvClient extends HdmiClient { } /** - * Set {@link HdmiMhlVendorCommandListener} to get incoming MHL vendor command. + * Sets {@link HdmiMhlVendorCommandListener} to get incoming MHL vendor command. * * @param listener to receive incoming MHL vendor command */ @@ -365,7 +383,7 @@ public final class HdmiTvClient extends HdmiClient { } /** - * Send MHL vendor command to the device connected to a port of the given portId. + * Sends MHL vendor command to the device connected to a port of the given portId. * * @param portId id of port to send MHL vendor command * @param offset offset in the in given data diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl index 4866a9a9b6e2..c1e924e59735 100644 --- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl +++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl @@ -59,6 +59,7 @@ interface IHdmiControlService { void setSystemAudioMute(boolean mute); void setInputChangeListener(IHdmiInputChangeListener listener); List<HdmiDeviceInfo> getInputDevices(); + List<HdmiDeviceInfo> getDeviceList(); void sendVendorCommand(int deviceType, int targetAddress, in byte[] params, boolean hasVendorId); void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType); diff --git a/core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl b/core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl index 55cc9257667a..a16e8787df8a 100644 --- a/core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl +++ b/core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl @@ -23,5 +23,6 @@ package android.hardware.hdmi; * @hide */ oneway interface IHdmiVendorCommandListener { - void onReceived(int logicalAddress, in byte[] operands, boolean hasVendorId); + void onReceived(int logicalAddress, int destAddress, in byte[] operands, boolean hasVendorId); + void onControlStateChanged(boolean enabled, int reason); } diff --git a/core/java/android/net/BaseNetworkStateTracker.java b/core/java/android/net/BaseNetworkStateTracker.java index 58d00487802c..e4e5b1e35d6c 100644 --- a/core/java/android/net/BaseNetworkStateTracker.java +++ b/core/java/android/net/BaseNetworkStateTracker.java @@ -170,16 +170,6 @@ public abstract class BaseNetworkStateTracker implements NetworkStateTracker { } @Override - public void addStackedLink(LinkProperties link) { - mLinkProperties.addStackedLink(link); - } - - @Override - public void removeStackedLink(LinkProperties link) { - mLinkProperties.removeStackedLink(link); - } - - @Override public void supplyMessenger(Messenger messenger) { // not supported on this network } diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java index c387055741f4..384ab1c8f50c 100644 --- a/core/java/android/net/LinkAddress.java +++ b/core/java/android/net/LinkAddress.java @@ -21,12 +21,14 @@ import android.os.Parcelable; import android.util.Pair; import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.InterfaceAddress; import java.net.UnknownHostException; import static android.system.OsConstants.IFA_F_DADFAILED; import static android.system.OsConstants.IFA_F_DEPRECATED; +import static android.system.OsConstants.IFA_F_OPTIMISTIC; import static android.system.OsConstants.IFA_F_TENTATIVE; import static android.system.OsConstants.RT_SCOPE_HOST; import static android.system.OsConstants.RT_SCOPE_LINK; @@ -93,6 +95,20 @@ public class LinkAddress implements Parcelable { } /** + * Utility function to check if |address| is a Unique Local IPv6 Unicast Address + * (a.k.a. "ULA"; RFC 4193). + * + * Per RFC 4193 section 8, fc00::/7 identifies these addresses. + */ + private boolean isIPv6ULA() { + if (address != null && address instanceof Inet6Address) { + byte[] bytes = address.getAddress(); + return ((bytes[0] & (byte)0xfc) == (byte)0xfc); + } + return false; + } + + /** * Utility function for the constructors. */ private void init(InetAddress address, int prefixLength, int flags, int scope) { @@ -268,8 +284,16 @@ public class LinkAddress implements Parcelable { * @hide */ public boolean isGlobalPreferred() { + /** + * Note that addresses flagged as IFA_F_OPTIMISTIC are + * simultaneously flagged as IFA_F_TENTATIVE (when the tentative + * state has cleared either DAD has succeeded or failed, and both + * flags are cleared regardless). + */ return (scope == RT_SCOPE_UNIVERSE && - (flags & (IFA_F_DADFAILED | IFA_F_DEPRECATED | IFA_F_TENTATIVE)) == 0L); + !isIPv6ULA() && + (flags & (IFA_F_DADFAILED | IFA_F_DEPRECATED)) == 0L && + ((flags & IFA_F_TENTATIVE) == 0L || (flags & IFA_F_OPTIMISTIC) != 0L)); } /** diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java index 662c57627f59..8b0dfc95fef0 100644 --- a/core/java/android/net/LinkProperties.java +++ b/core/java/android/net/LinkProperties.java @@ -493,16 +493,16 @@ public final class LinkProperties implements Parcelable { /** * Removes a stacked link. * - * If there a stacked link with the same interfacename as link, it is + * If there is a stacked link with the given interface name, it is * removed. Otherwise, nothing changes. * - * @param link The link to remove. + * @param iface The interface name of the link to remove. * @return true if the link was removed, false otherwise. * @hide */ - public boolean removeStackedLink(LinkProperties link) { - if (link != null && link.getInterfaceName() != null) { - LinkProperties removed = mStackedLinks.remove(link.getInterfaceName()); + public boolean removeStackedLink(String iface) { + if (iface != null) { + LinkProperties removed = mStackedLinks.remove(iface); return removed != null; } return false; @@ -675,17 +675,38 @@ public final class LinkProperties implements Parcelable { } /** - * Returns true if this link is provisioned for global connectivity. For IPv6, this requires an - * IP address, default route, and DNS server. For IPv4, this requires only an IPv4 address, - * because WifiStateMachine accepts static configurations that only specify an address but not - * DNS servers or a default route. + * Returns true if this link is provisioned for global IPv4 connectivity. + * This requires an IP address, default route, and DNS server. + * + * @return {@code true} if the link is provisioned, {@code false} otherwise. + */ + private boolean hasIPv4() { + return (hasIPv4Address() && + hasIPv4DefaultRoute() && + hasIPv4DnsServer()); + } + + /** + * Returns true if this link is provisioned for global IPv6 connectivity. + * This requires an IP address, default route, and DNS server. + * + * @return {@code true} if the link is provisioned, {@code false} otherwise. + */ + private boolean hasIPv6() { + return (hasGlobalIPv6Address() && + hasIPv6DefaultRoute() && + hasIPv6DnsServer()); + } + + /** + * Returns true if this link is provisioned for global connectivity, + * for at least one Internet Protocol family. * * @return {@code true} if the link is provisioned, {@code false} otherwise. * @hide */ public boolean isProvisioned() { - return (hasIPv4Address() || - (hasGlobalIPv6Address() && hasIPv6DefaultRoute() && hasIPv6DnsServer())); + return (hasIPv4() || hasIPv6()); } /** diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java index d8012fee5beb..40b7e066ddee 100644 --- a/core/java/android/net/MobileDataStateTracker.java +++ b/core/java/android/net/MobileDataStateTracker.java @@ -661,16 +661,6 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker { } @Override - public void addStackedLink(LinkProperties link) { - mLinkProperties.addStackedLink(link); - } - - @Override - public void removeStackedLink(LinkProperties link) { - mLinkProperties.removeStackedLink(link); - } - - @Override public String toString() { final CharArrayWriter writer = new CharArrayWriter(); final PrintWriter pw = new PrintWriter(writer); diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java index 58f0fc047dd8..4fa0593c5e13 100644 --- a/core/java/android/net/Network.java +++ b/core/java/android/net/Network.java @@ -21,7 +21,9 @@ import android.os.Parcelable; import android.os.Parcel; import android.system.ErrnoException; +import java.io.FileDescriptor; import java.io.IOException; +import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.MalformedURLException; @@ -264,18 +266,40 @@ public class Network implements Parcelable { } /** + * Binds the specified {@link DatagramSocket} to this {@code Network}. All data traffic on the + * socket will be sent on this {@code Network}, irrespective of any process-wide network binding + * set by {@link ConnectivityManager#setProcessDefaultNetwork}. The socket must not be + * connected. + */ + public void bindSocket(DatagramSocket socket) throws IOException { + // Apparently, the kernel doesn't update a connected UDP socket's routing upon mark changes. + if (socket.isConnected()) { + throw new SocketException("Socket is connected"); + } + // Query a property of the underlying socket to ensure that the socket's file descriptor + // exists, is available to bind to a network and is not closed. + socket.getReuseAddress(); + bindSocketFd(socket.getFileDescriptor$()); + } + + /** * Binds the specified {@link Socket} to this {@code Network}. All data traffic on the socket * will be sent on this {@code Network}, irrespective of any process-wide network binding set by * {@link ConnectivityManager#setProcessDefaultNetwork}. The socket must not be connected. */ public void bindSocket(Socket socket) throws IOException { + // Apparently, the kernel doesn't update a connected TCP socket's routing upon mark changes. if (socket.isConnected()) { throw new SocketException("Socket is connected"); } - // Query a property of the underlying socket to ensure the underlying - // socket exists so a file descriptor is available to bind to a network. + // Query a property of the underlying socket to ensure that the socket's file descriptor + // exists, is available to bind to a network and is not closed. socket.getReuseAddress(); - int err = NetworkUtils.bindSocketToNetwork(socket.getFileDescriptor$().getInt$(), netId); + bindSocketFd(socket.getFileDescriptor$()); + } + + private void bindSocketFd(FileDescriptor fd) throws IOException { + int err = NetworkUtils.bindSocketToNetwork(fd.getInt$(), netId); if (err != 0) { // bindSocketToNetwork returns negative errno. throw new ErrnoException("Binding socket to network " + netId, -err) diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java index 35500cc1cdb6..c80782c4fd60 100644 --- a/core/java/android/net/NetworkStateTracker.java +++ b/core/java/android/net/NetworkStateTracker.java @@ -216,16 +216,6 @@ public interface NetworkStateTracker { */ public void setDependencyMet(boolean met); - /** - * Informs the state tracker that another interface is stacked on top of it. - **/ - public void addStackedLink(LinkProperties link); - - /** - * Informs the state tracker that a stacked interface has been removed. - **/ - public void removeStackedLink(LinkProperties link); - /* * Called once to setup async channel between this and * the underlying network specific code. diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java index 6a78c29c15ac..3477b029f793 100644 --- a/core/java/android/net/Proxy.java +++ b/core/java/android/net/Proxy.java @@ -19,17 +19,10 @@ package android.net; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.content.Context; -import android.net.ProxyInfo; import android.text.TextUtils; import android.util.Log; - import org.apache.http.HttpHost; -import org.apache.http.HttpRequest; -import org.apache.http.conn.routing.HttpRoute; -import org.apache.http.conn.routing.HttpRoutePlanner; -import org.apache.http.conn.scheme.SchemeRegistry; -import org.apache.http.protocol.HttpContext; import java.net.InetSocketAddress; import java.net.ProxySelector; @@ -212,6 +205,7 @@ public final class Proxy { * is no proxy. * {@hide} */ + // TODO: Get rid of this method. It's used only in tests. public static final HttpHost getPreferredHttpHost(Context context, String url) { java.net.Proxy prefProxy = getProxy(context, url); diff --git a/core/java/android/net/ProxyInfo.java b/core/java/android/net/ProxyInfo.java index 1534e2c7f4b1..7694420e7065 100644 --- a/core/java/android/net/ProxyInfo.java +++ b/core/java/android/net/ProxyInfo.java @@ -36,7 +36,13 @@ import java.util.Locale; * * Other HTTP stacks will need to obtain the proxy info from * {@link Proxy#PROXY_CHANGE_ACTION} broadcast as the extra {@link Proxy#EXTRA_PROXY_INFO}. + * + * @deprecated Please use {@link java.net.URL#openConnection}, {@link java.net.Proxy} and + * friends. The Apache HTTP client is no longer maintained and may be removed in a future + * release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a> + * for further details. */ +@Deprecated public class ProxyInfo implements Parcelable { private String mHost; diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java index b0278d39e072..c15e6e55ab45 100644 --- a/core/java/android/net/SSLCertificateSocketFactory.java +++ b/core/java/android/net/SSLCertificateSocketFactory.java @@ -154,7 +154,13 @@ public class SSLCertificateSocketFactory extends SSLSocketFactory { * for none. The socket timeout is reset to 0 after the handshake. * @param cache The {@link SSLSessionCache} to use, or null for no cache. * @return a new SocketFactory with the specified parameters + * + * @deprecated Use {@link #getDefault()} along with a {@link javax.net.ssl.HttpsURLConnection} + * instead. The Apache HTTP client is no longer maintained and may be removed in a future + * release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a> + * for further details. */ + @Deprecated public static org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory( int handshakeTimeoutMillis, SSLSessionCache cache) { return new org.apache.http.conn.ssl.SSLSocketFactory( diff --git a/core/java/android/net/http/AndroidHttpClient.java b/core/java/android/net/http/AndroidHttpClient.java index 04f3974f4132..a26207666283 100644 --- a/core/java/android/net/http/AndroidHttpClient.java +++ b/core/java/android/net/http/AndroidHttpClient.java @@ -74,7 +74,13 @@ import java.util.zip.GZIPOutputStream; * To retain cookies, simply add a cookie store to the HttpContext:</p> * * <pre>context.setAttribute(ClientContext.COOKIE_STORE, cookieStore);</pre> + * + * @deprecated Please use {@link java.net.URLConnection} and friends instead. + * The Apache HTTP client is no longer maintained and may be removed in a future + * release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a> + * for further details. */ +@Deprecated public final class AndroidHttpClient implements HttpClient { // Gzip of data shorter than this probably won't be worthwhile @@ -108,7 +114,13 @@ public final class AndroidHttpClient implements HttpClient { * @param userAgent to report in your HTTP requests * @param context to use for caching SSL sessions (may be null for no caching) * @return AndroidHttpClient for you to use for all your requests. + * + * @deprecated Please use {@link java.net.URLConnection} and friends instead. See + * {@link android.net.SSLCertificateSocketFactory} for SSL cache support. If you'd + * like to set a custom useragent, please use {@link java.net.URLConnection#setRequestProperty(String, String)} + * with {@code field} set to {@code User-Agent}. */ + @Deprecated public static AndroidHttpClient newInstance(String userAgent, Context context) { HttpParams params = new BasicHttpParams(); @@ -148,7 +160,13 @@ public final class AndroidHttpClient implements HttpClient { * Create a new HttpClient with reasonable defaults (which you can update). * @param userAgent to report in your HTTP requests. * @return AndroidHttpClient for you to use for all your requests. + * + * @deprecated Please use {@link java.net.URLConnection} and friends instead. See + * {@link android.net.SSLCertificateSocketFactory} for SSL cache support. If you'd + * like to set a custom useragent, please use {@link java.net.URLConnection#setRequestProperty(String, String)} + * with {@code field} set to {@code User-Agent}. */ + @Deprecated public static AndroidHttpClient newInstance(String userAgent) { return newInstance(userAgent, null /* session cache */); } diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 24cdd77fa3cc..f361695b2fbd 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -588,6 +588,11 @@ public class Build { * </ul> */ public static final int LOLLIPOP = 21; + + /** + * Lollipop with an extra sugar coating on the outside! + */ + public static final int LOLLIPOP_MR1 = 22; } /** The type of build, like "user" or "eng". */ diff --git a/core/java/android/os/ConditionVariable.java b/core/java/android/os/ConditionVariable.java index 07b221c81dba..1e820f945689 100644 --- a/core/java/android/os/ConditionVariable.java +++ b/core/java/android/os/ConditionVariable.java @@ -109,7 +109,7 @@ public class ConditionVariable * <p> * If the condition is already opened, return immediately. * - * @param timeout the minimum time to wait in milliseconds. + * @param timeout the maximum time to wait in milliseconds. * * @return true if the condition was opened, false if the call returns * because of the timeout. diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java index 18730b65a7dd..084ca30e263c 100644 --- a/core/java/android/os/Debug.java +++ b/core/java/android/os/Debug.java @@ -1093,7 +1093,15 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo /** @hide */ public static final int MEMINFO_ZRAM_TOTAL = 8; /** @hide */ - public static final int MEMINFO_COUNT = 9; + public static final int MEMINFO_MAPPED = 9; + /** @hide */ + public static final int MEMINFO_VM_ALLOC_USED = 10; + /** @hide */ + public static final int MEMINFO_PAGE_TABLES = 11; + /** @hide */ + public static final int MEMINFO_KERNEL_STACK = 12; + /** @hide */ + public static final int MEMINFO_COUNT = 13; /** * Retrieves /proc/meminfo. outSizes is filled with fields diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index 16250c78af9a..5d5d2b384e04 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -92,6 +92,11 @@ interface INetworkManagementService void enableIpv6(String iface); /** + * Enables or enables IPv6 ND offload. + */ + void setInterfaceIpv6NdOffload(String iface, boolean enable); + + /** * Retrieves the network routes currently configured on the specified * interface */ @@ -336,19 +341,19 @@ interface INetworkManagementService void removeVpnUidRanges(int netId, in UidRange[] ranges); /** - * Start the clatd (464xlat) service + * Start the clatd (464xlat) service on the given interface. */ void startClatd(String interfaceName); /** - * Stop the clatd (464xlat) service + * Stop the clatd (464xlat) service on the given interface. */ - void stopClatd(); + void stopClatd(String interfaceName); /** - * Determine whether the clatd (464xlat) service has been started + * Determine whether the clatd (464xlat) service has been started on the given interface. */ - boolean isClatdStarted(); + boolean isClatdStarted(String interfaceName); /** * Start listening for mobile activity state changes. diff --git a/core/java/android/preference/ListPreference.java b/core/java/android/preference/ListPreference.java index 8081a5496399..9482a72a2f7c 100644 --- a/core/java/android/preference/ListPreference.java +++ b/core/java/android/preference/ListPreference.java @@ -162,10 +162,10 @@ public class ListPreference extends DialogPreference { @Override public CharSequence getSummary() { final CharSequence entry = getEntry(); - if (mSummary == null || entry == null) { + if (mSummary == null) { return super.getSummary(); } else { - return String.format(mSummary, entry); + return String.format(mSummary, entry == null ? "" : entry); } } diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java index 671f722fac10..3130b6465621 100644 --- a/core/java/android/preference/SeekBarVolumizer.java +++ b/core/java/android/preference/SeekBarVolumizer.java @@ -47,7 +47,6 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba } private final Context mContext; - private final Handler mHandler; private final H mUiHandler = new H(); private final Callback mCallback; private final Uri mDefaultUri; @@ -55,8 +54,9 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba private final int mStreamType; private final int mMaxStreamVolume; private final Receiver mReceiver = new Receiver(); - private final Observer mVolumeObserver; + private Handler mHandler; + private Observer mVolumeObserver; private int mOriginalStreamVolume; private Ringtone mRingtone; private int mLastProgress = -1; @@ -75,16 +75,8 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); mStreamType = streamType; mMaxStreamVolume = mAudioManager.getStreamMaxVolume(mStreamType); - HandlerThread thread = new HandlerThread(TAG + ".CallbackHandler"); - thread.start(); - mHandler = new Handler(thread.getLooper(), this); mCallback = callback; mOriginalStreamVolume = mAudioManager.getStreamVolume(mStreamType); - mVolumeObserver = new Observer(mHandler); - mContext.getContentResolver().registerContentObserver( - System.getUriFor(System.VOLUME_SETTINGS[mStreamType]), - false, mVolumeObserver); - mReceiver.setListening(true); if (defaultUri == null) { if (mStreamType == AudioManager.STREAM_RING) { defaultUri = Settings.System.DEFAULT_RINGTONE_URI; @@ -95,7 +87,6 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba } } mDefaultUri = defaultUri; - mHandler.sendEmptyMessage(MSG_INIT_SAMPLE); } public void setSeekBar(SeekBar seekBar) { @@ -139,6 +130,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba } private void postStartSample() { + if (mHandler == null) return; mHandler.removeMessages(MSG_START_SAMPLE); mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_SAMPLE), isSamplePlaying() ? CHECK_RINGTONE_PLAYBACK_DELAY_MS : 0); @@ -159,7 +151,8 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba } } - void postStopSample() { + private void postStopSample() { + if (mHandler == null) return; // remove pending delayed start messages mHandler.removeMessages(MSG_START_SAMPLE); mHandler.removeMessages(MSG_STOP_SAMPLE); @@ -173,11 +166,27 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba } public void stop() { + if (mHandler == null) return; // already stopped postStopSample(); mContext.getContentResolver().unregisterContentObserver(mVolumeObserver); - mSeekBar.setOnSeekBarChangeListener(null); mReceiver.setListening(false); + mSeekBar.setOnSeekBarChangeListener(null); mHandler.getLooper().quitSafely(); + mHandler = null; + mVolumeObserver = null; + } + + public void start() { + if (mHandler != null) return; // already started + HandlerThread thread = new HandlerThread(TAG + ".CallbackHandler"); + thread.start(); + mHandler = new Handler(thread.getLooper(), this); + mHandler.sendEmptyMessage(MSG_INIT_SAMPLE); + mVolumeObserver = new Observer(mHandler); + mContext.getContentResolver().registerContentObserver( + System.getUriFor(System.VOLUME_SETTINGS[mStreamType]), + false, mVolumeObserver); + mReceiver.setListening(true); } public void revertVolume() { @@ -193,7 +202,8 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba postSetVolume(progress); } - void postSetVolume(int progress) { + private void postSetVolume(int progress) { + if (mHandler == null) return; // Do the volume changing separately to give responsive UI mLastProgress = progress; mHandler.removeMessages(MSG_SET_STREAM_VOLUME); diff --git a/core/java/android/preference/VolumePreference.java b/core/java/android/preference/VolumePreference.java index df9e10e6d261..0d4c0b6d0152 100644 --- a/core/java/android/preference/VolumePreference.java +++ b/core/java/android/preference/VolumePreference.java @@ -67,6 +67,7 @@ public class VolumePreference extends SeekBarDialogPreference implements final SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar); mSeekBarVolumizer = new SeekBarVolumizer(getContext(), mStreamType, null, this); + mSeekBarVolumizer.start(); mSeekBarVolumizer.setSeekBar(seekBar); getPreferenceManager().registerOnActivityStopListener(this); @@ -116,7 +117,7 @@ public class VolumePreference extends SeekBarDialogPreference implements public void onActivityStop() { if (mSeekBarVolumizer != null) { - mSeekBarVolumizer.postStopSample(); + mSeekBarVolumizer.stopSample(); } } diff --git a/core/java/android/print/IPrintDocumentAdapter.aidl b/core/java/android/print/IPrintDocumentAdapter.aidl index 9d384fba874d..8f33e0b2c003 100644 --- a/core/java/android/print/IPrintDocumentAdapter.aidl +++ b/core/java/android/print/IPrintDocumentAdapter.aidl @@ -37,4 +37,5 @@ oneway interface IPrintDocumentAdapter { void write(in PageRange[] pages, in ParcelFileDescriptor fd, IWriteResultCallback callback, int sequence); void finish(); + void kill(String reason); } diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java index bf8ac651ed51..3fb812e401f7 100644 --- a/core/java/android/print/PrintManager.java +++ b/core/java/android/print/PrintManager.java @@ -634,6 +634,17 @@ public final class PrintManager { } @Override + public void kill(String reason) { + synchronized (mLock) { + // If destroyed the handler is null. + if (!isDestroyedLocked()) { + mHandler.obtainMessage(MyHandler.MSG_ON_KILL, + reason).sendToTarget(); + } + } + } + + @Override public void onActivityPaused(Activity activity) { /* do nothing */ } @@ -719,6 +730,7 @@ public final class PrintManager { public static final int MSG_ON_LAYOUT = 2; public static final int MSG_ON_WRITE = 3; public static final int MSG_ON_FINISH = 4; + public static final int MSG_ON_KILL = 5; public MyHandler(Looper looper) { super(looper, null, true); @@ -794,6 +806,15 @@ public final class PrintManager { } } break; + case MSG_ON_KILL: { + if (DEBUG) { + Log.i(LOG_TAG, "onKill()"); + } + + String reason = (String) message.obj; + throw new RuntimeException(reason); + } + default: { throw new IllegalArgumentException("Unknown message: " + message.what); diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java index 3e80ed0d23b1..3ec45e9095bf 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -24,13 +24,17 @@ import android.content.Context; import android.content.Intent; import android.content.pm.UserInfo; import android.database.Cursor; +import android.location.Country; +import android.location.CountryDetector; import android.net.Uri; import android.os.UserHandle; import android.os.UserManager; import android.provider.ContactsContract.CommonDataKinds.Callable; import android.provider.ContactsContract.CommonDataKinds.Phone; +import android.provider.ContactsContract.Data; import android.provider.ContactsContract.DataUsageFeedback; import android.telecom.PhoneAccountHandle; +import android.telephony.PhoneNumberUtils; import android.text.TextUtils; import com.android.internal.telephony.CallerInfo; @@ -404,7 +408,6 @@ public class CallLog { * @param accountHandle The accountHandle object identifying the provider of the call * @param start time stamp for the call in milliseconds * @param duration call duration in seconds - * @param subId the subscription id. * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for * the call. * @param addForAllUsers If true, the call is added to the call log of all currently @@ -503,12 +506,13 @@ public class CallLog { if (cursor != null) { try { if (cursor.getCount() > 0 && cursor.moveToFirst()) { - final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon() - .appendPath(cursor.getString(0)) - .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, - DataUsageFeedback.USAGE_TYPE_CALL) - .build(); - resolver.update(feedbackUri, new ContentValues(), null, null); + final String dataId = cursor.getString(0); + updateDataUsageStatForData(resolver, dataId); + if (duration >= MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS + && callType == Calls.OUTGOING_TYPE + && TextUtils.isEmpty(ci.normalizedNumber)) { + updateNormalizedNumber(context, resolver, dataId, number); + } } } finally { cursor.close(); @@ -581,5 +585,50 @@ public class CallLog { + " LIMIT -1 OFFSET 500)", null); return result; } + + private static void updateDataUsageStatForData(ContentResolver resolver, String dataId) { + final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon() + .appendPath(dataId) + .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, + DataUsageFeedback.USAGE_TYPE_CALL) + .build(); + resolver.update(feedbackUri, new ContentValues(), null, null); + } + + /* + * Update the normalized phone number for the given dataId in the ContactsProvider, based + * on the user's current country. + */ + private static void updateNormalizedNumber(Context context, ContentResolver resolver, + String dataId, String number) { + if (TextUtils.isEmpty(number) || TextUtils.isEmpty(dataId)) { + return; + } + final String countryIso = getCurrentCountryIso(context); + if (TextUtils.isEmpty(countryIso)) { + return; + } + final String normalizedNumber = PhoneNumberUtils.formatNumberToE164(number, + getCurrentCountryIso(context)); + if (TextUtils.isEmpty(normalizedNumber)) { + return; + } + final ContentValues values = new ContentValues(); + values.put(Phone.NORMALIZED_NUMBER, normalizedNumber); + resolver.update(Data.CONTENT_URI, values, Data._ID + "=?", new String[] {dataId}); + } + + private static String getCurrentCountryIso(Context context) { + String countryIso = null; + final CountryDetector detector = (CountryDetector) context.getSystemService( + Context.COUNTRY_DETECTOR); + if (detector != null) { + final Country country = detector.detectCountry(); + if (country != null) { + countryIso = country.getCountryIso(); + } + } + return countryIso; + } } } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index b1c338ee1cdd..c54a5ba80548 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -787,11 +787,10 @@ public final class Settings { * <p> * Output: Nothing. * @see android.service.notification.NotificationListenerService - * @hide */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_NOTIFICATION_LISTENER_SETTINGS - = "android.settings.NOTIFICATION_LISTENER_SETTINGS"; + = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"; /** * @hide @@ -873,8 +872,9 @@ public final class Settings { /** * Activity Action: Show battery saver settings. - * - * @hide + * <p> + * In some cases, a matching Activity may not exist, so ensure you safeguard + * against this. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_BATTERY_SAVER_SETTINGS @@ -3017,7 +3017,6 @@ public final class Settings { MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_ENABLED); MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_GLOBAL_ALERT_BYTES); MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_POLL_INTERVAL); - MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_REPORT_XT_OVER_DEV); MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_SAMPLE_ENABLED); MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_TIME_CACHE_MAX_AGE); MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_UID_BUCKET_DURATION); @@ -4739,8 +4738,8 @@ public final class Settings { public static final String SMS_DEFAULT_APPLICATION = "sms_default_application"; /** - * Name of a package that the current user has explicitly allowed to see all of that - * user's notifications. + * Names of the packages that the current user has explicitly allowed to + * see all of the user's notifications, separated by ':'. * * @hide */ @@ -5013,10 +5012,19 @@ public final class Settings { default: throw new IllegalArgumentException("Invalid location mode: " + mode); } - boolean gpsSuccess = Settings.Secure.setLocationProviderEnabledForUser( - cr, LocationManager.GPS_PROVIDER, gps, userId); + // Note it's important that we set the NLP mode first. The Google implementation + // of NLP clears its NLP consent setting any time it receives a + // LocationManager.PROVIDERS_CHANGED_ACTION broadcast and NLP is disabled. Also, + // it shows an NLP consent dialog any time it receives the broadcast, NLP is + // enabled, and the NLP consent is not set. If 1) we were to enable GPS first, + // 2) a setup wizard has its own NLP consent UI that sets the NLP consent setting, + // and 3) the receiver happened to complete before we enabled NLP, then the Google + // NLP would detect the attempt to enable NLP and show a redundant NLP consent + // dialog. Then the people who wrote the setup wizard would be sad. boolean nlpSuccess = Settings.Secure.setLocationProviderEnabledForUser( cr, LocationManager.NETWORK_PROVIDER, network, userId); + boolean gpsSuccess = Settings.Secure.setLocationProviderEnabledForUser( + cr, LocationManager.GPS_PROVIDER, gps, userId); return gpsSuccess && nlpSuccess; } } @@ -5453,8 +5461,6 @@ public final class Settings { public static final String NETSTATS_GLOBAL_ALERT_BYTES = "netstats_global_alert_bytes"; /** {@hide} */ public static final String NETSTATS_SAMPLE_ENABLED = "netstats_sample_enabled"; - /** {@hide} */ - public static final String NETSTATS_REPORT_XT_OVER_DEV = "netstats_report_xt_over_dev"; /** {@hide} */ public static final String NETSTATS_DEV_BUCKET_DURATION = "netstats_dev_bucket_duration"; @@ -6585,6 +6591,14 @@ public final class Settings { public static final String REQUIRE_PASSWORD_TO_DECRYPT = "require_password_to_decrypt"; /** + * Whether the Volte/VT is enabled + * <p> + * Type: int (0 for false, 1 for true) + * @hide + */ + public static final String ENHANCED_4G_MODE_ENABLED = "volte_vt_enabled"; + + /** * Settings to backup. This is here so that it's in the same place as the settings * keys and easy to update. * @@ -6615,7 +6629,8 @@ public final class Settings { WIFI_NUM_OPEN_NETWORKS_KEPT, EMERGENCY_TONE, CALL_AUTO_RETRY, - DOCK_AUDIO_MEDIA_ENABLED + DOCK_AUDIO_MEDIA_ENABLED, + LOW_POWER_MODE_TRIGGER_LEVEL }; // Populated lazily, guarded by class object: diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index 882a3c83d7ac..9a84a1ee9009 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -17,11 +17,13 @@ package android.service.notification; import android.content.ComponentName; +import android.content.Context; import android.content.res.Resources; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import android.text.format.DateFormat; import android.util.Slog; import org.xmlpull.v1.XmlPullParser; @@ -32,8 +34,11 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; +import java.util.Locale; import java.util.Objects; +import com.android.internal.R; + /** * Persisted configuration for zen mode. * @@ -461,20 +466,34 @@ public class ZenModeConfig implements Parcelable { return downtime; } - public static Condition toTimeCondition(int minutesFromNow) { + public static Condition toTimeCondition(Context context, int minutesFromNow) { final long now = System.currentTimeMillis(); final long millis = minutesFromNow == 0 ? ZERO_VALUE_MS : minutesFromNow * MINUTES_MS; - return toTimeCondition(now + millis, minutesFromNow); + return toTimeCondition(context, now + millis, minutesFromNow, now); } - public static Condition toTimeCondition(long time, int minutes) { - final int num = minutes < 60 ? minutes : Math.round(minutes / 60f); - final int resId = minutes < 60 - ? com.android.internal.R.plurals.zen_mode_duration_minutes - : com.android.internal.R.plurals.zen_mode_duration_hours; - final String caption = Resources.getSystem().getQuantityString(resId, num, num); + public static Condition toTimeCondition(Context context, long time, int minutes, long now) { + final int num, summaryResId, line1ResId; + if (minutes < 60) { + // display as minutes + num = minutes; + summaryResId = R.plurals.zen_mode_duration_minutes_summary; + line1ResId = R.plurals.zen_mode_duration_minutes; + } else { + // display as hours + num = Math.round(minutes / 60f); + summaryResId = com.android.internal.R.plurals.zen_mode_duration_hours_summary; + line1ResId = com.android.internal.R.plurals.zen_mode_duration_hours; + } + final String skeleton = DateFormat.is24HourFormat(context) ? "Hm" : "hma"; + final String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton); + final CharSequence formattedTime = DateFormat.format(pattern, time); + final Resources res = context.getResources(); + final String summary = res.getQuantityString(summaryResId, num, num, formattedTime); + final String line1 = res.getQuantityString(line1ResId, num, num, formattedTime); + final String line2 = res.getString(R.string.zen_mode_until, formattedTime); final Uri id = toCountdownConditionId(time); - return new Condition(id, caption, "", "", 0, Condition.STATE_TRUE, + return new Condition(id, summary, line1, line2, 0, Condition.STATE_TRUE, Condition.FLAG_RELEVANT_NOW); } diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java index aa6ad2048719..1e04eb45471d 100644 --- a/core/java/android/text/format/Time.java +++ b/core/java/android/text/format/Time.java @@ -48,7 +48,10 @@ import libcore.util.ZoneInfoDB; * <li>Much of the formatting / parsing assumes ASCII text and is therefore not suitable for * use with non-ASCII scripts.</li> * </ul> + * + * @deprecated Use {@link java.util.GregorianCalendar} instead. */ +@Deprecated public class Time { private static final String Y_M_D_T_H_M_S_000 = "%Y-%m-%dT%H:%M:%S.000"; private static final String Y_M_D_T_H_M_S_000_Z = "%Y-%m-%dT%H:%M:%S.000Z"; diff --git a/core/java/android/transition/ChangeBounds.java b/core/java/android/transition/ChangeBounds.java index 0da5fb6d91bc..c82587b76fe1 100644 --- a/core/java/android/transition/ChangeBounds.java +++ b/core/java/android/transition/ChangeBounds.java @@ -16,7 +16,9 @@ package android.transition; +import android.animation.AnimatorSet; import android.content.Context; +import android.content.res.TypedArray; import android.graphics.PointF; import android.animation.Animator; @@ -31,11 +33,12 @@ import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.util.AttributeSet; -import android.util.IntProperty; import android.util.Property; import android.view.View; import android.view.ViewGroup; +import com.android.internal.R; + import java.util.Map; /** @@ -43,17 +46,20 @@ import java.util.Map; * the scene change and animates those changes during the transition. * * <p>A ChangeBounds transition can be described in a resource file by using the - * tag <code>changeBounds</code>, along with the other standard + * tag <code>changeBounds</code>, using its attributes of + * {@link android.R.styleable#ChangeBounds} along with the other standard * attributes of {@link android.R.styleable#Transition}.</p> */ public class ChangeBounds extends Transition { private static final String PROPNAME_BOUNDS = "android:changeBounds:bounds"; + private static final String PROPNAME_CLIP = "android:changeBounds:clip"; private static final String PROPNAME_PARENT = "android:changeBounds:parent"; private static final String PROPNAME_WINDOW_X = "android:changeBounds:windowX"; private static final String PROPNAME_WINDOW_Y = "android:changeBounds:windowY"; private static final String[] sTransitionProperties = { PROPNAME_BOUNDS, + PROPNAME_CLIP, PROPNAME_PARENT, PROPNAME_WINDOW_X, PROPNAME_WINDOW_Y @@ -77,6 +83,83 @@ public class ChangeBounds extends Transition { } }; + private static final Property<ViewBounds, PointF> TOP_LEFT_PROPERTY = + new Property<ViewBounds, PointF>(PointF.class, "topLeft") { + @Override + public void set(ViewBounds viewBounds, PointF topLeft) { + viewBounds.setTopLeft(topLeft); + } + + @Override + public PointF get(ViewBounds viewBounds) { + return null; + } + }; + + private static final Property<ViewBounds, PointF> BOTTOM_RIGHT_PROPERTY = + new Property<ViewBounds, PointF>(PointF.class, "bottomRight") { + @Override + public void set(ViewBounds viewBounds, PointF bottomRight) { + viewBounds.setBottomRight(bottomRight); + } + + @Override + public PointF get(ViewBounds viewBounds) { + return null; + } + }; + + private static final Property<View, PointF> BOTTOM_RIGHT_ONLY_PROPERTY = + new Property<View, PointF>(PointF.class, "bottomRight") { + @Override + public void set(View view, PointF bottomRight) { + int left = view.getLeft(); + int top = view.getTop(); + int right = Math.round(bottomRight.x); + int bottom = Math.round(bottomRight.y); + view.setLeftTopRightBottom(left, top, right, bottom); + } + + @Override + public PointF get(View view) { + return null; + } + }; + + private static final Property<View, PointF> TOP_LEFT_ONLY_PROPERTY = + new Property<View, PointF>(PointF.class, "topLeft") { + @Override + public void set(View view, PointF topLeft) { + int left = Math.round(topLeft.x); + int top = Math.round(topLeft.y); + int right = view.getRight(); + int bottom = view.getBottom(); + view.setLeftTopRightBottom(left, top, right, bottom); + } + + @Override + public PointF get(View view) { + return null; + } + }; + + private static final Property<View, PointF> POSITION_PROPERTY = + new Property<View, PointF>(PointF.class, "position") { + @Override + public void set(View view, PointF topLeft) { + int left = Math.round(topLeft.x); + int top = Math.round(topLeft.y); + int right = left + view.getWidth(); + int bottom = top + view.getHeight(); + view.setLeftTopRightBottom(left, top, right, bottom); + } + + @Override + public PointF get(View view) { + return null; + } + }; + int[] tempLocation = new int[2]; boolean mResizeClip = false; boolean mReparent = false; @@ -88,6 +171,11 @@ public class ChangeBounds extends Transition { public ChangeBounds(Context context, AttributeSet attrs) { super(context, attrs); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ChangeBounds); + boolean resizeClip = a.getBoolean(R.styleable.ChangeBounds_resizeClip, false); + a.recycle(); + setResizeClip(resizeClip); } @Override @@ -95,11 +183,37 @@ public class ChangeBounds extends Transition { return sTransitionProperties; } + /** + * When <code>resizeClip</code> is true, ChangeBounds resizes the view using the clipBounds + * instead of changing the dimensions of the view during the animation. When + * <code>resizeClip</code> is false, ChangeBounds resizes the View by changing its dimensions. + * + * <p>When resizeClip is set to true, the clip bounds is modified by ChangeBounds. Therefore, + * {@link android.transition.ChangeClipBounds} is not compatible with ChangeBounds + * in this mode.</p> + * + * @param resizeClip Used to indicate whether the view bounds should be modified or the + * clip bounds should be modified by ChangeBounds. + * @see android.view.View#setClipBounds(android.graphics.Rect) + * @attr ref android.R.styleable#ChangeBounds_resizeClip + */ public void setResizeClip(boolean resizeClip) { mResizeClip = resizeClip; } /** + * Returns true when the ChangeBounds will resize by changing the clip bounds during the + * view animation or false when bounds are changed. The default value is false. + * + * @return true when the ChangeBounds will resize by changing the clip bounds during the + * view animation or false when bounds are changed. The default value is false. + * @attr ref android.R.styleable#ChangeBounds_resizeClip + */ + public boolean getResizeClip() { + return mResizeClip; + } + + /** * Setting this flag tells ChangeBounds to track the before/after parent * of every view using this transition. The flag is not enabled by * default because it requires the parent instances to be the same @@ -127,6 +241,9 @@ public class ChangeBounds extends Transition { values.values.put(PROPNAME_WINDOW_X, tempLocation[0]); values.values.put(PROPNAME_WINDOW_Y, tempLocation[1]); } + if (mResizeClip) { + values.values.put(PROPNAME_CLIP, view.getClipBounds()); + } } } @@ -170,158 +287,149 @@ public class ChangeBounds extends Transition { if (parentMatches(startParent, endParent)) { Rect startBounds = (Rect) startValues.values.get(PROPNAME_BOUNDS); Rect endBounds = (Rect) endValues.values.get(PROPNAME_BOUNDS); - int startLeft = startBounds.left; - int endLeft = endBounds.left; - int startTop = startBounds.top; - int endTop = endBounds.top; - int startRight = startBounds.right; - int endRight = endBounds.right; - int startBottom = startBounds.bottom; - int endBottom = endBounds.bottom; - int startWidth = startRight - startLeft; - int startHeight = startBottom - startTop; - int endWidth = endRight - endLeft; - int endHeight = endBottom - endTop; + final int startLeft = startBounds.left; + final int endLeft = endBounds.left; + final int startTop = startBounds.top; + final int endTop = endBounds.top; + final int startRight = startBounds.right; + final int endRight = endBounds.right; + final int startBottom = startBounds.bottom; + final int endBottom = endBounds.bottom; + final int startWidth = startRight - startLeft; + final int startHeight = startBottom - startTop; + final int endWidth = endRight - endLeft; + final int endHeight = endBottom - endTop; + Rect startClip = (Rect) startValues.values.get(PROPNAME_CLIP); + Rect endClip = (Rect) endValues.values.get(PROPNAME_CLIP); int numChanges = 0; if ((startWidth != 0 && startHeight != 0) || (endWidth != 0 && endHeight != 0)) { if (startLeft != endLeft || startTop != endTop) ++numChanges; if (startRight != endRight || startBottom != endBottom) ++numChanges; } + if ((startClip != null && !startClip.equals(endClip)) || + (startClip == null && endClip != null)) { + ++numChanges; + } if (numChanges > 0) { + Animator anim; if (!mResizeClip) { - Animator anim; - if (startWidth == endWidth && startHeight == endHeight) { - view.offsetLeftAndRight(startLeft - view.getLeft()); - view.offsetTopAndBottom(startTop - view.getTop()); - Path positionPath = getPathMotion().getPath(0, 0, endLeft - startLeft, - endTop - startTop); - anim = ObjectAnimator.ofInt(view, new HorizontalOffsetProperty(), - new VerticalOffsetProperty(), positionPath); - } else { - if (startLeft != endLeft) view.setLeft(startLeft); - if (startTop != endTop) view.setTop(startTop); - if (startRight != endRight) view.setRight(startRight); - if (startBottom != endBottom) view.setBottom(startBottom); - ObjectAnimator topLeftAnimator = null; - if (startLeft != endLeft || startTop != endTop) { + view.setLeftTopRightBottom(startLeft, startTop, startRight, startBottom); + if (numChanges == 2) { + if (startWidth == endWidth && startHeight == endHeight) { + Path topLeftPath = getPathMotion().getPath(startLeft, startTop, endLeft, + endTop); + anim = ObjectAnimator.ofObject(view, POSITION_PROPERTY, null, + topLeftPath); + } else { + final ViewBounds viewBounds = new ViewBounds(view); Path topLeftPath = getPathMotion().getPath(startLeft, startTop, endLeft, endTop); - topLeftAnimator = ObjectAnimator - .ofInt(view, "left", "top", topLeftPath); - } - ObjectAnimator bottomRightAnimator = null; - if (startRight != endRight || startBottom != endBottom) { + ObjectAnimator topLeftAnimator = ObjectAnimator + .ofObject(viewBounds, TOP_LEFT_PROPERTY, null, topLeftPath); + Path bottomRightPath = getPathMotion().getPath(startRight, startBottom, endRight, endBottom); - bottomRightAnimator = ObjectAnimator.ofInt(view, "right", "bottom", - bottomRightPath); + ObjectAnimator bottomRightAnimator = ObjectAnimator.ofObject(viewBounds, + BOTTOM_RIGHT_PROPERTY, null, bottomRightPath); + AnimatorSet set = new AnimatorSet(); + set.playTogether(topLeftAnimator, bottomRightAnimator); + anim = set; + set.addListener(new AnimatorListenerAdapter() { + // We need a strong reference to viewBounds until the + // animator ends. + private ViewBounds mViewBounds = viewBounds; + }); } - anim = TransitionUtils.mergeAnimators(topLeftAnimator, - bottomRightAnimator); - } - if (view.getParent() instanceof ViewGroup) { - final ViewGroup parent = (ViewGroup) view.getParent(); - parent.suppressLayout(true); - TransitionListener transitionListener = new TransitionListenerAdapter() { - boolean mCanceled = false; - - @Override - public void onTransitionCancel(Transition transition) { - parent.suppressLayout(false); - mCanceled = true; - } - - @Override - public void onTransitionEnd(Transition transition) { - if (!mCanceled) { - parent.suppressLayout(false); - } - } - - @Override - public void onTransitionPause(Transition transition) { - parent.suppressLayout(false); - } - - @Override - public void onTransitionResume(Transition transition) { - parent.suppressLayout(true); - } - }; - addListener(transitionListener); + } else if (startLeft != endLeft || startTop != endTop) { + Path topLeftPath = getPathMotion().getPath(startLeft, startTop, + endLeft, endTop); + anim = ObjectAnimator.ofObject(view, TOP_LEFT_ONLY_PROPERTY, null, + topLeftPath); + } else { + Path bottomRight = getPathMotion().getPath(startRight, startBottom, + endRight, endBottom); + anim = ObjectAnimator.ofObject(view, BOTTOM_RIGHT_ONLY_PROPERTY, null, + bottomRight); } - return anim; } else { - if (startWidth != endWidth) view.setRight(endLeft + - Math.max(startWidth, endWidth)); - if (startHeight != endHeight) view.setBottom(endTop + - Math.max(startHeight, endHeight)); - // TODO: don't clobber TX/TY - if (startLeft != endLeft) view.setTranslationX(startLeft - endLeft); - if (startTop != endTop) view.setTranslationY(startTop - endTop); - // Animate location with translationX/Y and size with clip bounds - float transXDelta = endLeft - startLeft; - float transYDelta = endTop - startTop; - int widthDelta = endWidth - startWidth; - int heightDelta = endHeight - startHeight; - numChanges = 0; - if (transXDelta != 0) numChanges++; - if (transYDelta != 0) numChanges++; - if (widthDelta != 0 || heightDelta != 0) numChanges++; - ObjectAnimator translationAnimator = null; - if (transXDelta != 0 || transYDelta != 0) { - Path topLeftPath = getPathMotion().getPath(0, 0, transXDelta, transYDelta); - translationAnimator = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, - View.TRANSLATION_Y, topLeftPath); + int maxWidth = Math.max(startWidth, endWidth); + int maxHeight = Math.max(startHeight, endHeight); + + view.setLeftTopRightBottom(startLeft, startTop, startLeft + maxWidth, + startTop + maxHeight); + + ObjectAnimator positionAnimator = null; + if (startLeft != endLeft || startTop != endTop) { + Path topLeftPath = getPathMotion().getPath(startLeft, startTop, endLeft, + endTop); + positionAnimator = ObjectAnimator.ofObject(view, POSITION_PROPERTY, null, + topLeftPath); + } + final Rect finalClip = endClip; + if (startClip == null) { + startClip = new Rect(0, 0, startWidth, startHeight); + } + if (endClip == null) { + endClip = new Rect(0, 0, endWidth, endHeight); } ObjectAnimator clipAnimator = null; - if (widthDelta != 0 || heightDelta != 0) { - Rect tempStartBounds = new Rect(0, 0, startWidth, startHeight); - Rect tempEndBounds = new Rect(0, 0, endWidth, endHeight); + if (!startClip.equals(endClip)) { + view.setClipBounds(startClip); clipAnimator = ObjectAnimator.ofObject(view, "clipBounds", sRectEvaluator, - tempStartBounds, tempEndBounds); - } - Animator anim = TransitionUtils.mergeAnimators(translationAnimator, - clipAnimator); - if (view.getParent() instanceof ViewGroup) { - final ViewGroup parent = (ViewGroup) view.getParent(); - parent.suppressLayout(true); - TransitionListener transitionListener = new TransitionListenerAdapter() { - boolean mCanceled = false; + startClip, endClip); + clipAnimator.addListener(new AnimatorListenerAdapter() { + private boolean mIsCanceled; @Override - public void onTransitionCancel(Transition transition) { - parent.suppressLayout(false); - mCanceled = true; + public void onAnimationCancel(Animator animation) { + mIsCanceled = true; } @Override - public void onTransitionEnd(Transition transition) { - if (!mCanceled) { - parent.suppressLayout(false); + public void onAnimationEnd(Animator animation) { + if (!mIsCanceled) { + view.setClipBounds(finalClip); + view.setLeftTopRightBottom(endLeft, endTop, endRight, + endBottom); } } + }); + } + anim = TransitionUtils.mergeAnimators(positionAnimator, + clipAnimator); + } + if (view.getParent() instanceof ViewGroup) { + final ViewGroup parent = (ViewGroup) view.getParent(); + parent.suppressLayout(true); + TransitionListener transitionListener = new TransitionListenerAdapter() { + boolean mCanceled = false; - @Override - public void onTransitionPause(Transition transition) { + @Override + public void onTransitionCancel(Transition transition) { + parent.suppressLayout(false); + mCanceled = true; + } + + @Override + public void onTransitionEnd(Transition transition) { + if (!mCanceled) { parent.suppressLayout(false); } + } + + @Override + public void onTransitionPause(Transition transition) { + parent.suppressLayout(false); + } - @Override - public void onTransitionResume(Transition transition) { - parent.suppressLayout(true); - } - }; - addListener(transitionListener); - } - anim.addListener(new AnimatorListenerAdapter() { @Override - public void onAnimationEnd(Animator animation) { - view.setClipBounds(null); + public void onTransitionResume(Transition transition) { + parent.suppressLayout(true); } - }); - return anim; + }; + addListener(transitionListener); } + return anim; } } else { int startX = (Integer) startValues.values.get(PROPNAME_WINDOW_X); @@ -357,47 +465,41 @@ public class ChangeBounds extends Transition { return null; } - private abstract static class OffsetProperty extends IntProperty<View> { - int mPreviousValue; - - public OffsetProperty(String name) { - super(name); - } - - @Override - public void setValue(View view, int value) { - int offset = value - mPreviousValue; - offsetBy(view, offset); - mPreviousValue = value; - } - - @Override - public Integer get(View object) { - return null; - } - - protected abstract void offsetBy(View view, int by); - } - - private static class HorizontalOffsetProperty extends OffsetProperty { - public HorizontalOffsetProperty() { - super("offsetLeftAndRight"); + private static class ViewBounds { + private int mLeft; + private int mTop; + private int mRight; + private int mBottom; + private boolean mIsTopLeftSet; + private boolean mIsBottomRightSet; + private View mView; + + public ViewBounds(View view) { + mView = view; } - @Override - protected void offsetBy(View view, int by) { - view.offsetLeftAndRight(by); + public void setTopLeft(PointF topLeft) { + mLeft = Math.round(topLeft.x); + mTop = Math.round(topLeft.y); + mIsTopLeftSet = true; + if (mIsBottomRightSet) { + setLeftTopRightBottom(); + } } - } - private static class VerticalOffsetProperty extends OffsetProperty { - public VerticalOffsetProperty() { - super("offsetTopAndBottom"); + public void setBottomRight(PointF bottomRight) { + mRight = Math.round(bottomRight.x); + mBottom = Math.round(bottomRight.y); + mIsBottomRightSet = true; + if (mIsTopLeftSet) { + setLeftTopRightBottom(); + } } - @Override - protected void offsetBy(View view, int by) { - view.offsetTopAndBottom(by); + private void setLeftTopRightBottom() { + mView.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom); + mIsTopLeftSet = false; + mIsBottomRightSet = false; } } } diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java index 6dede46df311..e99c2cfeedd7 100644 --- a/core/java/android/transition/Transition.java +++ b/core/java/android/transition/Transition.java @@ -1790,6 +1790,10 @@ public abstract class Transition implements Cloneable { private static boolean isValueChanged(TransitionValues oldValues, TransitionValues newValues, String key) { + if (oldValues.values.containsKey(key) != newValues.values.containsKey(key)) { + // The transition didn't care about this particular value, so we don't care, either. + return false; + } Object oldValue = oldValues.values.get(key); Object newValue = newValues.values.get(key); boolean changed; diff --git a/core/java/android/transition/TransitionUtils.java b/core/java/android/transition/TransitionUtils.java index 03423ffefaa4..49ceb3b5365e 100644 --- a/core/java/android/transition/TransitionUtils.java +++ b/core/java/android/transition/TransitionUtils.java @@ -22,8 +22,10 @@ import android.animation.TypeEvaluator; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Matrix; +import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; @@ -109,6 +111,35 @@ public class TransitionUtils { } /** + * Get a copy of bitmap of given drawable, return null if intrinsic size is zero + */ + public static Bitmap createDrawableBitmap(Drawable drawable) { + int width = drawable.getIntrinsicWidth(); + int height = drawable.getIntrinsicHeight(); + if (width <= 0 || height <= 0) { + return null; + } + float scale = Math.min(1f, ((float)MAX_IMAGE_SIZE) / (width * height)); + if (drawable instanceof BitmapDrawable && scale == 1f) { + // return same bitmap if scale down not needed + return ((BitmapDrawable) drawable).getBitmap(); + } + int bitmapWidth = (int) (width * scale); + int bitmapHeight = (int) (height * scale); + Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + Rect existingBounds = drawable.getBounds(); + int left = existingBounds.left; + int top = existingBounds.top; + int right = existingBounds.right; + int bottom = existingBounds.bottom; + drawable.setBounds(0, 0, bitmapWidth, bitmapHeight); + drawable.draw(canvas); + drawable.setBounds(left, top, right, bottom); + return bitmap; + } + + /** * Creates a Bitmap of the given view, using the Matrix matrix to transform to the local * coordinates. <code>matrix</code> will be modified during the bitmap creation. * diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java index f58291f48949..36bac31901fc 100644 --- a/core/java/android/transition/Visibility.java +++ b/core/java/android/transition/Visibility.java @@ -484,12 +484,19 @@ public abstract class Visibility extends Transition { @Override boolean areValuesChanged(TransitionValues oldValues, TransitionValues newValues) { - VisibilityInfo changeInfo = getVisibilityChangeInfo(oldValues, newValues); if (oldValues == null && newValues == null) { return false; } + if (oldValues != null && newValues != null && + newValues.values.containsKey(PROPNAME_VISIBILITY) != + oldValues.values.containsKey(PROPNAME_VISIBILITY)) { + // The transition wasn't targeted in either the start or end, so it couldn't + // have changed. + return false; + } + VisibilityInfo changeInfo = getVisibilityChangeInfo(oldValues, newValues); return changeInfo.visibilityChange && (changeInfo.startVisibility == View.VISIBLE || - changeInfo.endVisibility == View.VISIBLE); + changeInfo.endVisibility == View.VISIBLE); } /** diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java index 423e48b610a7..68f725e688bd 100644 --- a/core/java/android/util/ArraySet.java +++ b/core/java/android/util/ArraySet.java @@ -245,13 +245,20 @@ public final class ArraySet<E> implements Collection<E>, Set<E> { /** * Create a new ArraySet with the mappings from the given ArraySet. */ - public ArraySet(ArraySet set) { + public ArraySet(ArraySet<E> set) { this(); if (set != null) { addAll(set); } } + /** {@hide} */ + public ArraySet(Collection<E> set) { + this(); + if (set != null) { + addAll(set); + } + } /** * Make the array map empty. All storage is released. diff --git a/core/java/android/util/FloatMath.java b/core/java/android/util/FloatMath.java index 0ffd5bd61098..bdcf5ca2bc9e 100644 --- a/core/java/android/util/FloatMath.java +++ b/core/java/android/util/FloatMath.java @@ -21,7 +21,10 @@ package android.util; * versions of Android with a JIT, these are significantly slower than * the equivalent {@code Math} functions, which should be used in preference * to these. + * + * @deprecated Use {@link java.lang.Math} instead. */ +@Deprecated public class FloatMath { /** Prevents instantiation. */ diff --git a/core/java/android/util/IntArray.java b/core/java/android/util/IntArray.java new file mode 100644 index 000000000000..e8d394747b2a --- /dev/null +++ b/core/java/android/util/IntArray.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2014 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.util; + +import com.android.internal.util.ArrayUtils; + +import libcore.util.EmptyArray; + +/** + * Implements a growing array of int primitives. + * + * @hide + */ +public class IntArray implements Cloneable { + private static final int MIN_CAPACITY_INCREMENT = 12; + + private int[] mValues; + private int mSize; + + /** + * Creates an empty IntArray with the default initial capacity. + */ + public IntArray() { + this(10); + } + + /** + * Creates an empty IntArray with the specified initial capacity. + */ + public IntArray(int initialCapacity) { + if (initialCapacity == 0) { + mValues = EmptyArray.INT; + } else { + mValues = ArrayUtils.newUnpaddedIntArray(initialCapacity); + } + mSize = 0; + } + + /** + * Appends the specified value to the end of this array. + */ + public void add(int value) { + add(mSize, value); + } + + /** + * Inserts a value at the specified position in this array. + * + * @throws IndexOutOfBoundsException when index < 0 || index > size() + */ + public void add(int index, int value) { + if (index < 0 || index > mSize) { + throw new IndexOutOfBoundsException(); + } + + ensureCapacity(1); + + if (mSize - index != 0) { + System.arraycopy(mValues, index, mValues, index + 1, mSize - index); + } + + mValues[index] = value; + mSize++; + } + + /** + * Adds the values in the specified array to this array. + */ + public void addAll(IntArray values) { + final int count = values.mSize; + ensureCapacity(count); + + System.arraycopy(values.mValues, 0, mValues, mSize, count); + mSize += count; + } + + /** + * Ensures capacity to append at least <code>count</code> values. + */ + private void ensureCapacity(int count) { + final int currentSize = mSize; + final int minCapacity = currentSize + count; + if (minCapacity >= mValues.length) { + final int targetCap = currentSize + (currentSize < (MIN_CAPACITY_INCREMENT / 2) ? + MIN_CAPACITY_INCREMENT : currentSize >> 1); + final int newCapacity = targetCap > minCapacity ? targetCap : minCapacity; + final int[] newValues = ArrayUtils.newUnpaddedIntArray(newCapacity); + System.arraycopy(mValues, 0, newValues, 0, currentSize); + mValues = newValues; + } + } + + /** + * Removes all values from this array. + */ + public void clear() { + mSize = 0; + } + + @Override + public IntArray clone() throws CloneNotSupportedException { + final IntArray clone = (IntArray) super.clone(); + clone.mValues = mValues.clone(); + return clone; + } + + /** + * Returns the value at the specified position in this array. + */ + public int get(int index) { + if (index >= mSize) { + throw new ArrayIndexOutOfBoundsException(mSize, index); + } + return mValues[index]; + } + + /** + * Returns the index of the first occurrence of the specified value in this + * array, or -1 if this array does not contain the value. + */ + public int indexOf(int value) { + final int n = mSize; + for (int i = 0; i < n; i++) { + if (mValues[i] == value) { + return i; + } + } + return -1; + } + + /** + * Removes the value at the specified index from this array. + */ + public void remove(int index) { + if (index >= mSize) { + throw new ArrayIndexOutOfBoundsException(mSize, index); + } + System.arraycopy(mValues, index + 1, mValues, index, mSize - index - 1); + mSize--; + } + + /** + * Returns the number of values in this array. + */ + public int size() { + return mSize; + } +} diff --git a/core/java/android/util/PathParser.java b/core/java/android/util/PathParser.java index 6820f7785ec2..e5f3b2c3a5b1 100644 --- a/core/java/android/util/PathParser.java +++ b/core/java/android/util/PathParser.java @@ -34,7 +34,11 @@ public class PathParser { Path path = new Path(); PathDataNode[] nodes = createNodesFromPathData(pathData); if (nodes != null) { - PathDataNode.nodesToPath(nodes, path); + try { + PathDataNode.nodesToPath(nodes, path); + } catch (RuntimeException e) { + throw new RuntimeException("Error in parsing " + pathData, e); + } return path; } return null; @@ -128,7 +132,12 @@ public class PathParser { while (end < s.length()) { c = s.charAt(end); - if (((c - 'A') * (c - 'Z') <= 0) || (((c - 'a') * (c - 'z') <= 0))) { + // Note that 'e' or 'E' are not valid path commands, but could be + // used for floating point numbers' scientific notation. + // Therefore, when searching for next command, we should ignore 'e' + // and 'E'. + if ((((c - 'A') * (c - 'Z') <= 0) || ((c - 'a') * (c - 'z') <= 0)) + && c != 'e' && c != 'E') { return end; } end++; @@ -142,9 +151,9 @@ public class PathParser { private static class ExtractFloatResult { // We need to return the position of the next separator and whether the - // next float starts with a '-'. + // next float starts with a '-' or a '.'. int mEndPosition; - boolean mEndWithNegSign; + boolean mEndWithNegOrDot; } /** @@ -179,8 +188,8 @@ public class PathParser { s.substring(startPosition, endPosition)); } - if (result.mEndWithNegSign) { - // Keep the '-' sign with next number. + if (result.mEndWithNegOrDot) { + // Keep the '-' or '.' sign with next number. startPosition = endPosition; } else { startPosition = endPosition + 1; @@ -188,8 +197,7 @@ public class PathParser { } return Arrays.copyOf(results, count); } catch (NumberFormatException e) { - Log.e(LOGTAG, "error in parsing \"" + s + "\""); - throw e; + throw new RuntimeException("error in parsing \"" + s + "\"", e); } } @@ -201,11 +209,15 @@ public class PathParser { * the starting position of next number, whether it is ending with a '-'. */ private static void extract(String s, int start, ExtractFloatResult result) { - // Now looking for ' ', ',' or '-' from the start. + // Now looking for ' ', ',', '.' or '-' from the start. int currentIndex = start; boolean foundSeparator = false; - result.mEndWithNegSign = false; + result.mEndWithNegOrDot = false; + boolean secondDot = false; + boolean isExponential = false; for (; currentIndex < s.length(); currentIndex++) { + boolean isPrevExponential = isExponential; + isExponential = false; char currentChar = s.charAt(currentIndex); switch (currentChar) { case ' ': @@ -213,11 +225,25 @@ public class PathParser { foundSeparator = true; break; case '-': - if (currentIndex != start) { + // The negative sign following a 'e' or 'E' is not a separator. + if (currentIndex != start && !isPrevExponential) { foundSeparator = true; - result.mEndWithNegSign = true; + result.mEndWithNegOrDot = true; } break; + case '.': + if (!secondDot) { + secondDot = true; + } else { + // This is the second dot, and it is considered as a separator. + foundSeparator = true; + result.mEndWithNegOrDot = true; + } + break; + case 'e': + case 'E': + isExponential = true; + break; } if (foundSeparator) { break; diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java index 931fb8114716..74d42452503e 100644 --- a/core/java/android/util/TypedValue.java +++ b/core/java/android/util/TypedValue.java @@ -139,6 +139,17 @@ public class TypedValue { /* ------------------------------------------------------------ */ /** + * {@link #TYPE_NULL} data indicating the value was not specified. + */ + public static final int DATA_NULL_UNDEFINED = 0; + /** + * {@link #TYPE_NULL} data indicating the value was explicitly set to null. + */ + public static final int DATA_NULL_EMPTY = 1; + + /* ------------------------------------------------------------ */ + + /** * If {@link #density} is equal to this value, then the density should be * treated as the system's default density value: {@link DisplayMetrics#DENSITY_DEFAULT}. */ @@ -301,6 +312,18 @@ public class TypedValue { } /** + * Return the complex unit type for this value. For example, a dimen type + * with value 12sp will return {@link #COMPLEX_UNIT_SP}. Only use for values + * whose type is {@link #TYPE_DIMENSION}. + * + * @return The complex unit type. + */ + public int getComplexUnit() + { + return COMPLEX_UNIT_MASK & (data>>TypedValue.COMPLEX_UNIT_SHIFT); + } + + /** * Converts an unpacked complex data value holding a dimension to its final floating * point value. The two parameters <var>unit</var> and <var>value</var> * are as in {@link #TYPE_DIMENSION}. diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl index 3e7aae00af64..9fc80fcf4235 100644 --- a/core/java/android/view/IWindow.aidl +++ b/core/java/android/view/IWindow.aidl @@ -85,4 +85,9 @@ oneway interface IWindow { * is done. */ void doneAnimating(); + + /** + * Called for non-application windows when the enter animation has completed. + */ + void dispatchWindowShown(); } diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 132e25cb99fa..562d13866984 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -311,7 +311,10 @@ public class Surface implements Parcelable { * Unlike {@link #lockCanvas(Rect)} this will return a hardware-accelerated * canvas. See the <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#unsupported"> * unsupported drawing operations</a> for a list of what is and isn't - * supported in a hardware-accelerated canvas. + * supported in a hardware-accelerated canvas. It is also required to + * fully cover the surface every time {@link #lockHardwareCanvas()} is + * called as the buffer is not preserved between frames. Partial updates + * are not supported. * * @return A canvas for drawing into the surface. * diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index 1e46517013b9..00a88846a56a 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -191,7 +191,8 @@ public class ThreadedRenderer extends HardwareRenderer { final float lightX = width / 2.0f; mWidth = width; mHeight = height; - if (surfaceInsets != null && !surfaceInsets.isEmpty()) { + if (surfaceInsets != null && (surfaceInsets.left != 0 || surfaceInsets.right != 0 + || surfaceInsets.top != 0 || surfaceInsets.bottom != 0)) { mHasInsets = true; mInsetLeft = surfaceInsets.left; mInsetTop = surfaceInsets.top; @@ -255,6 +256,9 @@ public class ThreadedRenderer extends HardwareRenderer { mProfilingEnabled = wantProfiling; changed = true; } + if (changed) { + invalidateRoot(); + } return changed; } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 1ecc8d9067bc..1d09696c517f 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3109,6 +3109,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private MatchLabelForPredicate mMatchLabelForPredicate; /** + * Specifies a view before which this one is visited in accessibility traversal. + */ + private int mAccessibilityTraversalBeforeId = NO_ID; + + /** + * Specifies a view after which this one is visited in accessibility traversal. + */ + private int mAccessibilityTraversalAfterId = NO_ID; + + /** * Predicate for matching a view by its id. */ private MatchIdPredicate mMatchIdPredicate; @@ -3229,6 +3239,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners; + protected OnScrollChangeListener mOnScrollChangeListener; + /** * Listeners for attach events. */ @@ -3886,6 +3898,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, case com.android.internal.R.styleable.View_contentDescription: setContentDescription(a.getString(attr)); break; + case com.android.internal.R.styleable.View_accessibilityTraversalBefore: + setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID)); + break; + case com.android.internal.R.styleable.View_accessibilityTraversalAfter: + setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID)); + break; case com.android.internal.R.styleable.View_labelFor: setLabelFor(a.getResourceId(attr, NO_ID)); break; @@ -4606,6 +4624,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Register a callback to be invoked when the scroll position of this view + * changed. + * + * @param l The callback that will run. + * @hide Only used internally. + */ + public void setOnScrollChangeListener(OnScrollChangeListener l) { + getListenerInfo().mOnScrollChangeListener = l; + } + + /** * Register a callback to be invoked when focus of this view changed. * * @param l The callback that will run. @@ -5598,6 +5627,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (rootView == null) { rootView = this; } + View label = rootView.findLabelForView(this, mID); if (label != null) { info.setLabeledBy(label); @@ -5626,6 +5656,30 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } + if (mAccessibilityTraversalBeforeId != View.NO_ID) { + View rootView = getRootView(); + if (rootView == null) { + rootView = this; + } + View next = rootView.findViewInsideOutShouldExist(this, + mAccessibilityTraversalBeforeId); + if (next != null) { + info.setTraversalBefore(next); + } + } + + if (mAccessibilityTraversalAfterId != View.NO_ID) { + View rootView = getRootView(); + if (rootView == null) { + rootView = this; + } + View next = rootView.findViewInsideOutShouldExist(this, + mAccessibilityTraversalAfterId); + if (next != null) { + info.setTraversalAfter(next); + } + } + info.setVisibleToUser(isVisibleToUser()); info.setPackageName(mContext.getPackageName()); @@ -5877,6 +5931,21 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return true; } + /** + * Adds the clickable rectangles withing the bounds of this view. They + * may overlap. This method is intended for use only by the accessibility + * layer. + * + * @param outRects List to which to add clickable areas. + */ + void addClickableRectsForAccessibility(List<RectF> outRects) { + if (isClickable() || isLongClickable()) { + RectF bounds = new RectF(); + bounds.set(0, 0, getWidth(), getHeight()); + outRects.add(bounds); + } + } + static void offsetRects(List<RectF> rects, float offsetX, float offsetY) { final int rectCount = rects.size(); for (int i = 0; i < rectCount; i++) { @@ -6015,6 +6084,94 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Sets the id of a view before which this one is visited in accessibility traversal. + * A screen-reader must visit the content of this view before the content of the one + * it precedes. For example, if view B is set to be before view A, then a screen-reader + * will traverse the entire content of B before traversing the entire content of A, + * regardles of what traversal strategy it is using. + * <p> + * Views that do not have specified before/after relationships are traversed in order + * determined by the screen-reader. + * </p> + * <p> + * Setting that this view is before a view that is not important for accessibility + * or if this view is not important for accessibility will have no effect as the + * screen-reader is not aware of unimportant views. + * </p> + * + * @param beforeId The id of a view this one precedes in accessibility traversal. + * + * @attr ref android.R.styleable#View_accessibilityTraversalBefore + * + * @see #setImportantForAccessibility(int) + */ + @RemotableViewMethod + public void setAccessibilityTraversalBefore(int beforeId) { + if (mAccessibilityTraversalBeforeId == beforeId) { + return; + } + mAccessibilityTraversalBeforeId = beforeId; + notifyViewAccessibilityStateChangedIfNeeded( + AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + } + + /** + * Gets the id of a view before which this one is visited in accessibility traversal. + * + * @return The id of a view this one precedes in accessibility traversal if + * specified, otherwise {@link #NO_ID}. + * + * @see #setAccessibilityTraversalBefore(int) + */ + public int getAccessibilityTraversalBefore() { + return mAccessibilityTraversalBeforeId; + } + + /** + * Sets the id of a view after which this one is visited in accessibility traversal. + * A screen-reader must visit the content of the other view before the content of this + * one. For example, if view B is set to be after view A, then a screen-reader + * will traverse the entire content of A before traversing the entire content of B, + * regardles of what traversal strategy it is using. + * <p> + * Views that do not have specified before/after relationships are traversed in order + * determined by the screen-reader. + * </p> + * <p> + * Setting that this view is after a view that is not important for accessibility + * or if this view is not important for accessibility will have no effect as the + * screen-reader is not aware of unimportant views. + * </p> + * + * @param afterId The id of a view this one succedees in accessibility traversal. + * + * @attr ref android.R.styleable#View_accessibilityTraversalAfter + * + * @see #setImportantForAccessibility(int) + */ + @RemotableViewMethod + public void setAccessibilityTraversalAfter(int afterId) { + if (mAccessibilityTraversalAfterId == afterId) { + return; + } + mAccessibilityTraversalAfterId = afterId; + notifyViewAccessibilityStateChangedIfNeeded( + AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + } + + /** + * Gets the id of a view after which this one is visited in accessibility traversal. + * + * @return The id of a view this one succeedes in accessibility traversal if + * specified, otherwise {@link #NO_ID}. + * + * @see #setAccessibilityTraversalAfter(int) + */ + public int getAccessibilityTraversalAfter() { + return mAccessibilityTraversalAfterId; + } + + /** * Gets the id of a view for which this view serves as a label for * accessibility purposes. * @@ -6033,11 +6190,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @RemotableViewMethod public void setLabelFor(int id) { + if (mLabelForId == id) { + return; + } mLabelForId = id; if (mLabelForId != View.NO_ID && mID == View.NO_ID) { mID = generateViewId(); } + notifyViewAccessibilityStateChangedIfNeeded( + AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); } /** @@ -9779,6 +9941,29 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (ai != null) { ai.mViewScrollChanged = true; } + + if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) { + mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt); + } + } + + /** + * Interface definition for a callback to be invoked when the scroll + * position of a view changes. + * + * @hide Only used internally. + */ + public interface OnScrollChangeListener { + /** + * Called when the scroll position of a view changes. + * + * @param v The view whose scroll position has changed. + * @param scrollX Current horizontal scroll origin. + * @param scrollY Current vertical scroll origin. + * @param oldScrollX Previous horizontal scroll origin. + * @param oldScrollY Previous vertical scroll origin. + */ + void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY); } /** @@ -14047,7 +14232,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } else { draw(canvas); } - drawAccessibilityFocus(canvas); } } finally { renderNode.end(canvas); @@ -14342,7 +14526,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } else { draw(canvas); } - drawAccessibilityFocus(canvas); canvas.restoreToCount(restoreCount); canvas.setBitmap(null); @@ -14417,7 +14600,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } else { draw(canvas); } - drawAccessibilityFocus(canvas); mPrivateFlags = flags; @@ -15015,13 +15197,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { mPrivateFlags &= ~PFLAG_DIRTY_MASK; dispatchDraw(canvas); - if (mOverlay != null && !mOverlay.isEmpty()) { - mOverlay.getOverlayView().draw(canvas); - } } else { draw(canvas); } - drawAccessibilityFocus(canvas); } else { mPrivateFlags &= ~PFLAG_DIRTY_MASK; ((HardwareCanvas) canvas).drawRenderNode(renderNode, null, flags); @@ -15273,50 +15451,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * Draws the accessibility focus rect onto the specified canvas. - * - * @param canvas Canvas on which to draw the focus rect - */ - private void drawAccessibilityFocus(Canvas canvas) { - if (mAttachInfo == null) { - return; - } - - final Rect bounds = mAttachInfo.mTmpInvalRect; - final ViewRootImpl viewRoot = getViewRootImpl(); - if (viewRoot == null || viewRoot.getAccessibilityFocusedHost() != this) { - return; - } - - final AccessibilityManager manager = AccessibilityManager.getInstance(mContext); - if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) { - return; - } - - final Drawable drawable = viewRoot.getAccessibilityFocusedDrawable(); - if (drawable == null) { - return; - } - - final AccessibilityNodeInfo virtualView = viewRoot.getAccessibilityFocusedVirtualView(); - if (virtualView != null) { - virtualView.getBoundsInScreen(bounds); - final int[] offset = mAttachInfo.mTmpLocation; - getLocationOnScreen(offset); - bounds.offset(-offset[0], -offset[1]); - } else { - bounds.set(0, 0, mRight - mLeft, mBottom - mTop); - } - - canvas.save(); - canvas.translate(mScrollX, mScrollY); - canvas.clipRect(bounds, Region.Op.REPLACE); - drawable.setBounds(bounds); - drawable.draw(canvas); - canvas.restore(); - } - - /** * Draws the background onto the specified canvas. * * @param canvas Canvas on which to draw the background @@ -15676,7 +15810,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, sizeChange(newWidth, newHeight, oldWidth, oldHeight); } - if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) { + if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) { // If we are visible, force the DRAWN bit to on so that // this invalidate will go through (at least to our parent). // This is because someone may have invalidated this view @@ -15699,6 +15833,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return changed; } + /** + * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}. + * @hide + */ + public void setLeftTopRightBottom(int left, int top, int right, int bottom) { + setFrame(left, top, right, bottom); + } + private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) { onSizeChanged(newWidth, newHeight, oldWidth, oldHeight); if (mOverlay != null) { @@ -16330,6 +16472,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (tintInfo.mHasTintMode) { mBackground.setTintMode(tintInfo.mTintMode); } + + // The drawable (or one of its children) may not have been + // stateful before applying the tint, so let's try again. + if (mBackground.isStateful()) { + mBackground.setState(getDrawableState()); + } } } } @@ -16617,8 +16765,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidate(true); refreshDrawableState(); dispatchSetSelected(selected); - notifyViewAccessibilityStateChangedIfNeeded( - AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + if (selected) { + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); + } else { + notifyViewAccessibilityStateChangedIfNeeded( + AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + } } } @@ -17414,17 +17566,22 @@ public class View implements Drawable.Callback, KeyEvent.Callback, long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL; if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2); - if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT || - widthMeasureSpec != mOldWidthMeasureSpec || - heightMeasureSpec != mOldHeightMeasureSpec) { + final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT; + final boolean isExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY && + MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY; + final boolean matchingSize = isExactly && + getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec) && + getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec); + if (forceLayout || !matchingSize && + (widthMeasureSpec != mOldWidthMeasureSpec || + heightMeasureSpec != mOldHeightMeasureSpec)) { // first clears the measured dimension flag mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET; resolveRtlPropertiesIfNeeded(); - int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 : - mMeasureCache.indexOfKey(key); + int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key); if (cacheIndex < 0 || sIgnoreMeasureCache) { // measure ourselves, this should set the measured dimension flag back onMeasure(widthMeasureSpec, heightMeasureSpec); diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index 12a49d518fc1..50e64c6ea6fb 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -1005,12 +1005,21 @@ public class ViewDebug { return fields; } - final ArrayList<Field> foundFields = new ArrayList<Field>(); - fields = klass.getDeclaredFields(); + final ArrayList<Field> declaredFields = new ArrayList(); + klass.getDeclaredFieldsUnchecked(false, declaredFields); - int count = fields.length; + final ArrayList<Field> foundFields = new ArrayList<Field>(); + final int count = declaredFields.size(); for (int i = 0; i < count; i++) { - final Field field = fields[i]; + final Field field = declaredFields.get(i); + + // Ensure the field type can be resolved. + try { + field.getType(); + } catch (NoClassDefFoundError e) { + continue; + } + if (field.isAnnotationPresent(ExportedProperty.class)) { field.setAccessible(true); foundFields.add(field); @@ -1039,12 +1048,22 @@ public class ViewDebug { return methods; } - final ArrayList<Method> foundMethods = new ArrayList<Method>(); - methods = klass.getDeclaredMethods(); + final ArrayList<Method> declaredMethods = new ArrayList(); + klass.getDeclaredMethodsUnchecked(false, declaredMethods); - int count = methods.length; + final ArrayList<Method> foundMethods = new ArrayList<Method>(); + final int count = declaredMethods.size(); for (int i = 0; i < count; i++) { - final Method method = methods[i]; + final Method method = declaredMethods.get(i); + + // Ensure the method return and parameter types can be resolved. + try { + method.getReturnType(); + method.getParameterTypes(); + } catch (NoClassDefFoundError e) { + continue; + } + if (method.getParameterTypes().length == 0 && method.isAnnotationPresent(ExportedProperty.class) && method.getReturnType() != Void.class) { diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 4116b6b5b546..654a8edea2fe 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -51,8 +51,10 @@ import com.android.internal.util.Predicate; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; @@ -468,6 +470,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager @ViewDebug.ExportedProperty(category = "layout") private int mChildCountWithTransientState = 0; + // Iterator over the children in decreasing Z order (top children first). + private OrderedChildIterator mOrderedChildIterator; + /** * Currently registered axes for nested scrolling. Flag set consisting of * {@link #SCROLL_AXIS_HORIZONTAL} {@link #SCROLL_AXIS_VERTICAL} or {@link #SCROLL_AXIS_NONE} @@ -817,19 +822,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager return false; } - // Check whether any clickable siblings cover the child - // view and if so keep track of the intersections. Also - // respect Z ordering when iterating over children. - ArrayList<View> orderedList = buildOrderedChildList(); - final boolean useCustomOrder = orderedList == null - && isChildrenDrawingOrderEnabled(); - - final int childCount = mChildrenCount; - for (int i = childCount - 1; i >= 0; i--) { - final int childIndex = useCustomOrder - ? getChildDrawingOrder(childCount, i) : i; - final View sibling = (orderedList == null) - ? mChildren[childIndex] : orderedList.get(childIndex); + Iterator<View> iterator = obtainOrderedChildIterator(); + while (iterator.hasNext()) { + View sibling = iterator.next(); // We care only about siblings over the child. if (sibling == child) { @@ -837,12 +832,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } // Ignore invisible views as they are not interactive. - if (sibling.getVisibility() != View.VISIBLE) { - continue; - } - - // If sibling is not interactive we do not care. - if (!sibling.isClickable() && !sibling.isLongClickable()) { + if (!isVisible(sibling)) { continue; } @@ -850,28 +840,37 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager RectF siblingBounds = mAttachInfo.mTmpTransformRect1; siblingBounds.set(0, 0, sibling.getWidth(), sibling.getHeight()); - // Take into account the sibling transformation matrix. - if (!sibling.hasIdentityMatrix()) { - sibling.getMatrix().mapRect(siblingBounds); - } - - // Offset the sibling to our coordinates. - final int siblingDx = sibling.mLeft - mScrollX; - final int siblingDy = sibling.mTop - mScrollY; - siblingBounds.offset(siblingDx, siblingDy); + // Translate the sibling bounds to our coordinates. + offsetChildRectToMyCoords(siblingBounds, sibling); // Compute the intersection between the child and the sibling. if (siblingBounds.intersect(bounds)) { - // If an interactive sibling completely covers the child, done. - if (siblingBounds.equals(bounds)) { - return false; + List<RectF> clickableRects = new ArrayList<>(); + sibling.addClickableRectsForAccessibility(clickableRects); + + final int clickableRectCount = clickableRects.size(); + for (int j = 0; j < clickableRectCount; j++) { + RectF clickableRect = clickableRects.get(j); + + // Translate the clickable rect to our coordinates. + offsetChildRectToMyCoords(clickableRect, sibling); + + // Compute the intersection between the child and the clickable rects. + if (clickableRect.intersect(bounds)) { + // If a clickable rect completely covers the child, done. + if (clickableRect.equals(bounds)) { + releaseOrderedChildIterator(); + return false; + } + // Keep track of the intersection rectangle. + intersections.add(clickableRect); + } } - // Keep track of the intersection rectangle. - RectF intersection = new RectF(siblingBounds); - intersections.add(intersection); } } + releaseOrderedChildIterator(); + if (mParent instanceof ViewGroup) { ViewGroup parentGroup = (ViewGroup) mParent; return parentGroup.translateBoundsAndIntersectionsInWindowCoordinates( @@ -881,6 +880,94 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager return true; } + @Override + void addClickableRectsForAccessibility(List<RectF> outRects) { + int sizeBefore = outRects.size(); + + super.addClickableRectsForAccessibility(outRects); + + // If we added ourselves, then no need to visit children. + if (outRects.size() > sizeBefore) { + return; + } + + Iterator<View> iterator = obtainOrderedChildIterator(); + while (iterator.hasNext()) { + View child = iterator.next(); + + // Cannot click on an invisible view. + if (!isVisible(child)) { + continue; + } + + sizeBefore = outRects.size(); + + // Add clickable rects in the child bounds. + child.addClickableRectsForAccessibility(outRects); + + // Offset the clickable rects for out children to our coordinates. + final int sizeAfter = outRects.size(); + for (int j = sizeBefore; j < sizeAfter; j++) { + RectF rect = outRects.get(j); + + // Translate the clickable rect to our coordinates. + offsetChildRectToMyCoords(rect, child); + + // If a clickable rect fills the parent, done. + if ((int) rect.left == 0 && (int) rect.top == 0 + && (int) rect.right == mRight && (int) rect.bottom == mBottom) { + releaseOrderedChildIterator(); + return; + } + } + } + + releaseOrderedChildIterator(); + } + + private void offsetChildRectToMyCoords(RectF rect, View child) { + if (!child.hasIdentityMatrix()) { + child.getMatrix().mapRect(rect); + } + final int childDx = child.mLeft - mScrollX; + final int childDy = child.mTop - mScrollY; + rect.offset(childDx, childDy); + } + + private static boolean isVisible(View view) { + return (view.getAlpha() > 0 && view.getTransitionAlpha() > 0 && + view.getVisibility() == VISIBLE); + } + + /** + * Obtains the iterator to traverse the children in a descending Z order. + * Only one party can use the iterator at any given time and you cannot + * modify the children while using this iterator. Acquisition if already + * obtained is an error. + * + * @return The child iterator. + */ + OrderedChildIterator obtainOrderedChildIterator() { + if (mOrderedChildIterator == null) { + mOrderedChildIterator = new OrderedChildIterator(); + } else if (mOrderedChildIterator.isInitialized()) { + throw new IllegalStateException("Already obtained"); + } + mOrderedChildIterator.initialize(); + return mOrderedChildIterator; + } + + /** + * Releases the iterator to traverse the children in a descending Z order. + * Release if not obtained is an error. + */ + void releaseOrderedChildIterator() { + if (mOrderedChildIterator == null || !mOrderedChildIterator.isInitialized()) { + throw new IllegalStateException("Not obtained"); + } + mOrderedChildIterator.release(); + } + /** * Called when a child view has changed whether or not it is tracking transient state. */ @@ -3293,7 +3380,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager /** * Populates (and returns) mPreSortedChildren with a pre-ordered list of the View's children, - * sorted first by Z, then by child drawing order (if applicable). + * sorted first by Z, then by child drawing order (if applicable). This list must be cleared + * after use to avoid leaking child Views. * * Uses a stable, insertion sort which is commonly O(n) for ViewGroups with very few elevated * children. @@ -3668,6 +3756,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * @see #generateDefaultLayoutParams() */ public void addView(View child, int index) { + if (child == null) { + throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup"); + } LayoutParams params = child.getLayoutParams(); if (params == null) { params = generateDefaultLayoutParams(); @@ -3725,6 +3816,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager System.out.println(this + " addView"); } + if (child == null) { + throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup"); + } + // addViewInner() will call child.requestLayout() when setting the new LayoutParams // therefore, we call requestLayout() on ourselves before, so that the child's request // will be blocked at our level @@ -3852,6 +3947,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager */ protected boolean addViewInLayout(View child, int index, LayoutParams params, boolean preventRequestLayout) { + if (child == null) { + throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup"); + } child.mParent = null; addViewInner(child, index, params, preventRequestLayout); child.mPrivateFlags = (child.mPrivateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN; @@ -4065,9 +4163,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * {@link #dispatchDraw(android.graphics.Canvas)} or any related method.</p> */ public void removeView(View view) { - removeViewInternal(view); - requestLayout(); - invalidate(true); + if (removeViewInternal(view)) { + requestLayout(); + invalidate(true); + } } /** @@ -4130,11 +4229,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager invalidate(true); } - private void removeViewInternal(View view) { + private boolean removeViewInternal(View view) { final int index = indexOfChild(view); if (index >= 0) { removeViewInternal(index, view); + return true; } + return false; } private void removeViewInternal(int index, View view) { @@ -4149,9 +4250,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager clearChildFocus = true; } - if (view.isAccessibilityFocused()) { - view.clearAccessibilityFocus(); - } + view.clearAccessibilityFocus(); cancelTouchTarget(view); cancelHoverTarget(view); @@ -4244,9 +4343,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager clearChildFocus = true; } - if (view.isAccessibilityFocused()) { - view.clearAccessibilityFocus(); - } + view.clearAccessibilityFocus(); cancelTouchTarget(view); cancelHoverTarget(view); @@ -4331,9 +4428,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager clearChildFocus = true; } - if (view.isAccessibilityFocused()) { - view.clearAccessibilityFocus(); - } + view.clearAccessibilityFocus(); cancelTouchTarget(view); cancelHoverTarget(view); @@ -6488,7 +6583,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager */ public static class MarginLayoutParams extends ViewGroup.LayoutParams { /** - * The left margin in pixels of the child. + * The left margin in pixels of the child. Margin values should be positive. * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value * to this field. */ @@ -6496,7 +6591,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager public int leftMargin; /** - * The top margin in pixels of the child. + * The top margin in pixels of the child. Margin values should be positive. * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value * to this field. */ @@ -6504,7 +6599,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager public int topMargin; /** - * The right margin in pixels of the child. + * The right margin in pixels of the child. Margin values should be positive. * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value * to this field. */ @@ -6512,7 +6607,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager public int rightMargin; /** - * The bottom margin in pixels of the child. + * The bottom margin in pixels of the child. Margin values should be positive. * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value * to this field. */ @@ -6520,7 +6615,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager public int bottomMargin; /** - * The start margin in pixels of the child. + * The start margin in pixels of the child. Margin values should be positive. * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value * to this field. */ @@ -6528,7 +6623,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager private int startMargin = DEFAULT_MARGIN_RELATIVE; /** - * The end margin in pixels of the child. + * The end margin in pixels of the child. Margin values should be positive. * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value * to this field. */ @@ -6709,6 +6804,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * Sets the margins, in pixels. A call to {@link android.view.View#requestLayout()} needs * to be done so that the new margins are taken into account. Left and right margins may be * overriden by {@link android.view.View#requestLayout()} depending on layout direction. + * Margin values should be positive. * * @param left the left margin size * @param top the top margin size @@ -6738,7 +6834,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * Sets the relative margins, in pixels. A call to {@link android.view.View#requestLayout()} * needs to be done so that the new relative margins are taken into account. Left and right * margins may be overriden by {@link android.view.View#requestLayout()} depending on layout - * direction. + * direction. Margin values should be positive. * * @param start the start margin size * @param top the top margin size @@ -6761,7 +6857,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } /** - * Sets the relative start margin. + * Sets the relative start margin. Margin values should be positive. * * @param start the start margin size * @@ -6794,7 +6890,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } /** - * Sets the relative end margin. + * Sets the relative end margin. Margin values should be positive. * * @param end the end margin size * @@ -7281,4 +7377,57 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager canvas.drawLines(sDebugLines, paint); } + + private final class OrderedChildIterator implements Iterator<View> { + private List<View> mOrderedChildList; + private boolean mUseCustomOrder; + private int mCurrentIndex; + private boolean mInitialized; + + public void initialize() { + mOrderedChildList = buildOrderedChildList(); + mUseCustomOrder = (mOrderedChildList == null) + && isChildrenDrawingOrderEnabled(); + mCurrentIndex = mChildrenCount - 1; + mInitialized = true; + } + + public void release() { + if (mOrderedChildList != null) { + mOrderedChildList.clear(); + } + mUseCustomOrder = false; + mCurrentIndex = 0; + mInitialized = false; + } + + public boolean isInitialized() { + return mInitialized; + } + + @Override + public boolean hasNext() { + return (mCurrentIndex >= 0); + } + + @Override + public View next() { + if (!hasNext()) { + throw new NoSuchElementException("No such element"); + } + return getChild(mCurrentIndex--); + } + + private View getChild(int index) { + final int childIndex = mUseCustomOrder + ? getChildDrawingOrder(mChildrenCount, index) : index; + return (mOrderedChildList == null) + ? mChildren[childIndex] : mOrderedChildList.get(childIndex); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 81fc96619128..f0d52528807d 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -727,7 +727,10 @@ public final class ViewRootImpl implements ViewParent, mAttachInfo.mHardwareRenderer.destroy(); } - final boolean translucent = attrs.format != PixelFormat.OPAQUE; + final Rect insets = attrs.surfaceInsets; + final boolean hasSurfaceInsets = insets.left == 0 || insets.right == 0 + || insets.top == 0 || insets.bottom == 0; + final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets; mAttachInfo.mHardwareRenderer = HardwareRenderer.create(mContext, translucent); if (mAttachInfo.mHardwareRenderer != null) { mAttachInfo.mHardwareRenderer.setName(attrs.getTitle().toString()); @@ -2255,6 +2258,7 @@ public final class ViewRootImpl implements ViewParent, canvas.drawHardwareLayer(mResizeBuffer, mHardwareXOffset, mHardwareYOffset, mResizePaint); } + drawAccessibilityFocusedDrawableIfNeeded(canvas); } /** @@ -2474,18 +2478,38 @@ public final class ViewRootImpl implements ViewParent, dirty.offset(surfaceInsets.left, surfaceInsets.right); } - if (!dirty.isEmpty() || mIsAnimating) { + boolean accessibilityFocusDirty = false; + final Drawable drawable = mAttachInfo.mAccessibilityFocusDrawable; + if (drawable != null) { + final Rect bounds = mAttachInfo.mTmpInvalRect; + final boolean hasFocus = getAccessibilityFocusedRect(bounds); + if (!hasFocus) { + bounds.setEmpty(); + } + if (!bounds.equals(drawable.getBounds())) { + accessibilityFocusDirty = true; + } + } + + if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) { if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) { + // If accessibility focus moved, always invalidate the root. + boolean invalidateRoot = accessibilityFocusDirty; + // Draw with hardware renderer. mIsAnimating = false; - boolean invalidateRoot = false; + if (mHardwareYOffset != yOffset || mHardwareXOffset != xOffset) { mHardwareYOffset = yOffset; mHardwareXOffset = xOffset; - mAttachInfo.mHardwareRenderer.invalidateRoot(); + invalidateRoot = true; } mResizeAlpha = resizeAlpha; + if (invalidateRoot) { + mAttachInfo.mHardwareRenderer.invalidateRoot(); + } + dirty.setEmpty(); mBlockResizeBuffer = false; @@ -2604,6 +2628,8 @@ public final class ViewRootImpl implements ViewParent, attachInfo.mSetIgnoreDirtyState = false; mView.draw(canvas); + + drawAccessibilityFocusedDrawableIfNeeded(canvas); } finally { if (!attachInfo.mSetIgnoreDirtyState) { // Only clear the flag if it was not set during the mView.draw() call @@ -2627,7 +2653,56 @@ public final class ViewRootImpl implements ViewParent, return true; } - Drawable getAccessibilityFocusedDrawable() { + /** + * We want to draw a highlight around the current accessibility focused. + * Since adding a style for all possible view is not a viable option we + * have this specialized drawing method. + * + * Note: We are doing this here to be able to draw the highlight for + * virtual views in addition to real ones. + * + * @param canvas The canvas on which to draw. + */ + private void drawAccessibilityFocusedDrawableIfNeeded(Canvas canvas) { + final Rect bounds = mAttachInfo.mTmpInvalRect; + if (getAccessibilityFocusedRect(bounds)) { + final Drawable drawable = getAccessibilityFocusedDrawable(); + if (drawable != null) { + drawable.setBounds(bounds); + drawable.draw(canvas); + } + } else if (mAttachInfo.mAccessibilityFocusDrawable != null) { + mAttachInfo.mAccessibilityFocusDrawable.setBounds(0, 0, 0, 0); + } + } + + private boolean getAccessibilityFocusedRect(Rect bounds) { + final AccessibilityManager manager = AccessibilityManager.getInstance(mView.mContext); + if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) { + return false; + } + + final View host = mAccessibilityFocusedHost; + if (host == null || host.mAttachInfo == null) { + return false; + } + + final AccessibilityNodeProvider provider = host.getAccessibilityNodeProvider(); + if (provider == null) { + host.getBoundsOnScreen(bounds); + } else if (mAccessibilityFocusedVirtualView != null) { + mAccessibilityFocusedVirtualView.getBoundsInScreen(bounds); + } else { + return false; + } + + final AttachInfo attachInfo = mAttachInfo; + bounds.offset(-attachInfo.mWindowLeft, -attachInfo.mWindowTop); + bounds.intersect(0, 0, attachInfo.mViewRootImpl.mWidth, attachInfo.mViewRootImpl.mHeight); + return !bounds.isEmpty(); + } + + private Drawable getAccessibilityFocusedDrawable() { // Lazily load the accessibility focus drawable. if (mAttachInfo.mAccessibilityFocusDrawable == null) { final TypedValue value = new TypedValue(); @@ -3014,6 +3089,7 @@ public final class ViewRootImpl implements ViewParent, private final static int MSG_INVALIDATE_WORLD = 23; private final static int MSG_WINDOW_MOVED = 24; private final static int MSG_SYNTHESIZE_INPUT_EVENT = 25; + private final static int MSG_DISPATCH_WINDOW_SHOWN = 26; final class ViewRootHandler extends Handler { @Override @@ -3063,6 +3139,8 @@ public final class ViewRootImpl implements ViewParent, return "MSG_WINDOW_MOVED"; case MSG_SYNTHESIZE_INPUT_EVENT: return "MSG_SYNTHESIZE_INPUT_EVENT"; + case MSG_DISPATCH_WINDOW_SHOWN: + return "MSG_DISPATCH_WINDOW_SHOWN"; } return super.getMessageName(message); } @@ -3291,6 +3369,9 @@ public final class ViewRootImpl implements ViewParent, invalidateWorld(mView); } } break; + case MSG_DISPATCH_WINDOW_SHOWN: { + handleDispatchWindowShown(); + } } } } @@ -5137,6 +5218,10 @@ public final class ViewRootImpl implements ViewParent, } } + public void handleDispatchWindowShown() { + mAttachInfo.mTreeObserver.dispatchOnWindowShown(); + } + public void getLastTouchPoint(Point outLocation) { outLocation.x = (int) mLastTouchPoint.x; outLocation.y = (int) mLastTouchPoint.y; @@ -5997,6 +6082,10 @@ public final class ViewRootImpl implements ViewParent, mHandler.sendMessage(msg); } + public void dispatchWindowShown() { + mHandler.sendEmptyMessage(MSG_DISPATCH_WINDOW_SHOWN); + } + public void dispatchCloseSystemDialogs(String reason) { Message msg = Message.obtain(); msg.what = MSG_CLOSE_SYSTEM_DIALOGS; @@ -6507,6 +6596,14 @@ public final class ViewRootImpl implements ViewParent, viewAncestor.dispatchDoneAnimating(); } } + + @Override + public void dispatchWindowShown() { + final ViewRootImpl viewAncestor = mViewAncestor.get(); + if (viewAncestor != null) { + viewAncestor.dispatchWindowShown(); + } + } } public static final class CalledFromWrongThreadException extends AndroidRuntimeException { diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java index a9444b44760a..b85fec8a0c08 100644 --- a/core/java/android/view/ViewTreeObserver.java +++ b/core/java/android/view/ViewTreeObserver.java @@ -44,10 +44,15 @@ public final class ViewTreeObserver { private CopyOnWriteArray<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners; private CopyOnWriteArray<OnScrollChangedListener> mOnScrollChangedListeners; private CopyOnWriteArray<OnPreDrawListener> mOnPreDrawListeners; + private CopyOnWriteArray<OnWindowShownListener> mOnWindowShownListeners; // These listeners cannot be mutated during dispatch private ArrayList<OnDrawListener> mOnDrawListeners; + /** Remains false until #dispatchOnWindowShown() is called. If a listener registers after + * that the listener will be immediately called. */ + private boolean mWindowShown; + private boolean mAlive = true; /** @@ -174,6 +179,19 @@ public final class ViewTreeObserver { } /** + * Interface definition for a callback noting when a system window has been displayed. + * This is only used for non-Activity windows. Activity windows can use + * Activity.onEnterAnimationComplete() to get the same signal. + * @hide + */ + public interface OnWindowShownListener { + /** + * Callback method to be invoked when a non-activity window is fully shown. + */ + void onWindowShown(); + } + + /** * Parameters used with OnComputeInternalInsetsListener. * * We are not yet ready to commit to this API and support it, so @@ -375,6 +393,14 @@ public final class ViewTreeObserver { } } + if (observer.mOnWindowShownListeners != null) { + if (mOnWindowShownListeners != null) { + mOnWindowShownListeners.addAll(observer.mOnWindowShownListeners); + } else { + mOnWindowShownListeners = observer.mOnWindowShownListeners; + } + } + observer.kill(); } @@ -568,6 +594,45 @@ public final class ViewTreeObserver { } /** + * Register a callback to be invoked when the view tree window has been shown + * + * @param listener The callback to add + * + * @throws IllegalStateException If {@link #isAlive()} returns false + * @hide + */ + public void addOnWindowShownListener(OnWindowShownListener listener) { + checkIsAlive(); + + if (mOnWindowShownListeners == null) { + mOnWindowShownListeners = new CopyOnWriteArray<OnWindowShownListener>(); + } + + mOnWindowShownListeners.add(listener); + if (mWindowShown) { + listener.onWindowShown(); + } + } + + /** + * Remove a previously installed window shown callback + * + * @param victim The callback to remove + * + * @throws IllegalStateException If {@link #isAlive()} returns false + * + * @see #addOnWindowShownListener(OnWindowShownListener) + * @hide + */ + public void removeOnWindowShownListener(OnWindowShownListener victim) { + checkIsAlive(); + if (mOnWindowShownListeners == null) { + return; + } + mOnWindowShownListeners.remove(victim); + } + + /** * <p>Register a callback to be invoked when the view tree is about to be drawn.</p> * <p><strong>Note:</strong> this method <strong>cannot</strong> be invoked from * {@link android.view.ViewTreeObserver.OnDrawListener#onDraw()}.</p> @@ -854,6 +919,27 @@ public final class ViewTreeObserver { } /** + * Notifies registered listeners that the window is now shown + * @hide + */ + @SuppressWarnings("unchecked") + public final void dispatchOnWindowShown() { + mWindowShown = true; + final CopyOnWriteArray<OnWindowShownListener> listeners = mOnWindowShownListeners; + if (listeners != null && listeners.size() > 0) { + CopyOnWriteArray.Access<OnWindowShownListener> access = listeners.start(); + try { + int count = access.size(); + for (int i = 0; i < count; i++) { + access.get(i).onWindowShown(); + } + } finally { + listeners.end(); + } + } + } + + /** * Notifies registered listeners that the drawing pass is about to start. */ public final void dispatchOnDraw() { diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 63ab7d252237..0076abff2f09 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -24,7 +24,6 @@ import android.content.res.TypedArray; import android.graphics.PixelFormat; import android.graphics.drawable.Drawable; import android.media.session.MediaController; -import android.media.session.MediaSession; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; @@ -801,9 +800,6 @@ public abstract class Window { public void setFlags(int flags, int mask) { final WindowManager.LayoutParams attrs = getAttributes(); attrs.flags = (attrs.flags&~mask) | (flags&mask); - if ((mask&WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0) { - attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY; - } mForcedWindowFlags |= mask; dispatchWindowAttributesChanged(attrs); } @@ -817,6 +813,15 @@ public abstract class Window { /** * {@hide} */ + protected void setNeedsMenuKey(int value) { + final WindowManager.LayoutParams attrs = getAttributes(); + attrs.needsMenuKey = value; + dispatchWindowAttributesChanged(attrs); + } + + /** + * {@hide} + */ protected void dispatchWindowAttributesChanged(WindowManager.LayoutParams attrs) { if (mCallback != null) { mCallback.onWindowAttributesChanged(attrs); @@ -1069,17 +1074,36 @@ public abstract class Window { public abstract void onConfigurationChanged(Configuration newConfig); /** + * Sets the window elevation. + * + * @param elevation The window elevation. + * @see View#setElevation(float) + * @see android.R.styleable#Window_windowElevation + */ + public void setElevation(float elevation) {} + + /** + * Sets whether window content should be clipped to the outline of the + * window background. + * + * @param clipToOutline Whether window content should be clipped to the + * outline of the window background. + * @see View#setClipToOutline(boolean) + * @see android.R.styleable#Window_windowClipToOutline + */ + public void setClipToOutline(boolean clipToOutline) {} + + /** * Change the background of this window to a Drawable resource. Setting the * background to null will make the window be opaque. To make the window * transparent, you can use an empty drawable (for instance a ColorDrawable * with the color 0 or the system drawable android:drawable/empty.) * - * @param resid The resource identifier of a drawable resource which will be - * installed as the new background. + * @param resId The resource identifier of a drawable resource which will + * be installed as the new background. */ - public void setBackgroundDrawableResource(int resid) - { - setBackgroundDrawable(mContext.getDrawable(resid)); + public void setBackgroundDrawableResource(int resId) { + setBackgroundDrawable(mContext.getDrawable(resId)); } /** @@ -1125,31 +1149,31 @@ public abstract class Window { * Set an explicit Drawable value for feature of this window. You must * have called requestFeature(featureId) before calling this function. * - * @param featureId The desired drawable feature to change. - * Features are constants defined by Window. + * @param featureId The desired drawable feature to change. Features are + * constants defined by Window. * @param drawable A Drawable object to display. */ public abstract void setFeatureDrawable(int featureId, Drawable drawable); /** - * Set a custom alpha value for the given drawale feature, controlling how + * Set a custom alpha value for the given drawable feature, controlling how * much the background is visible through it. * - * @param featureId The desired drawable feature to change. - * Features are constants defined by Window. + * @param featureId The desired drawable feature to change. Features are + * constants defined by Window. * @param alpha The alpha amount, 0 is completely transparent and 255 is * completely opaque. */ public abstract void setFeatureDrawableAlpha(int featureId, int alpha); /** - * Set the integer value for a feature. The range of the value depends on - * the feature being set. For FEATURE_PROGRESSS, it should go from 0 to - * 10000. At 10000 the progress is complete and the indicator hidden. + * Set the integer value for a feature. The range of the value depends on + * the feature being set. For {@link #FEATURE_PROGRESS}, it should go from + * 0 to 10000. At 10000 the progress is complete and the indicator hidden. * - * @param featureId The desired feature to change. - * Features are constants defined by Window. - * @param value The value for the feature. The interpretation of this + * @param featureId The desired feature to change. Features are constants + * defined by Window. + * @param value The value for the feature. The interpretation of this * value is feature-specific. */ public abstract void setFeatureInt(int featureId, int value); diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 47ee52e25116..f4f047e60230 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -523,15 +523,6 @@ public interface WindowManager extends ViewManager { public static final int TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+27; /** - * Window type: Recents. Same layer as {@link #TYPE_SYSTEM_DIALOG} but only appears on - * one user's screen. - * In multiuser systems shows on all users' windows. - * @hide - */ - public static final int TYPE_RECENTS_OVERLAY = FIRST_SYSTEM_WINDOW+28; - - - /** * Window type: keyguard scrim window. Shows if keyguard needs to be restarted. * In multiuser systems shows on all users' windows. * @hide @@ -551,6 +542,19 @@ public interface WindowManager extends ViewManager { public static final int TYPE_VOICE_INTERACTION = FIRST_SYSTEM_WINDOW+31; /** + * Window type: Windows that are overlaid <em>only</em> by an {@link + * android.accessibilityservice.AccessibilityService} for interception of + * user interactions without changing the windows an accessibility service + * can introspect. In particular, an accessibility service can introspect + * only windows that a sighted user can interact with which is they can touch + * these windows or can type into these windows. For example, if there + * is a full screen accessibility overlay that is touchable, the windows + * below it will be introspectable by an accessibility service regardless + * they are covered by a touchable window. + */ + public static final int TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW+32; + + /** * End of types of system windows. */ public static final int LAST_SYSTEM_WINDOW = 2999; @@ -887,9 +891,6 @@ public interface WindowManager extends ViewManager { */ public static final int FLAG_TRANSLUCENT_NAVIGATION = 0x08000000; - // ----- HIDDEN FLAGS. - // These start at the high bit and go down. - /** * Flag for a window in local focus mode. * Window in local focus mode can control focus independent of window manager using @@ -912,17 +913,12 @@ public interface WindowManager extends ViewManager { public static final int FLAG_SLIPPERY = 0x20000000; /** - * Flag for a window belonging to an activity that responds to {@link KeyEvent#KEYCODE_MENU} - * and therefore needs a Menu key. For devices where Menu is a physical button this flag is - * ignored, but on devices where the Menu key is drawn in software it may be hidden unless - * this flag is set. - * - * (Note that Action Bars, when available, are the preferred way to offer additional - * functions otherwise accessed via an options menu.) - * - * {@hide} + * Window flag: When requesting layout with an attached window, the attached window may + * overlap with the screen decorations of the parent window such as the navigation bar. By + * including this flag, the window manager will layout the attached window within the decor + * frame of the parent window such that it doesn't overlap with screen decorations. */ - public static final int FLAG_NEEDS_MENU_KEY = 0x40000000; + public static final int FLAG_LAYOUT_ATTACHED_IN_DECOR = 0x40000000; /** * Flag indicating that this Window is responsible for drawing the background for the @@ -1065,16 +1061,6 @@ public interface WindowManager extends ViewManager { */ public static final int PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS = 0x00000004; - /** - * This is set for a window that has explicitly specified its - * FLAG_NEEDS_MENU_KEY, so we know the value on this window is the - * appropriate one to use. If this is not set, we should look at - * windows behind it to determine the appropriate value. - * - * @hide - */ - public static final int PRIVATE_FLAG_SET_NEEDS_MENU_KEY = 0x00000008; - /** In a multiuser system if this flag is set and the owner is a system process then this * window will appear on all user screens. This overrides the default behavior of window * types that normally only appear on the owning user's screen. Refer to each window type @@ -1122,6 +1108,45 @@ public interface WindowManager extends ViewManager { public int privateFlags; /** + * Value for {@link #needsMenuKey} for a window that has not explicitly specified if it + * needs {@link #NEEDS_MENU_SET_TRUE} or doesn't need {@link #NEEDS_MENU_SET_FALSE} a menu + * key. For this case, we should look at windows behind it to determine the appropriate + * value. + * + * @hide + */ + public static final int NEEDS_MENU_UNSET = 0; + + /** + * Value for {@link #needsMenuKey} for a window that has explicitly specified it needs a + * menu key. + * + * @hide + */ + public static final int NEEDS_MENU_SET_TRUE = 1; + + /** + * Value for {@link #needsMenuKey} for a window that has explicitly specified it doesn't + * needs a menu key. + * + * @hide + */ + public static final int NEEDS_MENU_SET_FALSE = 2; + + /** + * State variable for a window belonging to an activity that responds to + * {@link KeyEvent#KEYCODE_MENU} and therefore needs a Menu key. For devices where Menu is a + * physical button this variable is ignored, but on devices where the Menu key is drawn in + * software it may be hidden unless this variable is set to {@link #NEEDS_MENU_SET_TRUE}. + * + * (Note that Action Bars, when available, are the preferred way to offer additional + * functions otherwise accessed via an options menu.) + * + * {@hide} + */ + public int needsMenuKey = NEEDS_MENU_UNSET; + + /** * Given a particular set of window manager flags, determine whether * such a window may be a target for an input method when it has * focus. In particular, this checks the @@ -1129,9 +1154,9 @@ public interface WindowManager extends ViewManager { * flags and returns true if the combination of the two corresponds * to a window that needs to be behind the input method so that the * user can type into it. - * + * * @param flags The current window manager flags. - * + * * @return Returns true if such a window should be behind/interact * with an input method, false if not. */ @@ -1299,7 +1324,7 @@ public interface WindowManager extends ViewManager { * * @hide */ - public Rect surfaceInsets = new Rect(); + public final Rect surfaceInsets = new Rect(); /** * The desired bitmap format. May be one of the constants in @@ -1596,14 +1621,15 @@ public interface WindowManager extends ViewManager { out.writeInt(surfaceInsets.top); out.writeInt(surfaceInsets.right); out.writeInt(surfaceInsets.bottom); + out.writeInt(needsMenuKey); } - + public static final Parcelable.Creator<LayoutParams> CREATOR = new Parcelable.Creator<LayoutParams>() { public LayoutParams createFromParcel(Parcel in) { return new LayoutParams(in); } - + public LayoutParams[] newArray(int size) { return new LayoutParams[size]; } @@ -1643,8 +1669,9 @@ public interface WindowManager extends ViewManager { surfaceInsets.top = in.readInt(); surfaceInsets.right = in.readInt(); surfaceInsets.bottom = in.readInt(); + needsMenuKey = in.readInt(); } - + @SuppressWarnings({"PointlessBitwiseExpression"}) public static final int LAYOUT_CHANGED = 1<<0; public static final int TYPE_CHANGED = 1<<1; @@ -1678,14 +1705,16 @@ public interface WindowManager extends ViewManager { /** {@hide} */ public static final int PREFERRED_REFRESH_RATE_CHANGED = 1 << 21; /** {@hide} */ + public static final int NEEDS_MENU_KEY_CHANGED = 1 << 22; + /** {@hide} */ public static final int EVERYTHING_CHANGED = 0xffffffff; // internal buffer to backup/restore parameters under compatibility mode. private int[] mCompatibilityParamsBackup = null; - + public final int copyFrom(LayoutParams o) { int changes = 0; - + if (width != o.width) { width = o.width; changes |= LAYOUT_CHANGED; @@ -1822,9 +1851,14 @@ public interface WindowManager extends ViewManager { changes |= SURFACE_INSETS_CHANGED; } + if (needsMenuKey != o.needsMenuKey) { + needsMenuKey = o.needsMenuKey; + changes |= NEEDS_MENU_KEY_CHANGED; + } + return changes; } - + @Override public String debug(String output) { output += "Contents of " + this + ":"; @@ -1928,6 +1962,10 @@ public interface WindowManager extends ViewManager { if (!surfaceInsets.equals(Insets.NONE)) { sb.append(" surfaceInsets=").append(surfaceInsets); } + if (needsMenuKey != NEEDS_MENU_UNSET) { + sb.append(" needsMenuKey="); + sb.append(needsMenuKey); + } sb.append('}'); return sb.toString(); } diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java index 38e372367ac5..f557b976d535 100644 --- a/core/java/android/view/WindowManagerInternal.java +++ b/core/java/android/view/WindowManagerInternal.java @@ -173,4 +173,20 @@ public abstract class WindowManagerInternal { * redrawn. */ public abstract void waitForAllWindowsDrawn(Runnable callback, long timeout); + + /** + * Adds a window token for a given window type. + * + * @param token The token to add. + * @param type The window type. + */ + public abstract void addWindowToken(android.os.IBinder token, int type); + + /** + * Removes a window token. + * + * @param token The toke to remove. + * @param removeWindows Whether to also remove the windows associated with the token. + */ + public abstract void removeWindowToken(android.os.IBinder token, boolean removeWindows); } diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index 3987fbc02989..b5afdf78d123 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -547,6 +547,8 @@ public class AccessibilityNodeInfo implements Parcelable { private long mParentNodeId = ROOT_NODE_ID; private long mLabelForId = ROOT_NODE_ID; private long mLabeledById = ROOT_NODE_ID; + private long mTraversalBefore = ROOT_NODE_ID; + private long mTraversalAfter = ROOT_NODE_ID; private int mBooleanProperties; private final Rect mBoundsInParent = new Rect(); @@ -1046,6 +1048,126 @@ public class AccessibilityNodeInfo implements Parcelable { } /** + * Gets the node before which this one is visited during traversal. A screen-reader + * must visit the content of this node before the content of the one it precedes. + * + * @return The succeeding node if such or <code>null</code>. + * + * @see #setTraversalBefore(android.view.View) + * @see #setTraversalBefore(android.view.View, int) + */ + public AccessibilityNodeInfo getTraversalBefore() { + enforceSealed(); + return getNodeForAccessibilityId(mTraversalBefore); + } + + /** + * Sets the view before whose node this one should be visited during traversal. A + * screen-reader must visit the content of this node before the content of the one + * it precedes. + * <p> + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. + * This class is made immutable before being delivered to an AccessibilityService. + * </p> + * + * @param view The view providing the preceding node. + * + * @see #getTraversalBefore() + */ + public void setTraversalBefore(View view) { + setTraversalBefore(view, UNDEFINED_ITEM_ID); + } + + /** + * Sets the node before which this one is visited during traversal. A screen-reader + * must visit the content of this node before the content of the one it precedes. + * The successor is a virtual descendant of the given <code>root</code>. If + * <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root is set + * as the successor. + * <p> + * A virtual descendant is an imaginary View that is reported as a part of the view + * hierarchy for accessibility purposes. This enables custom views that draw complex + * content to report them selves as a tree of virtual views, thus conveying their + * logical structure. + * </p> + * <p> + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. + * This class is made immutable before being delivered to an AccessibilityService. + * </p> + * + * @param root The root of the virtual subtree. + * @param virtualDescendantId The id of the virtual descendant. + */ + public void setTraversalBefore(View root, int virtualDescendantId) { + enforceNotSealed(); + final int rootAccessibilityViewId = (root != null) + ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; + mTraversalBefore = makeNodeId(rootAccessibilityViewId, virtualDescendantId); + } + + /** + * Gets the node after which this one is visited in accessibility traversal. + * A screen-reader must visit the content of the other node before the content + * of this one. + * + * @return The succeeding node if such or <code>null</code>. + * + * @see #setTraversalAfter(android.view.View) + * @see #setTraversalAfter(android.view.View, int) + */ + public AccessibilityNodeInfo getTraversalAfter() { + enforceSealed(); + return getNodeForAccessibilityId(mTraversalAfter); + } + + /** + * Sets the view whose node is visited after this one in accessibility traversal. + * A screen-reader must visit the content of the other node before the content + * of this one. + * <p> + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. + * This class is made immutable before being delivered to an AccessibilityService. + * </p> + * + * @param view The previous view. + * + * @see #getTraversalAfter() + */ + public void setTraversalAfter(View view) { + setTraversalAfter(view, UNDEFINED_ITEM_ID); + } + + /** + * Sets the node after which this one is visited in accessibility traversal. + * A screen-reader must visit the content of the other node before the content + * of this one. If <code>virtualDescendantId</code> equals to {@link View#NO_ID} + * the root is set as the predecessor. + * <p> + * A virtual descendant is an imaginary View that is reported as a part of the view + * hierarchy for accessibility purposes. This enables custom views that draw complex + * content to report them selves as a tree of virtual views, thus conveying their + * logical structure. + * </p> + * <p> + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. + * This class is made immutable before being delivered to an AccessibilityService. + * </p> + * + * @param root The root of the virtual subtree. + * @param virtualDescendantId The id of the virtual descendant. + */ + public void setTraversalAfter(View root, int virtualDescendantId) { + enforceNotSealed(); + final int rootAccessibilityViewId = (root != null) + ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; + mTraversalAfter = makeNodeId(rootAccessibilityViewId, virtualDescendantId); + } + + /** * Sets the maximum text length, or -1 for no limit. * <p> * Typically used to indicate that an editable text field has a limit on @@ -1229,13 +1351,7 @@ public class AccessibilityNodeInfo implements Parcelable { */ public AccessibilityNodeInfo getParent() { enforceSealed(); - if (!canPerformRequestOverConnection(mParentNodeId)) { - return null; - } - AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); - return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, - mWindowId, mParentNodeId, false, FLAG_PREFETCH_PREDECESSORS - | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS); + return getNodeForAccessibilityId(mParentNodeId); } /** @@ -2055,13 +2171,7 @@ public class AccessibilityNodeInfo implements Parcelable { */ public AccessibilityNodeInfo getLabelFor() { enforceSealed(); - if (!canPerformRequestOverConnection(mLabelForId)) { - return null; - } - AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); - return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, - mWindowId, mLabelForId, false, FLAG_PREFETCH_PREDECESSORS - | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS); + return getNodeForAccessibilityId(mLabelForId); } /** @@ -2113,13 +2223,7 @@ public class AccessibilityNodeInfo implements Parcelable { */ public AccessibilityNodeInfo getLabeledBy() { enforceSealed(); - if (!canPerformRequestOverConnection(mLabeledById)) { - return null; - } - AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); - return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, - mWindowId, mLabeledById, false, FLAG_PREFETCH_PREDECESSORS - | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS); + return getNodeForAccessibilityId(mLabeledById); } /** @@ -2453,6 +2557,9 @@ public class AccessibilityNodeInfo implements Parcelable { parcel.writeLong(mParentNodeId); parcel.writeLong(mLabelForId); parcel.writeLong(mLabeledById); + parcel.writeLong(mTraversalBefore); + parcel.writeLong(mTraversalAfter); + parcel.writeInt(mConnectionId); final LongArray childIds = mChildNodeIds; @@ -2571,6 +2678,8 @@ public class AccessibilityNodeInfo implements Parcelable { mParentNodeId = other.mParentNodeId; mLabelForId = other.mLabelForId; mLabeledById = other.mLabeledById; + mTraversalBefore = other.mTraversalBefore; + mTraversalAfter = other.mTraversalAfter; mWindowId = other.mWindowId; mConnectionId = other.mConnectionId; mBoundsInParent.set(other.mBoundsInParent); @@ -2633,6 +2742,9 @@ public class AccessibilityNodeInfo implements Parcelable { mParentNodeId = parcel.readLong(); mLabelForId = parcel.readLong(); mLabeledById = parcel.readLong(); + mTraversalBefore = parcel.readLong(); + mTraversalAfter = parcel.readLong(); + mConnectionId = parcel.readInt(); final int childrenSize = parcel.readInt(); @@ -2725,6 +2837,8 @@ public class AccessibilityNodeInfo implements Parcelable { mParentNodeId = ROOT_NODE_ID; mLabelForId = ROOT_NODE_ID; mLabeledById = ROOT_NODE_ID; + mTraversalBefore = ROOT_NODE_ID; + mTraversalAfter = ROOT_NODE_ID; mWindowId = UNDEFINED_ITEM_ID; mConnectionId = UNDEFINED_CONNECTION_ID; mMaxTextLength = -1; @@ -2911,6 +3025,8 @@ public class AccessibilityNodeInfo implements Parcelable { builder.append("; accessibilityViewId: " + getAccessibilityViewId(mSourceNodeId)); builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId)); builder.append("; mParentNodeId: " + mParentNodeId); + builder.append("; traversalBefore: ").append(mTraversalBefore); + builder.append("; traversalAfter: ").append(mTraversalAfter); int granularities = mMovementGranularities; builder.append("; MovementGranularities: ["); @@ -2963,6 +3079,16 @@ public class AccessibilityNodeInfo implements Parcelable { return builder.toString(); } + private AccessibilityNodeInfo getNodeForAccessibilityId(long accessibilityId) { + if (!canPerformRequestOverConnection(accessibilityId)) { + return null; + } + AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); + return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, + mWindowId, accessibilityId, false, FLAG_PREFETCH_PREDECESSORS + | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS); + } + /** * A class defining an action that can be performed on an {@link AccessibilityNodeInfo}. * Each action has a unique id that is mandatory and optional data. diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java index ad55f5f2a097..e1942beaaa0f 100644 --- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java +++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java @@ -51,11 +51,24 @@ public final class AccessibilityWindowInfo implements Parcelable { */ public static final int TYPE_SYSTEM = 3; + /** + * Window type: Windows that are overlaid <em>only</em> by an {@link + * android.accessibilityservice.AccessibilityService} for interception of + * user interactions without changing the windows an accessibility service + * can introspect. In particular, an accessibility service can introspect + * only windows that a sighted user can interact with which they can touch + * these windows or can type into these windows. For example, if there + * is a full screen accessibility overlay that is touchable, the windows + * below it will be introspectable by an accessibility service regardless + * they are covered by a touchable window. + */ + public static final int TYPE_ACCESSIBILITY_OVERLAY = 4; + private static final int UNDEFINED = -1; private static final int BOOLEAN_PROPERTY_ACTIVE = 1 << 0; private static final int BOOLEAN_PROPERTY_FOCUSED = 1 << 1; - private static final int BOOLEAN_PROPERTY_ACCESSIBLITY_FOCUSED = 1 << 2; + private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED = 1 << 2; // Housekeeping. private static final int MAX_POOL_SIZE = 10; @@ -85,6 +98,7 @@ public final class AccessibilityWindowInfo implements Parcelable { * @see #TYPE_APPLICATION * @see #TYPE_INPUT_METHOD * @see #TYPE_SYSTEM + * @see #TYPE_ACCESSIBILITY_OVERLAY */ public int getType() { return mType; @@ -93,7 +107,7 @@ public final class AccessibilityWindowInfo implements Parcelable { /** * Sets the type of the window. * - * @param The type + * @param type The type * * @hide */ @@ -115,7 +129,7 @@ public final class AccessibilityWindowInfo implements Parcelable { * Sets the layer which determines the Z-order of the window. Windows * with greater layer appear on top of windows with lesser layer. * - * @param The window layer. + * @param layer The window layer. * * @hide */ @@ -174,7 +188,7 @@ public final class AccessibilityWindowInfo implements Parcelable { /** * Sets the unique window id. * - * @param windowId The window id. + * @param id The window id. * * @hide */ @@ -230,7 +244,7 @@ public final class AccessibilityWindowInfo implements Parcelable { * the user is currently touching or the window has input focus * and the user is not touching any window. * - * @param Whether this is the active window. + * @param active Whether this is the active window. * * @hide */ @@ -250,7 +264,7 @@ public final class AccessibilityWindowInfo implements Parcelable { /** * Sets if this window has input focus. * - * @param Whether has input focus. + * @param focused Whether has input focus. * * @hide */ @@ -264,18 +278,18 @@ public final class AccessibilityWindowInfo implements Parcelable { * @return Whether has accessibility focus. */ public boolean isAccessibilityFocused() { - return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBLITY_FOCUSED); + return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED); } /** * Sets if this window has accessibility focus. * - * @param Whether has accessibility focus. + * @param focused Whether has accessibility focus. * * @hide */ public void setAccessibilityFocused(boolean focused) { - setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBLITY_FOCUSED, focused); + setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED, focused); } /** @@ -534,6 +548,9 @@ public final class AccessibilityWindowInfo implements Parcelable { case TYPE_SYSTEM: { return "TYPE_SYSTEM"; } + case TYPE_ACCESSIBILITY_OVERLAY: { + return "TYPE_ACCESSIBILITY_OVERLAY"; + } default: return "<UNKNOWN>"; } diff --git a/core/java/android/view/animation/AccelerateDecelerateInterpolator.java b/core/java/android/view/animation/AccelerateDecelerateInterpolator.java index ed6949a0f3b6..21d5a5b86bf2 100644 --- a/core/java/android/view/animation/AccelerateDecelerateInterpolator.java +++ b/core/java/android/view/animation/AccelerateDecelerateInterpolator.java @@ -26,17 +26,17 @@ import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; /** * An interpolator where the rate of change starts and ends slowly but * accelerates through the middle. - * */ @HasNativeInterpolator -public class AccelerateDecelerateInterpolator implements Interpolator, NativeInterpolatorFactory { +public class AccelerateDecelerateInterpolator extends BaseInterpolator + implements NativeInterpolatorFactory { public AccelerateDecelerateInterpolator() { } - + @SuppressWarnings({"UnusedDeclaration"}) public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) { } - + public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; } diff --git a/core/java/android/view/animation/AccelerateInterpolator.java b/core/java/android/view/animation/AccelerateInterpolator.java index 1c75f166bf17..6c8d7b19fb15 100644 --- a/core/java/android/view/animation/AccelerateInterpolator.java +++ b/core/java/android/view/animation/AccelerateInterpolator.java @@ -33,7 +33,7 @@ import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; * */ @HasNativeInterpolator -public class AccelerateInterpolator implements Interpolator, NativeInterpolatorFactory { +public class AccelerateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { private final float mFactor; private final double mDoubleFactor; @@ -70,7 +70,7 @@ public class AccelerateInterpolator implements Interpolator, NativeInterpolatorF mFactor = a.getFloat(R.styleable.AccelerateInterpolator_factor, 1.0f); mDoubleFactor = 2 * mFactor; - + setChangingConfiguration(a.getChangingConfigurations()); a.recycle(); } diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java index af4e04ffe3a8..606c83e39c05 100644 --- a/core/java/android/view/animation/AnimationUtils.java +++ b/core/java/android/view/animation/AnimationUtils.java @@ -321,7 +321,7 @@ public class AnimationUtils { private static Interpolator createInterpolatorFromXml(Resources res, Theme theme, XmlPullParser parser) throws XmlPullParserException, IOException { - Interpolator interpolator = null; + BaseInterpolator interpolator = null; // Make sure we are on a start tag. int type; @@ -361,10 +361,7 @@ public class AnimationUtils { } else { throw new RuntimeException("Unknown interpolator name: " + parser.getName()); } - } - return interpolator; - } } diff --git a/core/java/android/view/animation/AnticipateInterpolator.java b/core/java/android/view/animation/AnticipateInterpolator.java index fe756bd473e1..fb66c312181c 100644 --- a/core/java/android/view/animation/AnticipateInterpolator.java +++ b/core/java/android/view/animation/AnticipateInterpolator.java @@ -31,7 +31,7 @@ import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; * An interpolator where the change starts backward then flings forward. */ @HasNativeInterpolator -public class AnticipateInterpolator implements Interpolator, NativeInterpolatorFactory { +public class AnticipateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { private final float mTension; public AnticipateInterpolator() { @@ -60,9 +60,8 @@ public class AnticipateInterpolator implements Interpolator, NativeInterpolatorF a = res.obtainAttributes(attrs, R.styleable.AnticipateInterpolator); } - mTension = - a.getFloat(R.styleable.AnticipateInterpolator_tension, 2.0f); - + mTension = a.getFloat(R.styleable.AnticipateInterpolator_tension, 2.0f); + setChangingConfiguration(a.getChangingConfigurations()); a.recycle(); } diff --git a/core/java/android/view/animation/AnticipateOvershootInterpolator.java b/core/java/android/view/animation/AnticipateOvershootInterpolator.java index 78e5acf247a0..1af72da7a3a4 100644 --- a/core/java/android/view/animation/AnticipateOvershootInterpolator.java +++ b/core/java/android/view/animation/AnticipateOvershootInterpolator.java @@ -35,7 +35,8 @@ import static com.android.internal.R.styleable.AnticipateOvershootInterpolator; * the target value and finally goes back to the final value. */ @HasNativeInterpolator -public class AnticipateOvershootInterpolator implements Interpolator, NativeInterpolatorFactory { +public class AnticipateOvershootInterpolator extends BaseInterpolator + implements NativeInterpolatorFactory { private final float mTension; public AnticipateOvershootInterpolator() { @@ -78,7 +79,7 @@ public class AnticipateOvershootInterpolator implements Interpolator, NativeInte mTension = a.getFloat(AnticipateOvershootInterpolator_tension, 2.0f) * a.getFloat(AnticipateOvershootInterpolator_extraTension, 1.5f); - + setChangingConfiguration(a.getChangingConfigurations()); a.recycle(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java b/core/java/android/view/animation/BaseInterpolator.java index f339401dce18..9c0014c951c3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java +++ b/core/java/android/view/animation/BaseInterpolator.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2014 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. @@ -14,19 +14,24 @@ * limitations under the License. */ -package com.android.systemui.statusbar.policy; +package android.view.animation; -import android.content.Context; -import android.content.SharedPreferences; - -public class Prefs { - private static final String SHARED_PREFS_NAME = "status_bar"; - - public static SharedPreferences read(Context context) { - return context.getSharedPreferences(Prefs.SHARED_PREFS_NAME, Context.MODE_PRIVATE); +/** + * An abstract class which is extended by default interpolators. + */ +abstract public class BaseInterpolator implements Interpolator { + private int mChangingConfiguration; + /** + * @hide + */ + public int getChangingConfiguration() { + return mChangingConfiguration; } - public static SharedPreferences.Editor edit(Context context) { - return context.getSharedPreferences(Prefs.SHARED_PREFS_NAME, Context.MODE_PRIVATE).edit(); + /** + * @hide + */ + void setChangingConfiguration(int changingConfiguration) { + mChangingConfiguration = changingConfiguration; } } diff --git a/core/java/android/view/animation/BounceInterpolator.java b/core/java/android/view/animation/BounceInterpolator.java index 9d8ca901f0ad..909eaa4c7c26 100644 --- a/core/java/android/view/animation/BounceInterpolator.java +++ b/core/java/android/view/animation/BounceInterpolator.java @@ -27,7 +27,7 @@ import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; * An interpolator where the change bounces at the end. */ @HasNativeInterpolator -public class BounceInterpolator implements Interpolator, NativeInterpolatorFactory { +public class BounceInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { public BounceInterpolator() { } diff --git a/core/java/android/view/animation/CycleInterpolator.java b/core/java/android/view/animation/CycleInterpolator.java index 3114aa3ca1d6..663c1091ca29 100644 --- a/core/java/android/view/animation/CycleInterpolator.java +++ b/core/java/android/view/animation/CycleInterpolator.java @@ -33,7 +33,7 @@ import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; * */ @HasNativeInterpolator -public class CycleInterpolator implements Interpolator, NativeInterpolatorFactory { +public class CycleInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { public CycleInterpolator(float cycles) { mCycles = cycles; } @@ -52,7 +52,7 @@ public class CycleInterpolator implements Interpolator, NativeInterpolatorFactor } mCycles = a.getFloat(R.styleable.CycleInterpolator_cycles, 1.0f); - + setChangingConfiguration(a.getChangingConfigurations()); a.recycle(); } diff --git a/core/java/android/view/animation/DecelerateInterpolator.java b/core/java/android/view/animation/DecelerateInterpolator.java index 674207ca7e00..f426f60dc581 100644 --- a/core/java/android/view/animation/DecelerateInterpolator.java +++ b/core/java/android/view/animation/DecelerateInterpolator.java @@ -33,7 +33,7 @@ import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; * */ @HasNativeInterpolator -public class DecelerateInterpolator implements Interpolator, NativeInterpolatorFactory { +public class DecelerateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { public DecelerateInterpolator() { } @@ -62,7 +62,7 @@ public class DecelerateInterpolator implements Interpolator, NativeInterpolatorF } mFactor = a.getFloat(R.styleable.DecelerateInterpolator_factor, 1.0f); - + setChangingConfiguration(a.getChangingConfigurations()); a.recycle(); } diff --git a/core/java/android/view/animation/LinearInterpolator.java b/core/java/android/view/animation/LinearInterpolator.java index 552c6119513d..2a047b48cfb0 100644 --- a/core/java/android/view/animation/LinearInterpolator.java +++ b/core/java/android/view/animation/LinearInterpolator.java @@ -25,17 +25,16 @@ import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; /** * An interpolator where the rate of change is constant - * */ @HasNativeInterpolator -public class LinearInterpolator implements Interpolator, NativeInterpolatorFactory { +public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { public LinearInterpolator() { } - + public LinearInterpolator(Context context, AttributeSet attrs) { } - + public float getInterpolation(float input) { return input; } diff --git a/core/java/android/view/animation/OvershootInterpolator.java b/core/java/android/view/animation/OvershootInterpolator.java index d6c280871a99..306688a1b10b 100644 --- a/core/java/android/view/animation/OvershootInterpolator.java +++ b/core/java/android/view/animation/OvershootInterpolator.java @@ -32,7 +32,7 @@ import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; * then comes back. */ @HasNativeInterpolator -public class OvershootInterpolator implements Interpolator, NativeInterpolatorFactory { +public class OvershootInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { private final float mTension; public OvershootInterpolator() { @@ -61,9 +61,8 @@ public class OvershootInterpolator implements Interpolator, NativeInterpolatorFa a = res.obtainAttributes(attrs, R.styleable.OvershootInterpolator); } - mTension = - a.getFloat(R.styleable.OvershootInterpolator_tension, 2.0f); - + mTension = a.getFloat(R.styleable.OvershootInterpolator_tension, 2.0f); + setChangingConfiguration(a.getChangingConfigurations()); a.recycle(); } diff --git a/core/java/android/view/animation/PathInterpolator.java b/core/java/android/view/animation/PathInterpolator.java index 945ecf00656a..eec5555e6d79 100644 --- a/core/java/android/view/animation/PathInterpolator.java +++ b/core/java/android/view/animation/PathInterpolator.java @@ -42,7 +42,7 @@ import com.android.internal.R; * path.lineTo(1f, 1f); * </pre></blockquote></p> */ -public class PathInterpolator implements Interpolator { +public class PathInterpolator extends BaseInterpolator { // This governs how accurate the approximation of the Path is. private static final float PRECISION = 0.002f; @@ -98,7 +98,7 @@ public class PathInterpolator implements Interpolator { a = res.obtainAttributes(attrs, R.styleable.PathInterpolator); } parseInterpolatorFromTypeArray(a); - + setChangingConfiguration(a.getChangingConfigurations()); a.recycle(); } diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 043916840fad..6927660d2a12 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -2663,7 +2663,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * @return True if the selector should be shown */ boolean shouldShowSelector() { - return (!isInTouchMode()) || (touchModeDrawsInPressedState() && isPressed()); + return (isFocused() && !isInTouchMode()) || (touchModeDrawsInPressedState() && isPressed()); } private void drawSelector(Canvas canvas) { @@ -4653,7 +4653,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (mPositionScroller == null) { mPositionScroller = createPositionScroller(); } - mPositionScroller.startWithOffset(position, offset, offset); + mPositionScroller.startWithOffset(position, offset); } /** @@ -4910,9 +4910,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (position >= headerViewsCount && position < footerViewsStart) { // The view will be rebound to new data, clear any // system-managed transient state. - if (child.isAccessibilityFocused()) { - child.clearAccessibilityFocus(); - } + child.clearAccessibilityFocus(); mRecycler.addScrapView(child, position); } } @@ -4933,9 +4931,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (position >= headerViewsCount && position < footerViewsStart) { // The view will be rebound to new data, clear any // system-managed transient state. - if (child.isAccessibilityFocused()) { - child.clearAccessibilityFocus(); - } + child.clearAccessibilityFocus(); mRecycler.addScrapView(child, position); } } @@ -6776,9 +6772,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } private void clearAccessibilityFromScrap(View view) { - if (view.isAccessibilityFocused()) { - view.clearAccessibilityFocus(); - } + view.clearAccessibilityFocus(); view.setAccessibilityDelegate(null); } diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java index b2cfdf7da22f..d39960f6b915 100644 --- a/core/java/android/widget/AbsSeekBar.java +++ b/core/java/android/widget/AbsSeekBar.java @@ -267,6 +267,12 @@ public abstract class AbsSeekBar extends ProgressBar { if (mHasThumbTintMode) { mThumb.setTintMode(mThumbTintMode); } + + // The drawable (or one of its children) may not have been + // stateful before applying the tint, so let's try again. + if (mThumb.isStateful()) { + mThumb.setState(getDrawableState()); + } } } diff --git a/core/java/android/widget/ActionMenuView.java b/core/java/android/widget/ActionMenuView.java index 7198e522f3ae..0a8a01f2dfe9 100644 --- a/core/java/android/widget/ActionMenuView.java +++ b/core/java/android/widget/ActionMenuView.java @@ -429,7 +429,7 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo } final int childCount = getChildCount(); - final int midVertical = (top + bottom) / 2; + final int midVertical = (bottom - top) / 2; final int dividerWidth = getDividerWidth(); int overflowWidth = 0; int nonOverflowWidth = 0; diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java index b9f891ce71c9..5e2394ca834e 100644 --- a/core/java/android/widget/AdapterView.java +++ b/core/java/android/widget/AdapterView.java @@ -215,7 +215,12 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup { private boolean mDesiredFocusableState; private boolean mDesiredFocusableInTouchModeState; + /** Lazily-constructed runnable for dispatching selection events. */ private SelectionNotifier mSelectionNotifier; + + /** Selection notifier that's waiting for the next layout pass. */ + private SelectionNotifier mPendingSelectionNotifier; + /** * When set to true, calls to requestLayout() will not propagate up the parent hierarchy. * This is used to layout the children during a layout pass. @@ -854,39 +859,51 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup { private class SelectionNotifier implements Runnable { public void run() { - if (mDataChanged) { - // Data has changed between when this SelectionNotifier - // was posted and now. We need to wait until the AdapterView - // has been synched to the new data. + mPendingSelectionNotifier = null; + + if (mDataChanged && getViewRootImpl() != null + && getViewRootImpl().isLayoutRequested()) { + // Data has changed between when this SelectionNotifier was + // posted and now. Postpone the notification until the next + // layout is complete and we run checkSelectionChanged(). if (getAdapter() != null) { - post(this); + mPendingSelectionNotifier = this; } } else { - fireOnSelected(); - performAccessibilityActionsOnSelected(); + dispatchOnItemSelected(); } } } void selectionChanged() { + // We're about to post or run the selection notifier, so we don't need + // a pending notifier. + mPendingSelectionNotifier = null; + if (mOnItemSelectedListener != null || AccessibilityManager.getInstance(mContext).isEnabled()) { if (mInLayout || mBlockLayoutRequests) { // If we are in a layout traversal, defer notification // by posting. This ensures that the view tree is - // in a consistent state and is able to accomodate + // in a consistent state and is able to accommodate // new layout or invalidate requests. if (mSelectionNotifier == null) { mSelectionNotifier = new SelectionNotifier(); + } else { + removeCallbacks(mSelectionNotifier); } post(mSelectionNotifier); } else { - fireOnSelected(); - performAccessibilityActionsOnSelected(); + dispatchOnItemSelected(); } } } + private void dispatchOnItemSelected() { + fireOnSelected(); + performAccessibilityActionsOnSelected(); + } + private void fireOnSelected() { if (mOnItemSelectedListener == null) { return; @@ -1042,12 +1059,22 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup { notifySubtreeAccessibilityStateChangedIfNeeded(); } + /** + * Called after layout to determine whether the selection position needs to + * be updated. Also used to fire any pending selection events. + */ void checkSelectionChanged() { if ((mSelectedPosition != mOldSelectedPosition) || (mSelectedRowId != mOldSelectedRowId)) { selectionChanged(); mOldSelectedPosition = mSelectedPosition; mOldSelectedRowId = mSelectedRowId; } + + // If we have a pending selection notification -- and we won't if we + // just fired one in selectionChanged() -- run it now. + if (mPendingSelectionNotifier != null) { + mPendingSelectionNotifier.run(); + } } /** diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java index 10e56c74f979..5c05b5a3d367 100644 --- a/core/java/android/widget/AppSecurityPermissions.java +++ b/core/java/android/widget/AppSecurityPermissions.java @@ -99,12 +99,12 @@ public class AppSecurityPermissions { public Drawable loadGroupIcon(PackageManager pm) { if (icon != 0) { - return loadIcon(pm); + return loadUnbadgedIcon(pm); } else { ApplicationInfo appInfo; try { appInfo = pm.getApplicationInfo(packageName, 0); - return appInfo.loadIcon(pm); + return appInfo.loadUnbadgedIcon(pm); } catch (NameNotFoundException e) { } } diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java index ea60abbfb144..f380d689e1c5 100644 --- a/core/java/android/widget/CalendarView.java +++ b/core/java/android/widget/CalendarView.java @@ -775,9 +775,14 @@ public class CalendarView extends FrameLayout { private ViewGroup mDayNamesHeader; /** - * Cached labels for the week names header. + * Cached abbreviations for day of week names. */ - private String[] mDayLabels; + private String[] mDayNamesShort; + + /** + * Cached full-length day of week names. + */ + private String[] mDayNamesLong; /** * The first day of the week. @@ -1306,11 +1311,14 @@ public class CalendarView extends FrameLayout { * Sets up the strings to be used by the header. */ private void setUpHeader() { - mDayLabels = new String[mDaysPerWeek]; + mDayNamesShort = new String[mDaysPerWeek]; + mDayNamesLong = new String[mDaysPerWeek]; for (int i = mFirstDayOfWeek, count = mFirstDayOfWeek + mDaysPerWeek; i < count; i++) { int calendarDay = (i > Calendar.SATURDAY) ? i - Calendar.SATURDAY : i; - mDayLabels[i - mFirstDayOfWeek] = DateUtils.getDayOfWeekString(calendarDay, + mDayNamesShort[i - mFirstDayOfWeek] = DateUtils.getDayOfWeekString(calendarDay, DateUtils.LENGTH_SHORTEST); + mDayNamesLong[i - mFirstDayOfWeek] = DateUtils.getDayOfWeekString(calendarDay, + DateUtils.LENGTH_LONG); } TextView label = (TextView) mDayNamesHeader.getChildAt(0); @@ -1325,7 +1333,8 @@ public class CalendarView extends FrameLayout { label.setTextAppearance(mContext, mWeekDayTextAppearanceResId); } if (i < mDaysPerWeek + 1) { - label.setText(mDayLabels[i - 1]); + label.setText(mDayNamesShort[i - 1]); + label.setContentDescription(mDayNamesLong[i - 1]); label.setVisibility(View.VISIBLE); } else { label.setVisibility(View.GONE); diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java index eb8e8aa66360..69969a940db8 100644 --- a/core/java/android/widget/CheckedTextView.java +++ b/core/java/android/widget/CheckedTextView.java @@ -267,6 +267,12 @@ public class CheckedTextView extends TextView implements Checkable { if (mHasCheckMarkTintMode) { mCheckMarkDrawable.setTintMode(mCheckMarkTintMode); } + + // The drawable (or one of its children) may not have been + // stateful before applying the tint, so let's try again. + if (mCheckMarkDrawable.isStateful()) { + mCheckMarkDrawable.setState(getDrawableState()); + } } } diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java index 7d9d3052fe22..447ccc2692a2 100644 --- a/core/java/android/widget/CompoundButton.java +++ b/core/java/android/widget/CompoundButton.java @@ -29,6 +29,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.util.AttributeSet; import android.view.Gravity; +import android.view.SoundEffectConstants; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; @@ -114,15 +115,16 @@ public abstract class CompoundButton extends Button implements Checkable { @Override public boolean performClick() { - /* - * XXX: These are tiny, need some surrounding 'expanded touch area', - * which will need to be implemented in Button if we only override - * performClick() - */ - - /* When clicked, toggle the state */ toggle(); - return super.performClick(); + + final boolean handled = super.performClick(); + if (!handled) { + // View only makes a sound effect if the onClickListener was + // called, so we'll need to make one here instead. + playSoundEffect(SoundEffectConstants.CLICK); + } + + return handled; } @ViewDebug.ExportedProperty @@ -313,6 +315,12 @@ public abstract class CompoundButton extends Button implements Checkable { if (mHasButtonTintMode) { mButtonDrawable.setTintMode(mButtonTintMode); } + + // The drawable (or one of its children) may not have been + // stateful before applying the tint, so let's try again. + if (mButtonDrawable.isStateful()) { + mButtonDrawable.setState(getDrawableState()); + } } } diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java index e71b38366baa..64c81e0fc777 100644 --- a/core/java/android/widget/DatePickerCalendarDelegate.java +++ b/core/java/android/widget/DatePickerCalendarDelegate.java @@ -21,13 +21,11 @@ import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; import android.text.format.DateFormat; import android.text.format.DateUtils; import android.util.AttributeSet; -import android.util.SparseArray; import android.view.HapticFeedbackConstants; import android.view.LayoutInflater; import android.view.View; @@ -186,6 +184,8 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i headerSelectedTextColor)); mDayPickerView = new DayPickerView(mContext, this); + mDayPickerView.setRange(mMinDate, mMaxDate); + mYearPickerView = new YearPickerView(mContext); mYearPickerView.init(this); @@ -411,7 +411,8 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i updateDisplay(false); } mMinDate.setTimeInMillis(minDate); - mDayPickerView.goTo(getSelectedDay(), false, true, true); + mDayPickerView.setRange(mMinDate, mMaxDate); + mYearPickerView.setRange(mMinDate, mMaxDate); } @Override @@ -432,7 +433,8 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i updateDisplay(false); } mMaxDate.setTimeInMillis(maxDate); - mDayPickerView.goTo(getSelectedDay(), false, true, true); + mDayPickerView.setRange(mMinDate, mMaxDate); + mYearPickerView.setRange(mMinDate, mMaxDate); } @Override @@ -454,36 +456,6 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i } @Override - public int getMinYear() { - return mMinDate.get(Calendar.YEAR); - } - - @Override - public int getMaxYear() { - return mMaxDate.get(Calendar.YEAR); - } - - @Override - public int getMinMonth() { - return mMinDate.get(Calendar.MONTH); - } - - @Override - public int getMaxMonth() { - return mMaxDate.get(Calendar.MONTH); - } - - @Override - public int getMinDay() { - return mMinDate.get(Calendar.DAY_OF_MONTH); - } - - @Override - public int getMaxDay() { - return mMaxDate.get(Calendar.DAY_OF_MONTH); - } - - @Override public void setEnabled(boolean enabled) { mMonthAndDayLayout.setEnabled(enabled); mHeaderYearTextView.setEnabled(enabled); diff --git a/core/java/android/widget/DatePickerController.java b/core/java/android/widget/DatePickerController.java index 059709d55156..ea6ec6153e4f 100644 --- a/core/java/android/widget/DatePickerController.java +++ b/core/java/android/widget/DatePickerController.java @@ -38,20 +38,5 @@ interface DatePickerController { void setFirstDayOfWeek(int firstDayOfWeek); int getFirstDayOfWeek(); - int getMinYear(); - int getMaxYear(); - - int getMinMonth(); - int getMaxMonth(); - - int getMinDay(); - int getMaxDay(); - - void setMinDate(long minDate); - Calendar getMinDate(); - - void setMaxDate(long maxDate); - Calendar getMaxDate(); - void tryVibrate(); } diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java index ca4095ed1292..fcf66f658291 100644 --- a/core/java/android/widget/DayPickerView.java +++ b/core/java/android/widget/DayPickerView.java @@ -25,6 +25,7 @@ import android.os.Bundle; import android.os.Handler; import android.util.AttributeSet; import android.util.Log; +import android.util.MathUtils; import android.view.View; import android.view.ViewConfiguration; import android.view.accessibility.AccessibilityEvent; @@ -57,9 +58,11 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener, // highlighted time private Calendar mSelectedDay = Calendar.getInstance(); - private SimpleMonthAdapter mAdapter; - private Calendar mTempDay = Calendar.getInstance(); + private Calendar mMinDate = Calendar.getInstance(); + private Calendar mMaxDate = Calendar.getInstance(); + + private SimpleMonthAdapter mAdapter; // which month should be displayed/highlighted [0-11] private int mCurrentMonthDisplayed; @@ -75,6 +78,7 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener, public DayPickerView(Context context, DatePickerController controller) { super(context); + init(); setController(controller); } @@ -97,6 +101,41 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener, setUpListView(); } + public void setRange(Calendar minDate, Calendar maxDate) { + mMinDate.setTimeInMillis(minDate.getTimeInMillis()); + mMaxDate.setTimeInMillis(maxDate.getTimeInMillis()); + + mAdapter.setRange(mMinDate, mMaxDate); + + if (constrainCalendar(mSelectedDay, mMinDate, mMaxDate)) { + goTo(mSelectedDay, false, true, true); + } + } + + /** + * Constrains the supplied calendar to stay within the min and max + * calendars, returning <code>true</code> if the supplied calendar + * was modified. + * + * @param value The calendar to constrain + * @param min The minimum calendar + * @param max The maximum calendar + * @return True if <code>value</code> was modified + */ + private boolean constrainCalendar(Calendar value, Calendar min, Calendar max) { + if (value.compareTo(min) < 0) { + value.setTimeInMillis(min.getTimeInMillis()); + return true; + } + + if (value.compareTo(max) > 0) { + value.setTimeInMillis(max.getTimeInMillis()); + return true; + } + + return false; + } + public void onChange() { setUpAdapter(); setAdapter(mAdapter); @@ -137,23 +176,16 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener, setFriction(ViewConfiguration.getScrollFriction() * mFriction); } - private int getDiffMonths(Calendar start, Calendar end){ + private int getDiffMonths(Calendar start, Calendar end) { final int diffYears = end.get(Calendar.YEAR) - start.get(Calendar.YEAR); final int diffMonths = end.get(Calendar.MONTH) - start.get(Calendar.MONTH) + 12 * diffYears; return diffMonths; } private int getPositionFromDay(Calendar day) { - final int diffMonthMax = getDiffMonths(mController.getMinDate(), mController.getMaxDate()); - int diffMonth = getDiffMonths(mController.getMinDate(), day); - - if (diffMonth < 0 ) { - diffMonth = 0; - } else if (diffMonth > diffMonthMax) { - diffMonth = diffMonthMax; - } - - return diffMonth; + final int diffMonthMax = getDiffMonths(mMinDate, mMaxDate); + final int diffMonth = getDiffMonths(mMinDate, day); + return MathUtils.constrain(diffMonth, 0, diffMonthMax); } /** @@ -171,8 +203,7 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener, * visible * @return Whether or not the view animated to the new location */ - public boolean goTo(Calendar day, boolean animate, boolean setSelected, - boolean forceScroll) { + public boolean goTo(Calendar day, boolean animate, boolean setSelected, boolean forceScroll) { // Set the selected day if (setSelected) { @@ -464,10 +495,10 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener, } // Figure out what month is showing. - int firstVisiblePosition = getFirstVisiblePosition(); - int month = firstVisiblePosition % 12; - int year = firstVisiblePosition / 12 + mController.getMinYear(); - Calendar day = Calendar.getInstance(); + final int firstVisiblePosition = getFirstVisiblePosition(); + final int month = firstVisiblePosition % 12; + final int year = firstVisiblePosition / 12 + mMinDate.get(Calendar.YEAR); + final Calendar day = Calendar.getInstance(); day.set(year, month, 1); // Scroll either forward or backward one month. diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java index e3175242d19e..d974c29c39eb 100644 --- a/core/java/android/widget/FrameLayout.java +++ b/core/java/android/widget/FrameLayout.java @@ -384,6 +384,12 @@ public class FrameLayout extends ViewGroup { if (mHasForegroundTintMode) { mForeground.setTintMode(mForegroundTintMode); } + + // The drawable (or one of its children) may not have been + // stateful before applying the tint, so let's try again. + if (mForeground.isStateful()) { + mForeground.setState(getDrawableState()); + } } } diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java index f90a9fe24e92..c68bfcaa5bc2 100644 --- a/core/java/android/widget/ImageView.java +++ b/core/java/android/widget/ImageView.java @@ -386,21 +386,21 @@ public class ImageView extends View { */ @android.view.RemotableViewMethod public void setImageResource(int resId) { - if (mUri != null || mResource != resId) { - final int oldWidth = mDrawableWidth; - final int oldHeight = mDrawableHeight; + // The resource configuration may have changed, so we should always + // try to load the resource even if the resId hasn't changed. + final int oldWidth = mDrawableWidth; + final int oldHeight = mDrawableHeight; - updateDrawable(null); - mResource = resId; - mUri = null; + updateDrawable(null); + mResource = resId; + mUri = null; - resolveUri(); + resolveUri(); - if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) { - requestLayout(); - } - invalidate(); + if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) { + requestLayout(); } + invalidate(); } /** @@ -527,6 +527,12 @@ public class ImageView extends View { if (mHasDrawableTintMode) { mDrawable.setTintMode(mDrawableTintMode); } + + // The drawable (or one of its children) may not have been + // stateful before applying the tint, so let's try again. + if (mDrawable.isStateful()) { + mDrawable.setState(getDrawableState()); + } } } @@ -820,6 +826,7 @@ public class ImageView extends View { mDrawableHeight = d.getIntrinsicHeight(); applyImageTint(); applyColorMod(); + configureBounds(); } else { mDrawableWidth = mDrawableHeight = -1; @@ -1120,6 +1127,9 @@ public class ImageView extends View { /** @hide */ public void animateTransform(Matrix matrix) { + if (mDrawable == null) { + return; + } if (matrix == null) { mDrawable.setBounds(0, 0, getWidth(), getHeight()); } else { diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java index 3c186e3b9d2b..a31d37e30c7a 100644 --- a/core/java/android/widget/ListPopupWindow.java +++ b/core/java/android/widget/ListPopupWindow.java @@ -1252,14 +1252,7 @@ public class ListPopupWindow { final boolean wasForwarding = mForwarding; final boolean forwarding; if (wasForwarding) { - if (mWasLongPress) { - // If we started forwarding as a result of a long-press, - // just silently stop forwarding events so that the window - // stays open. - forwarding = onTouchForwarded(event); - } else { - forwarding = onTouchForwarded(event) || !onForwardingStopped(); - } + forwarding = onTouchForwarded(event) || !onForwardingStopped(); } else { forwarding = onTouchObserved(event) && onForwardingStarted(); @@ -1639,6 +1632,11 @@ public class ListPopupWindow { setPressed(false); updateSelectorState(); + final View motionView = getChildAt(mMotionPosition - mFirstPosition); + if (motionView != null) { + motionView.setPressed(false); + } + if (mClickAnimation != null) { mClickAnimation.cancel(); mClickAnimation = null; @@ -1653,6 +1651,15 @@ public class ListPopupWindow { setPressed(true); layoutChildren(); + // Manage the pressed view based on motion position. This allows us to + // play nicely with actual touch and scroll events. + final View motionView = getChildAt(mMotionPosition - mFirstPosition); + if (motionView != null) { + motionView.setPressed(false); + } + mMotionPosition = position; + child.setPressed(true); + // Ensure that keyboard focus starts from the last touched position. setSelectedPositionInt(position); positionSelectorLikeTouch(position, child, x, y); diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java index 7b3dd31fd159..a40d4f83a17b 100644 --- a/core/java/android/widget/OverScroller.java +++ b/core/java/android/widget/OverScroller.java @@ -904,6 +904,10 @@ public class OverScroller { final long time = AnimationUtils.currentAnimationTimeMillis(); final long currentTime = time - mStartTime; + if (currentTime == 0) { + // Skip work but report that we're still going if we have a nonzero duration. + return mDuration > 0; + } if (currentTime > mDuration) { return false; } diff --git a/core/java/android/widget/PopupMenu.java b/core/java/android/widget/PopupMenu.java index 111dadc5f868..2708398ae021 100644 --- a/core/java/android/widget/PopupMenu.java +++ b/core/java/android/widget/PopupMenu.java @@ -16,6 +16,7 @@ package android.widget; +import com.android.internal.R; import com.android.internal.view.menu.MenuBuilder; import com.android.internal.view.menu.MenuPopupHelper; import com.android.internal.view.menu.MenuPresenter; @@ -37,10 +38,11 @@ import android.widget.ListPopupWindow.ForwardingListener; * of the popup will dismiss it. */ public class PopupMenu implements MenuBuilder.Callback, MenuPresenter.Callback { - private Context mContext; - private MenuBuilder mMenu; - private View mAnchor; - private MenuPopupHelper mPopup; + private final Context mContext; + private final MenuBuilder mMenu; + private final View mAnchor; + private final MenuPopupHelper mPopup; + private OnMenuItemClickListener mMenuItemClickListener; private OnDismissListener mDismissListener; private OnTouchListener mDragListener; @@ -58,31 +60,56 @@ public class PopupMenu implements MenuBuilder.Callback, MenuPresenter.Callback { } /** - * Construct a new PopupMenu. + * Constructor to create a new popup menu with an anchor view. * - * @param context Context for the PopupMenu. - * @param anchor Anchor view for this popup. The popup will appear below the anchor if there - * is room, or above it if there is not. + * @param context Context the popup menu is running in, through which it + * can access the current theme, resources, etc. + * @param anchor Anchor view for this popup. The popup will appear below + * the anchor if there is room, or above it if there is not. */ public PopupMenu(Context context, View anchor) { this(context, anchor, Gravity.NO_GRAVITY); } /** - * Construct a new PopupMenu. + * Constructor to create a new popup menu with an anchor view and alignment + * gravity. * - * @param context Context for the PopupMenu. - * @param anchor Anchor view for this popup. The popup will appear below the anchor if there - * is room, or above it if there is not. - * @param gravity The {@link Gravity} value for aligning the popup with its anchor + * @param context Context the popup menu is running in, through which it + * can access the current theme, resources, etc. + * @param anchor Anchor view for this popup. The popup will appear below + * the anchor if there is room, or above it if there is not. + * @param gravity The {@link Gravity} value for aligning the popup with its + * anchor. */ public PopupMenu(Context context, View anchor, int gravity) { - // TODO Theme? + this(context, anchor, gravity, R.attr.popupMenuStyle, 0); + } + + /** + * Constructor a create a new popup menu with a specific style. + * + * @param context Context the popup menu is running in, through which it + * can access the current theme, resources, etc. + * @param anchor Anchor view for this popup. The popup will appear below + * the anchor if there is room, or above it if there is not. + * @param gravity The {@link Gravity} value for aligning the popup with its + * anchor. + * @param popupStyleAttr An attribute in the current theme that contains a + * reference to a style resource that supplies default values for + * the popup window. Can be 0 to not look for defaults. + * @param popupStyleRes A resource identifier of a style resource that + * supplies default values for the popup window, used only if + * popupStyleAttr is 0 or can not be found in the theme. Can be 0 + * to not look for defaults. + */ + public PopupMenu(Context context, View anchor, int gravity, int popupStyleAttr, + int popupStyleRes) { mContext = context; mMenu = new MenuBuilder(context); mMenu.setCallback(this); mAnchor = anchor; - mPopup = new MenuPopupHelper(context, mMenu, anchor); + mPopup = new MenuPopupHelper(context, mMenu, anchor, false, popupStyleAttr, popupStyleRes); mPopup.setGravity(gravity); mPopup.setCallback(this); } diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index 41d3e3208ee2..54a7940a0499 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -97,9 +97,11 @@ public class PopupWindow { private boolean mAllowScrollingAnchorParent = true; private boolean mLayoutInsetDecor = false; private boolean mNotTouchModal; + private boolean mAttachedInDecor = true; + private boolean mAttachedInDecorSet = false; private OnTouchListener mTouchInterceptor; - + private int mWidthMode; private int mWidth; private int mLastWidth; @@ -316,6 +318,7 @@ public class PopupWindow { mContext = contentView.getContext(); mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); } + setContentView(contentView); setWidth(width); setHeight(height); @@ -373,16 +376,16 @@ public class PopupWindow { public int getAnimationStyle() { return mAnimationStyle; } - + /** - * Set the flag on popup to ignore cheek press eventt; by default this flag + * Set the flag on popup to ignore cheek press event; by default this flag * is set to false * which means the pop wont ignore cheek press dispatch events. - * + * * <p>If the popup is showing, calling this method will take effect only * the next time the popup is shown or through a manual call to one of * the {@link #update()} methods.</p> - * + * * @see #update() */ public void setIgnoreCheekPress() { @@ -443,6 +446,19 @@ public class PopupWindow { if (mWindowManager == null && mContentView != null) { mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); } + + // Setting the default for attachedInDecor based on SDK version here + // instead of in the constructor since we might not have the context + // object in the constructor. We only want to set default here if the + // app hasn't already set the attachedInDecor. + if (mContext != null && !mAttachedInDecorSet) { + // Attach popup window in decor frame of parent window by default for + // {@link Build.VERSION_CODES.LOLLIPOP_MR1} or greater. Keep current + // behavior of not attaching to decor frame for older SDKs. + setAttachedInDecor(mContext.getApplicationInfo().targetSdkVersion + >= Build.VERSION_CODES.LOLLIPOP_MR1); + } + } /** @@ -452,7 +468,7 @@ public class PopupWindow { public void setTouchInterceptor(OnTouchListener l) { mTouchInterceptor = l; } - + /** * <p>Indicate whether the popup window can grab the focus.</p> * @@ -702,6 +718,36 @@ public class PopupWindow { } /** + * <p>Indicates whether the popup window will be attached in the decor frame of its parent + * window. + * + * @return true if the window will be attached to the decor frame of its parent window. + * + * @see #setAttachedInDecor(boolean) + * @see WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR + */ + public boolean isAttachedInDecor() { + return mAttachedInDecor; + } + + /** + * <p>This will attach the popup window to the decor frame of the parent window to avoid + * overlaping with screen decorations like the navigation bar. Overrides the default behavior of + * the flag {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR}. + * + * <p>By default the flag is set on SDK version {@link Build.VERSION_CODES#LOLLIPOP_MR1} or + * greater and cleared on lesser SDK versions. + * + * @param enabled true if the popup should be attached to the decor frame of its parent window. + * + * @see WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR + */ + public void setAttachedInDecor(boolean enabled) { + mAttachedInDecor = enabled; + mAttachedInDecorSet = true; + } + + /** * Allows the popup window to force the flag * {@link WindowManager.LayoutParams#FLAG_LAYOUT_INSET_DECOR}, overriding default behavior. * This will cause the popup to inset its content to account for system windows overlaying @@ -1140,9 +1186,12 @@ public class PopupWindow { if (mNotTouchModal) { curFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; } + if (mAttachedInDecor) { + curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR; + } return curFlags; } - + private int computeAnimationResource() { if (mAnimationStyle == -1) { if (mIsDropdown) { diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java index e9298c229f4e..887a93b8425f 100644 --- a/core/java/android/widget/ProgressBar.java +++ b/core/java/android/widget/ProgressBar.java @@ -604,6 +604,7 @@ public class ProgressBar extends View { * @see #getIndeterminateTintList() * @see Drawable#setTintList(ColorStateList) */ + @RemotableViewMethod public void setIndeterminateTintList(@Nullable ColorStateList tint) { if (mProgressTintInfo == null) { mProgressTintInfo = new ProgressTintInfo(); @@ -672,6 +673,12 @@ public class ProgressBar extends View { if (tintInfo.mHasIndeterminateTintMode) { mIndeterminateDrawable.setTintMode(tintInfo.mIndeterminateTintMode); } + + // The drawable (or one of its children) may not have been + // stateful before applying the tint, so let's try again. + if (mIndeterminateDrawable.isStateful()) { + mIndeterminateDrawable.setState(getDrawableState()); + } } } } @@ -780,6 +787,12 @@ public class ProgressBar extends View { if (mProgressTintInfo.mHasProgressTintMode) { target.setTintMode(mProgressTintInfo.mProgressTintMode); } + + // The drawable (or one of its children) may not have been + // stateful before applying the tint, so let's try again. + if (target.isStateful()) { + target.setState(getDrawableState()); + } } } } @@ -799,6 +812,12 @@ public class ProgressBar extends View { if (mProgressTintInfo.mHasProgressBackgroundTintMode) { target.setTintMode(mProgressTintInfo.mProgressBackgroundTintMode); } + + // The drawable (or one of its children) may not have been + // stateful before applying the tint, so let's try again. + if (target.isStateful()) { + target.setState(getDrawableState()); + } } } } @@ -818,6 +837,12 @@ public class ProgressBar extends View { if (mProgressTintInfo.mHasSecondaryProgressTintMode) { target.setTintMode(mProgressTintInfo.mSecondaryProgressTintMode); } + + // The drawable (or one of its children) may not have been + // stateful before applying the tint, so let's try again. + if (target.isStateful()) { + target.setState(getDrawableState()); + } } } } @@ -842,6 +867,7 @@ public class ProgressBar extends View { * @see #getProgressTintList() * @see Drawable#setTintList(ColorStateList) */ + @RemotableViewMethod public void setProgressTintList(@Nullable ColorStateList tint) { if (mProgressTintInfo == null) { mProgressTintInfo = new ProgressTintInfo(); @@ -923,6 +949,7 @@ public class ProgressBar extends View { * @see #getProgressBackgroundTintList() * @see Drawable#setTintList(ColorStateList) */ + @RemotableViewMethod public void setProgressBackgroundTintList(@Nullable ColorStateList tint) { if (mProgressTintInfo == null) { mProgressTintInfo = new ProgressTintInfo(); diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java index 56f126cbe447..24fc2bb9a8d2 100644 --- a/core/java/android/widget/RadialTimePickerView.java +++ b/core/java/android/widget/RadialTimePickerView.java @@ -22,21 +22,19 @@ import android.animation.Keyframe; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.animation.ValueAnimator; -import android.annotation.SuppressLint; import android.content.Context; -import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; +import android.graphics.Rect; import android.graphics.Typeface; -import android.graphics.RectF; import android.os.Bundle; -import android.text.format.DateUtils; -import android.text.format.Time; import android.util.AttributeSet; +import android.util.IntArray; import android.util.Log; +import android.util.MathUtils; import android.util.TypedValue; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; @@ -44,10 +42,11 @@ import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import com.android.internal.R; +import com.android.internal.widget.ExploreByTouchHelper; -import java.text.DateFormatSymbols; import java.util.ArrayList; import java.util.Calendar; import java.util.Locale; @@ -69,7 +68,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { private static final int HOURS = 0; private static final int MINUTES = 1; private static final int HOURS_INNER = 2; - private static final int AMPM = 3; private static final int SELECTOR_CIRCLE = 0; private static final int SELECTOR_DOT = 1; @@ -87,12 +85,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { // Alpha level of color for selector. private static final int ALPHA_SELECTOR = 60; // was 51 - // Alpha level of color for selected circle. - private static final int ALPHA_AMPM_SELECTED = ALPHA_SELECTOR; - - // Alpha level of color for pressed circle. - private static final int ALPHA_AMPM_PRESSED = 255; // was 175 - private static final float COSINE_30_DEGREES = ((float) Math.sqrt(3)) * 0.5f; private static final float SINE_30_DEGREES = 0.5f; @@ -105,17 +97,16 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { private static final int CENTER_RADIUS = 2; - private static final int[] STATE_SET_SELECTED = new int[] {R.attr.state_selected}; - private static int[] sSnapPrefer30sMap = new int[361]; + private final InvalidateUpdateListener mInvalidateUpdateListener = + new InvalidateUpdateListener(); + private final String[] mHours12Texts = new String[12]; private final String[] mOuterHours24Texts = new String[12]; private final String[] mInnerHours24Texts = new String[12]; private final String[] mMinutesTexts = new String[12]; - private final String[] mAmPmText = new String[2]; - private final Paint[] mPaint = new Paint[2]; private final int[] mColor = new int[2]; private final IntHolder[] mAlpha = new IntHolder[2]; @@ -126,14 +117,42 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { private final int[][] mColorSelector = new int[2][3]; private final IntHolder[][] mAlphaSelector = new IntHolder[2][3]; - private final Paint mPaintAmPmText = new Paint(); - private final Paint[] mPaintAmPmCircle = new Paint[2]; - private final Paint mPaintBackground = new Paint(); - private final Paint mPaintDisabled = new Paint(); private final Paint mPaintDebug = new Paint(); - private Typeface mTypeface; + private final Typeface mTypeface; + + private final float[] mCircleRadius = new float[3]; + + private final float[] mTextSize = new float[2]; + + private final float[][] mTextGridHeights = new float[2][7]; + private final float[][] mTextGridWidths = new float[2][7]; + + private final float[] mInnerTextGridHeights = new float[7]; + private final float[] mInnerTextGridWidths = new float[7]; + + private final float[] mCircleRadiusMultiplier = new float[2]; + private final float[] mNumbersRadiusMultiplier = new float[3]; + + private final float[] mTextSizeMultiplier = new float[3]; + + private final float[] mAnimationRadiusMultiplier = new float[3]; + + private final float mTransitionMidRadiusMultiplier; + private final float mTransitionEndRadiusMultiplier; + + private final int[] mLineLength = new int[3]; + private final int[] mSelectionRadius = new int[3]; + private final float mSelectionRadiusMultiplier; + private final int[] mSelectionDegrees = new int[3]; + + private final ArrayList<Animator> mHoursToMinutesAnims = new ArrayList<Animator>(); + private final ArrayList<Animator> mMinuteToHoursAnims = new ArrayList<Animator>(); + + private final RadialPickerTouchHelper mTouchHelper; + + private float mInnerTextSize; private boolean mIs24HourMode; private boolean mShowHours; @@ -147,66 +166,21 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { private int mXCenter; private int mYCenter; - private float[] mCircleRadius = new float[3]; - private int mMinHypotenuseForInnerNumber; private int mMaxHypotenuseForOuterNumber; private int mHalfwayHypotenusePoint; - private float[] mTextSize = new float[2]; - private float mInnerTextSize; - - private float[][] mTextGridHeights = new float[2][7]; - private float[][] mTextGridWidths = new float[2][7]; - - private float[] mInnerTextGridHeights = new float[7]; - private float[] mInnerTextGridWidths = new float[7]; - private String[] mOuterTextHours; private String[] mInnerTextHours; private String[] mOuterTextMinutes; - - private float[] mCircleRadiusMultiplier = new float[2]; - private float[] mNumbersRadiusMultiplier = new float[3]; - - private float[] mTextSizeMultiplier = new float[3]; - - private float[] mAnimationRadiusMultiplier = new float[3]; - - private float mTransitionMidRadiusMultiplier; - private float mTransitionEndRadiusMultiplier; - private AnimatorSet mTransition; - private InvalidateUpdateListener mInvalidateUpdateListener = new InvalidateUpdateListener(); - - private int[] mLineLength = new int[3]; - private int[] mSelectionRadius = new int[3]; - private float mSelectionRadiusMultiplier; - private int[] mSelectionDegrees = new int[3]; - - private int mAmPmCircleRadius; - private float mAmPmYCenter; - - private float mAmPmCircleRadiusMultiplier; - private int mAmPmTextColor; - - private float mLeftIndicatorXCenter; - private float mRightIndicatorXCenter; - - private int mAmPmUnselectedColor; - private int mAmPmSelectedColor; private int mAmOrPm; - private int mAmOrPmPressed; - private int mDisabledAlpha; - private RectF mRectF = new RectF(); - private boolean mInputEnabled = true; private OnValueSelectedListener mListener; - private final ArrayList<Animator> mHoursToMinutesAnims = new ArrayList<Animator>(); - private final ArrayList<Animator> mMinuteToHoursAnims = new ArrayList<Animator>(); + private boolean mInputEnabled = true; public interface OnValueSelectedListener { void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance); @@ -314,11 +288,21 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { return degrees; } + @SuppressWarnings("unused") + public RadialTimePickerView(Context context) { + this(context, null); + } + public RadialTimePickerView(Context context, AttributeSet attrs) { this(context, attrs, R.attr.timePickerStyle); } - public RadialTimePickerView(Context context, AttributeSet attrs, int defStyle) { + public RadialTimePickerView(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public RadialTimePickerView( + Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs); // Pull disabled alpha from theme. @@ -329,28 +313,7 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { // process style attributes final Resources res = getResources(); final TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.TimePicker, - defStyle, 0); - - ColorStateList amPmBackgroundColor = a.getColorStateList( - R.styleable.TimePicker_amPmBackgroundColor); - if (amPmBackgroundColor == null) { - amPmBackgroundColor = res.getColorStateList( - R.color.timepicker_default_ampm_unselected_background_color_material); - } - - // Obtain the backup selected color. If the background color state - // list doesn't have a state for selected, we'll use this color. - final int amPmSelectedColor = a.getColor(R.styleable.TimePicker_amPmSelectedBackgroundColor, - res.getColor(R.color.timepicker_default_ampm_selected_background_color_material)); - amPmBackgroundColor = ColorStateList.addFirstIfMissing( - amPmBackgroundColor, R.attr.state_selected, amPmSelectedColor); - - mAmPmSelectedColor = amPmBackgroundColor.getColorForState( - STATE_SET_SELECTED, amPmSelectedColor); - mAmPmUnselectedColor = amPmBackgroundColor.getDefaultColor(); - - mAmPmTextColor = a.getColor(R.styleable.TimePicker_amPmTextColor, - res.getColor(R.color.timepicker_default_text_color_material)); + defStyleAttr, defStyleRes); mTypeface = Typeface.create("sans-serif", Typeface.NORMAL); @@ -419,16 +382,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { R.styleable.TimePicker_numbersSelectorColor, R.color.timepicker_default_selector_color_material); - mPaintAmPmText.setColor(mAmPmTextColor); - mPaintAmPmText.setTypeface(mTypeface); - mPaintAmPmText.setAntiAlias(true); - mPaintAmPmText.setTextAlign(Paint.Align.CENTER); - - mPaintAmPmCircle[AM] = new Paint(); - mPaintAmPmCircle[AM].setAntiAlias(true); - mPaintAmPmCircle[PM] = new Paint(); - mPaintAmPmCircle[PM].setAntiAlias(true); - mPaintBackground.setColor(a.getColor(R.styleable.TimePicker_numbersBackgroundColor, res.getColor(R.color.timepicker_default_numbers_background_color_material))); mPaintBackground.setAntiAlias(true); @@ -444,7 +397,14 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { mShowHours = true; mIs24HourMode = false; mAmOrPm = AM; - mAmOrPmPressed = -1; + + // Set up accessibility components. + mTouchHelper = new RadialPickerTouchHelper(); + setAccessibilityDelegate(mTouchHelper); + + if (getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { + setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); + } initHoursAndMinutesText(); initData(); @@ -470,8 +430,8 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { final int currentHour = calendar.get(Calendar.HOUR_OF_DAY); final int currentMinute = calendar.get(Calendar.MINUTE); - setCurrentHour(currentHour); - setCurrentMinute(currentMinute); + setCurrentHourInternal(currentHour, false, false); + setCurrentMinuteInternal(currentMinute, false); setHapticFeedbackEnabled(true); } @@ -493,8 +453,9 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { public void initialize(int hour, int minute, boolean is24HourMode) { mIs24HourMode = is24HourMode; - setCurrentHour(hour); - setCurrentMinute(minute); + + setCurrentHourInternal(hour, false, false); + setCurrentMinuteInternal(minute, false); } public void setCurrentItemShowing(int item, boolean animate) { @@ -524,23 +485,39 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { * @param hour the current hour between 0 and 23 (inclusive) */ public void setCurrentHour(int hour) { + setCurrentHourInternal(hour, true, false); + } + + /** + * Sets the current hour. + * + * @param hour The current hour + * @param callback Whether the value listener should be invoked + * @param autoAdvance Whether the listener should auto-advance to the next + * selection mode, e.g. hour to minutes + */ + private void setCurrentHourInternal(int hour, boolean callback, boolean autoAdvance) { final int degrees = (hour % 12) * DEGREES_FOR_ONE_HOUR; mSelectionDegrees[HOURS] = degrees; mSelectionDegrees[HOURS_INNER] = degrees; // 0 is 12 AM (midnight) and 12 is 12 PM (noon). - mAmOrPm = (hour == 0 || (hour % 24) < 12) ? AM : PM; - - if (mIs24HourMode) { - // Inner circle is 1 through 12. - mIsOnInnerCircle = hour >= 1 && hour <= 12; - } else { - mIsOnInnerCircle = false; + final int amOrPm = (hour == 0 || (hour % 24) < 12) ? AM : PM; + final boolean isOnInnerCircle = mIs24HourMode && hour >= 1 && hour <= 12; + if (mAmOrPm != amOrPm || mIsOnInnerCircle != isOnInnerCircle) { + mAmOrPm = amOrPm; + mIsOnInnerCircle = isOnInnerCircle; + + initData(); + updateLayoutData(); + mTouchHelper.invalidateRoot(); } - initData(); - updateLayoutData(); invalidate(); + + if (callback && mListener != null) { + mListener.onValueSelected(HOURS, hour, autoAdvance); + } } /** @@ -549,15 +526,19 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { * @return the current hour between 0 and 23 (inclusive) */ public int getCurrentHour() { - int hour = (mSelectionDegrees[mIsOnInnerCircle ? - HOURS_INNER : HOURS] / DEGREES_FOR_ONE_HOUR) % 12; + return getHourForDegrees( + mSelectionDegrees[mIsOnInnerCircle ? HOURS_INNER : HOURS], mIsOnInnerCircle); + } + + private int getHourForDegrees(int degrees, boolean innerCircle) { + int hour = (degrees / DEGREES_FOR_ONE_HOUR) % 12; if (mIs24HourMode) { // Convert the 12-hour value into 24-hour time based on where the // selector is positioned. - if (mIsOnInnerCircle && hour == 0) { + if (innerCircle && hour == 0) { // Inner circle is 1 through 12. hour = 12; - } else if (!mIsOnInnerCircle && hour != 0) { + } else if (!innerCircle && hour != 0) { // Outer circle is 13 through 23 and 0. hour += 12; } @@ -567,30 +548,55 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { return hour; } + private int getDegreesForHour(int hour) { + // Convert to be 0-11. + if (mIs24HourMode) { + if (hour >= 12) { + hour -= 12; + } + } else if (hour == 12) { + hour = 0; + } + return hour * DEGREES_FOR_ONE_HOUR; + } + public void setCurrentMinute(int minute) { + setCurrentMinuteInternal(minute, true); + } + + private void setCurrentMinuteInternal(int minute, boolean callback) { mSelectionDegrees[MINUTES] = (minute % 60) * DEGREES_FOR_ONE_MINUTE; + invalidate(); + + if (callback && mListener != null) { + mListener.onValueSelected(MINUTES, minute, false); + } } // Returns minutes in 0-59 range public int getCurrentMinute() { - return (mSelectionDegrees[MINUTES] / DEGREES_FOR_ONE_MINUTE); + return getMinuteForDegrees(mSelectionDegrees[MINUTES]); + } + + private int getMinuteForDegrees(int degrees) { + return degrees / DEGREES_FOR_ONE_MINUTE; + } + + private int getDegreesForMinute(int minute) { + return minute * DEGREES_FOR_ONE_MINUTE; } public void setAmOrPm(int val) { mAmOrPm = (val % 2); invalidate(); + mTouchHelper.invalidateRoot(); } public int getAmOrPm() { return mAmOrPm; } - public void swapAmPm() { - mAmOrPm = (mAmOrPm == AM) ? PM : AM; - invalidate(); - } - public void showHours(boolean animate) { if (mShowHours) return; mShowHours = true; @@ -621,10 +627,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { mInnerHours24Texts[i] = String.format("%d", HOURS_NUMBERS[i]); mMinutesTexts[i] = String.format("%02d", MINUTES_NUMBERS[i]); } - - String[] amPmStrings = TimePickerClockDelegate.getAmPmStrings(mContext); - mAmPmText[AM] = amPmStrings[0]; - mAmPmText[PM] = amPmStrings[1]; } private void initData() { @@ -674,9 +676,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { mAnimationRadiusMultiplier[HOURS_INNER] = 1; mAnimationRadiusMultiplier[MINUTES] = 1; - mAmPmCircleRadiusMultiplier = Float.parseFloat( - res.getString(R.string.timepicker_ampm_circle_radius_multiplier)); - mAlpha[HOURS].setValue(mShowHours ? ALPHA_OPAQUE : ALPHA_TRANSPARENT); mAlpha[MINUTES].setValue(mShowHours ? ALPHA_TRANSPARENT : ALPHA_OPAQUE); @@ -710,14 +709,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { mCircleRadius[HOURS_INNER] = min * mCircleRadiusMultiplier[HOURS]; mCircleRadius[MINUTES] = min * mCircleRadiusMultiplier[MINUTES]; - if (!mIs24HourMode) { - // We'll need to draw the AM/PM circles, so the main circle will need to have - // a slightly higher center. To keep the entire view centered vertically, we'll - // have to push it up by half the radius of the AM/PM circles. - int amPmCircleRadius = (int) (mCircleRadius[HOURS] * mAmPmCircleRadiusMultiplier); - mYCenter -= amPmCircleRadius / 2; - } - mMinHypotenuseForInnerNumber = (int) (mCircleRadius[HOURS] * mNumbersRadiusMultiplier[HOURS_INNER]) - mSelectionRadius[HOURS]; mMaxHypotenuseForOuterNumber = (int) (mCircleRadius[HOURS] @@ -739,16 +730,7 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { mSelectionRadius[HOURS_INNER] = mSelectionRadius[HOURS]; mSelectionRadius[MINUTES] = (int) (mCircleRadius[MINUTES] * mSelectionRadiusMultiplier); - mAmPmCircleRadius = (int) (mCircleRadius[HOURS] * mAmPmCircleRadiusMultiplier); - mPaintAmPmText.setTextSize(mAmPmCircleRadius * 3 / 4); - - // Line up the vertical center of the AM/PM circles with the bottom of the main circle. - mAmPmYCenter = mYCenter + mCircleRadius[HOURS]; - - // Line up the horizontal edges of the AM/PM circles with the horizontal edges - // of the main circle - mLeftIndicatorXCenter = mXCenter - mCircleRadius[HOURS] + mAmPmCircleRadius; - mRightIndicatorXCenter = mXCenter + mCircleRadius[HOURS] - mAmPmCircleRadius; + mTouchHelper.invalidateRoot(); } @Override @@ -780,9 +762,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { mColor[MINUTES], mAlpha[MINUTES].getValue()); drawCenter(canvas); - if (!mIs24HourMode) { - drawAmPm(canvas); - } if (DEBUG) { drawDebug(canvas); @@ -804,50 +783,6 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { drawSelector(canvas, MINUTES); } - private void drawAmPm(Canvas canvas) { - final boolean isLayoutRtl = isLayoutRtl(); - - int amColor = mAmPmUnselectedColor; - int amAlpha = ALPHA_OPAQUE; - int pmColor = mAmPmUnselectedColor; - int pmAlpha = ALPHA_OPAQUE; - if (mAmOrPm == AM) { - amColor = mAmPmSelectedColor; - amAlpha = ALPHA_AMPM_SELECTED; - } else if (mAmOrPm == PM) { - pmColor = mAmPmSelectedColor; - pmAlpha = ALPHA_AMPM_SELECTED; - } - if (mAmOrPmPressed == AM) { - amColor = mAmPmSelectedColor; - amAlpha = ALPHA_AMPM_PRESSED; - } else if (mAmOrPmPressed == PM) { - pmColor = mAmPmSelectedColor; - pmAlpha = ALPHA_AMPM_PRESSED; - } - - // Draw the two circles - mPaintAmPmCircle[AM].setColor(amColor); - mPaintAmPmCircle[AM].setAlpha(getMultipliedAlpha(amColor, amAlpha)); - canvas.drawCircle(isLayoutRtl ? mRightIndicatorXCenter : mLeftIndicatorXCenter, - mAmPmYCenter, mAmPmCircleRadius, mPaintAmPmCircle[AM]); - - mPaintAmPmCircle[PM].setColor(pmColor); - mPaintAmPmCircle[PM].setAlpha(getMultipliedAlpha(pmColor, pmAlpha)); - canvas.drawCircle(isLayoutRtl ? mLeftIndicatorXCenter : mRightIndicatorXCenter, - mAmPmYCenter, mAmPmCircleRadius, mPaintAmPmCircle[PM]); - - // Draw the AM/PM texts on top - mPaintAmPmText.setColor(mAmPmTextColor); - float textYCenter = mAmPmYCenter - - (int) (mPaintAmPmText.descent() + mPaintAmPmText.ascent()) / 2; - - canvas.drawText(isLayoutRtl ? mAmPmText[PM] : mAmPmText[AM], mLeftIndicatorXCenter, - textYCenter, mPaintAmPmText); - canvas.drawText(isLayoutRtl ? mAmPmText[AM] : mAmPmText[PM], mRightIndicatorXCenter, - textYCenter, mPaintAmPmText); - } - private int getMultipliedAlpha(int argb, int alpha) { return (int) (Color.alpha(argb) * (alpha / 255.0) + 0.5); } @@ -917,20 +852,17 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { float top = mYCenter - outerRadius; float right = mXCenter + outerRadius; float bottom = mYCenter + outerRadius; - mRectF = new RectF(left, top, right, bottom); - canvas.drawRect(mRectF, mPaintDebug); + canvas.drawRect(left, top, right, bottom, mPaintDebug); // Draw outer rectangle for background left = mXCenter - mCircleRadius[HOURS]; top = mYCenter - mCircleRadius[HOURS]; right = mXCenter + mCircleRadius[HOURS]; bottom = mYCenter + mCircleRadius[HOURS]; - mRectF.set(left, top, right, bottom); - canvas.drawRect(mRectF, mPaintDebug); + canvas.drawRect(left, top, right, bottom, mPaintDebug); // Draw outer view rectangle - mRectF.set(0, 0, getWidth(), getHeight()); - canvas.drawRect(mRectF, mPaintDebug); + canvas.drawRect(0, 0, getWidth(), getHeight(), mPaintDebug); // Draw selected time final String selected = String.format("%02d:%02d", getCurrentHour(), getCurrentMinute()); @@ -950,7 +882,7 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { float x = mXCenter - width / 2; float y = mYCenter + 1.5f * height; - canvas.drawText(selected.toString(), x, y, paint); + canvas.drawText(selected, x, y, paint); } private void calculateGridSizesHours() { @@ -1044,12 +976,14 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { } // Used for animating the hours by changing their radius + @SuppressWarnings("unused") private void setAnimationRadiusMultiplierHours(float animationRadiusMultiplier) { mAnimationRadiusMultiplier[HOURS] = animationRadiusMultiplier; mAnimationRadiusMultiplier[HOURS_INNER] = animationRadiusMultiplier; } // Used for animating the minutes by changing their radius + @SuppressWarnings("unused") private void setAnimationRadiusMultiplierMinutes(float animationRadiusMultiplier) { mAnimationRadiusMultiplier[MINUTES] = animationRadiusMultiplier; } @@ -1242,41 +1176,25 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { } final float opposite = Math.abs(y - mYCenter); - double degrees = Math.toDegrees(Math.asin(opposite / hypotenuse)); + int degrees = (int) (Math.toDegrees(Math.asin(opposite / hypotenuse)) + 0.5); // Now we have to translate to the correct quadrant. - boolean rightSide = (x > mXCenter); - boolean topSide = (y < mYCenter); - if (rightSide && topSide) { - degrees = 90 - degrees; - } else if (rightSide && !topSide) { - degrees = 90 + degrees; - } else if (!rightSide && !topSide) { - degrees = 270 - degrees; - } else if (!rightSide && topSide) { - degrees = 270 + degrees; - } - return (int) degrees; - } - - private int getIsTouchingAmOrPm(float x, float y) { - final boolean isLayoutRtl = isLayoutRtl(); - int squaredYDistance = (int) ((y - mAmPmYCenter) * (y - mAmPmYCenter)); - - int distanceToAmCenter = (int) Math.sqrt( - (x - mLeftIndicatorXCenter) * (x - mLeftIndicatorXCenter) + squaredYDistance); - if (distanceToAmCenter <= mAmPmCircleRadius) { - return (isLayoutRtl ? PM : AM); - } - - int distanceToPmCenter = (int) Math.sqrt( - (x - mRightIndicatorXCenter) * (x - mRightIndicatorXCenter) + squaredYDistance); - if (distanceToPmCenter <= mAmPmCircleRadius) { - return (isLayoutRtl ? AM : PM); + final boolean rightSide = (x > mXCenter); + final boolean topSide = (y < mYCenter); + if (rightSide) { + if (topSide) { + degrees = 90 - degrees; + } else { + degrees = 90 + degrees; + } + } else { + if (topSide) { + degrees = 270 + degrees; + } else { + degrees = 270 - degrees; + } } - - // Neither was close enough. - return -1; + return degrees; } @Override @@ -1295,181 +1213,326 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { switch(event.getAction()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: - mAmOrPmPressed = getIsTouchingAmOrPm(eventX, eventY); - if (mAmOrPmPressed != -1) { - result = true; - } else { - degrees = getDegreesFromXY(eventX, eventY); - if (degrees != -1) { - snapDegrees = (mShowHours ? - snapOnly30s(degrees, 0) : snapPrefer30s(degrees)) % 360; + degrees = getDegreesFromXY(eventX, eventY); + if (degrees != -1) { + snapDegrees = (mShowHours ? + snapOnly30s(degrees, 0) : snapPrefer30s(degrees)) % 360; + if (mShowHours) { + mSelectionDegrees[HOURS] = snapDegrees; + mSelectionDegrees[HOURS_INNER] = snapDegrees; + } else { + mSelectionDegrees[MINUTES] = snapDegrees; + } + performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK); + if (mListener != null) { if (mShowHours) { - mSelectionDegrees[HOURS] = snapDegrees; - mSelectionDegrees[HOURS_INNER] = snapDegrees; - } else { - mSelectionDegrees[MINUTES] = snapDegrees; - } - performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK); - if (mListener != null) { - if (mShowHours) { - mListener.onValueSelected(HOURS, getCurrentHour(), false); - } else { - mListener.onValueSelected(MINUTES, getCurrentMinute(), false); - } + mListener.onValueSelected(HOURS, getCurrentHour(), false); + } else { + mListener.onValueSelected(MINUTES, getCurrentMinute(), false); } - result = true; } + result = true; + invalidate(); } - invalidate(); - return result; + break; case MotionEvent.ACTION_UP: - mAmOrPmPressed = getIsTouchingAmOrPm(eventX, eventY); - if (mAmOrPmPressed != -1) { - if (mAmOrPm != mAmOrPmPressed) { - swapAmPm(); + degrees = getDegreesFromXY(eventX, eventY); + if (degrees != -1) { + snapDegrees = (mShowHours ? + snapOnly30s(degrees, 0) : snapPrefer30s(degrees)) % 360; + if (mShowHours) { + mSelectionDegrees[HOURS] = snapDegrees; + mSelectionDegrees[HOURS_INNER] = snapDegrees; + } else { + mSelectionDegrees[MINUTES] = snapDegrees; } - mAmOrPmPressed = -1; if (mListener != null) { - mListener.onValueSelected(AMPM, getCurrentHour(), true); - } - result = true; - } else { - degrees = getDegreesFromXY(eventX, eventY); - if (degrees != -1) { - snapDegrees = (mShowHours ? - snapOnly30s(degrees, 0) : snapPrefer30s(degrees)) % 360; if (mShowHours) { - mSelectionDegrees[HOURS] = snapDegrees; - mSelectionDegrees[HOURS_INNER] = snapDegrees; - } else { - mSelectionDegrees[MINUTES] = snapDegrees; + mListener.onValueSelected(HOURS, getCurrentHour(), true); + } else { + mListener.onValueSelected(MINUTES, getCurrentMinute(), true); } - if (mListener != null) { - if (mShowHours) { - mListener.onValueSelected(HOURS, getCurrentHour(), true); - } else { - mListener.onValueSelected(MINUTES, getCurrentMinute(), true); - } - } - result = true; } - } - if (result) { invalidate(); + result = true; } - return result; - - default: break; } - return false; + return result; } - /** - * Necessary for accessibility, to ensure we support "scrolling" forward and backward - * in the circle. - */ - @Override - public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(info); - info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); - info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); - } - - /** - * Announce the currently-selected time when launched. - */ @Override - public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { - if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { - // Clear the event's current text so that only the current time will be spoken. - event.getText().clear(); - Time time = new Time(); - time.hour = getCurrentHour(); - time.minute = getCurrentMinute(); - long millis = time.normalize(true); - int flags = DateUtils.FORMAT_SHOW_TIME; - if (mIs24HourMode) { - flags |= DateUtils.FORMAT_24HOUR; - } - String timeString = DateUtils.formatDateTime(getContext(), millis, flags); - event.getText().add(timeString); + public boolean dispatchHoverEvent(MotionEvent event) { + // First right-of-refusal goes the touch exploration helper. + if (mTouchHelper.dispatchHoverEvent(event)) { return true; } - return super.dispatchPopulateAccessibilityEvent(event); + return super.dispatchHoverEvent(event); } - /** - * When scroll forward/backward events are received, jump the time to the higher/lower - * discrete, visible value on the circle. - */ - @SuppressLint("NewApi") - @Override - public boolean performAccessibilityAction(int action, Bundle arguments) { - if (super.performAccessibilityAction(action, arguments)) { - return true; + public void setInputEnabled(boolean inputEnabled) { + mInputEnabled = inputEnabled; + invalidate(); + } + + private class RadialPickerTouchHelper extends ExploreByTouchHelper { + private final Rect mTempRect = new Rect(); + + private final int TYPE_HOUR = 1; + private final int TYPE_MINUTE = 2; + + private final int SHIFT_TYPE = 0; + private final int MASK_TYPE = 0xF; + + private final int SHIFT_VALUE = 8; + private final int MASK_VALUE = 0xFF; + + /** Increment in which virtual views are exposed for minutes. */ + private final int MINUTE_INCREMENT = 5; + + public RadialPickerTouchHelper() { + super(RadialTimePickerView.this); } - int changeMultiplier = 0; - if (action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD) { - changeMultiplier = 1; - } else if (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD) { - changeMultiplier = -1; + @Override + public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(host, info); + + info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD); + info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD); } - if (changeMultiplier != 0) { - int value = 0; - int stepSize = 0; - if (mShowHours) { - stepSize = DEGREES_FOR_ONE_HOUR; - value = getCurrentHour() % 12; - } else { - stepSize = DEGREES_FOR_ONE_MINUTE; - value = getCurrentMinute(); + + @Override + public boolean performAccessibilityAction(View host, int action, Bundle arguments) { + if (super.performAccessibilityAction(host, action, arguments)) { + return true; + } + + switch (action) { + case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: + adjustPicker(1); + return true; + case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: + adjustPicker(-1); + return true; } - int degrees = value * stepSize; - degrees = snapOnly30s(degrees, changeMultiplier); - value = degrees / stepSize; - int maxValue = 0; - int minValue = 0; + return false; + } + + private void adjustPicker(int step) { + final int stepSize; + final int initialValue; + final int maxValue; + final int minValue; if (mShowHours) { + stepSize = DEGREES_FOR_ONE_HOUR; + initialValue = getCurrentHour() % 12; + if (mIs24HourMode) { maxValue = 23; + minValue = 0; } else { maxValue = 12; minValue = 1; } } else { + stepSize = DEGREES_FOR_ONE_MINUTE; + initialValue = getCurrentMinute(); + maxValue = 55; + minValue = 0; } - if (value > maxValue) { - // If we scrolled forward past the highest number, wrap around to the lowest. - value = minValue; - } else if (value < minValue) { - // If we scrolled backward past the lowest number, wrap around to the highest. - value = maxValue; + + final int steppedValue = snapOnly30s(initialValue * stepSize, step) / stepSize; + final int clampedValue = MathUtils.constrain(steppedValue, minValue, maxValue); + if (mShowHours) { + setCurrentHour(clampedValue); + } else { + setCurrentMinute(clampedValue); } + } + + @Override + protected int getVirtualViewAt(float x, float y) { + final int id; + final int degrees = getDegreesFromXY(x, y); + if (degrees != -1) { + final int snapDegrees = snapOnly30s(degrees, 0) % 360; + if (mShowHours) { + final int hour = getHourForDegrees(snapDegrees, mIsOnInnerCircle); + id = makeId(TYPE_HOUR, hour); + } else { + final int current = getCurrentMinute(); + final int touched = getMinuteForDegrees(degrees); + final int snapped = getMinuteForDegrees(snapDegrees); + + // If the touched minute is closer to the current minute + // than it is to the snapped minute, return current. + final int minute; + if (Math.abs(current - touched) < Math.abs(snapped - touched)) { + minute = current; + } else { + minute = snapped; + } + id = makeId(TYPE_MINUTE, minute); + } + } else { + id = INVALID_ID; + } + + return id; + } + + @Override + protected void getVisibleVirtualViews(IntArray virtualViewIds) { if (mShowHours) { - setCurrentHour(value); - if (mListener != null) { - mListener.onValueSelected(HOURS, value, false); + final int min = mIs24HourMode ? 0 : 1; + final int max = mIs24HourMode ? 23 : 12; + for (int i = min; i <= max ; i++) { + virtualViewIds.add(makeId(TYPE_HOUR, i)); } } else { - setCurrentMinute(value); - if (mListener != null) { - mListener.onValueSelected(MINUTES, value, false); + final int current = getCurrentMinute(); + for (int i = 0; i < 60; i += MINUTE_INCREMENT) { + virtualViewIds.add(makeId(TYPE_MINUTE, i)); + + // If the current minute falls between two increments, + // insert an extra node for it. + if (current > i && current < i + MINUTE_INCREMENT) { + virtualViewIds.add(makeId(TYPE_MINUTE, current)); + } } } - return true; } - return false; - } + @Override + protected void onPopulateEventForVirtualView(int virtualViewId, AccessibilityEvent event) { + event.setClassName(getClass().getName()); - public void setInputEnabled(boolean inputEnabled) { - mInputEnabled = inputEnabled; - invalidate(); + final int type = getTypeFromId(virtualViewId); + final int value = getValueFromId(virtualViewId); + final CharSequence description = getVirtualViewDescription(type, value); + event.setContentDescription(description); + } + + @Override + protected void onPopulateNodeForVirtualView(int virtualViewId, AccessibilityNodeInfo node) { + node.setClassName(getClass().getName()); + node.addAction(AccessibilityAction.ACTION_CLICK); + + final int type = getTypeFromId(virtualViewId); + final int value = getValueFromId(virtualViewId); + final CharSequence description = getVirtualViewDescription(type, value); + node.setContentDescription(description); + + getBoundsForVirtualView(virtualViewId, mTempRect); + node.setBoundsInParent(mTempRect); + + final boolean selected = isVirtualViewSelected(type, value); + node.setSelected(selected); + } + + @Override + protected boolean onPerformActionForVirtualView(int virtualViewId, int action, + Bundle arguments) { + if (action == AccessibilityNodeInfo.ACTION_CLICK) { + final int type = getTypeFromId(virtualViewId); + final int value = getValueFromId(virtualViewId); + if (type == TYPE_HOUR) { + final int hour = mIs24HourMode ? value : hour12To24(value, mAmOrPm); + setCurrentHour(hour); + return true; + } else if (type == TYPE_MINUTE) { + setCurrentMinute(value); + return true; + } + } + return false; + } + + private int hour12To24(int hour12, int amOrPm) { + int hour24 = hour12; + if (hour12 == 12) { + if (amOrPm == AM) { + hour24 = 0; + } + } else if (amOrPm == PM) { + hour24 += 12; + } + return hour24; + } + + private void getBoundsForVirtualView(int virtualViewId, Rect bounds) { + final float radius; + final int type = getTypeFromId(virtualViewId); + final int value = getValueFromId(virtualViewId); + final float centerRadius; + final float degrees; + if (type == TYPE_HOUR) { + final boolean innerCircle = mIs24HourMode && value > 0 && value <= 12; + if (innerCircle) { + centerRadius = mCircleRadius[HOURS_INNER] * mNumbersRadiusMultiplier[HOURS_INNER]; + radius = mSelectionRadius[HOURS_INNER]; + } else { + centerRadius = mCircleRadius[HOURS] * mNumbersRadiusMultiplier[HOURS]; + radius = mSelectionRadius[HOURS]; + } + + degrees = getDegreesForHour(value); + } else if (type == TYPE_MINUTE) { + centerRadius = mCircleRadius[MINUTES] * mNumbersRadiusMultiplier[MINUTES]; + degrees = getDegreesForMinute(value); + radius = mSelectionRadius[MINUTES]; + } else { + // This should never happen. + centerRadius = 0; + degrees = 0; + radius = 0; + } + + final double radians = Math.toRadians(degrees); + final float xCenter = mXCenter + centerRadius * (float) Math.sin(radians); + final float yCenter = mYCenter - centerRadius * (float) Math.cos(radians); + + bounds.set((int) (xCenter - radius), (int) (yCenter - radius), + (int) (xCenter + radius), (int) (yCenter + radius)); + } + + private CharSequence getVirtualViewDescription(int type, int value) { + final CharSequence description; + if (type == TYPE_HOUR || type == TYPE_MINUTE) { + description = Integer.toString(value); + } else { + description = null; + } + return description; + } + + private boolean isVirtualViewSelected(int type, int value) { + final boolean selected; + if (type == TYPE_HOUR) { + selected = getCurrentHour() == value; + } else if (type == TYPE_MINUTE) { + selected = getCurrentMinute() == value; + } else { + selected = false; + } + return selected; + } + + private int makeId(int type, int value) { + return type << SHIFT_TYPE | value << SHIFT_VALUE; + } + + private int getTypeFromId(int id) { + return id >>> SHIFT_TYPE & MASK_TYPE; + } + + private int getValueFromId(int id) { + return id >>> SHIFT_VALUE & MASK_VALUE; + } } private static class IntHolder { diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 7cb3c378ace0..dd7fa18468c2 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -27,6 +27,7 @@ import android.content.Intent; import android.content.IntentSender; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Bitmap; @@ -1069,6 +1070,7 @@ public class RemoteViews implements Parcelable, Filter { static final int BITMAP = 12; static final int BUNDLE = 13; static final int INTENT = 14; + static final int COLOR_STATE_LIST = 15; String methodName; int type; @@ -1142,6 +1144,11 @@ public class RemoteViews implements Parcelable, Filter { this.value = Intent.CREATOR.createFromParcel(in); } break; + case COLOR_STATE_LIST: + if (in.readInt() != 0) { + this.value = ColorStateList.CREATOR.createFromParcel(in); + } + break; default: break; } @@ -1212,6 +1219,11 @@ public class RemoteViews implements Parcelable, Filter { ((Intent)this.value).writeToParcel(out, flags); } break; + case COLOR_STATE_LIST: + out.writeInt(this.value != null ? 1 : 0); + if (this.value != null) { + ((ColorStateList)this.value).writeToParcel(out, flags); + } default: break; } @@ -1247,6 +1259,8 @@ public class RemoteViews implements Parcelable, Filter { return Bundle.class; case INTENT: return Intent.class; + case COLOR_STATE_LIST: + return ColorStateList.class; default: return null; } @@ -2207,6 +2221,42 @@ public class RemoteViews implements Parcelable, Filter { } /** + * @hide + * Equivalent to calling {@link android.widget.ProgressBar#setProgressTintList}. + * + * @param viewId The id of the view whose tint should change + * @param tint the tint to apply, may be {@code null} to clear tint + */ + public void setProgressTintList(int viewId, ColorStateList tint) { + addAction(new ReflectionAction(viewId, "setProgressTintList", + ReflectionAction.COLOR_STATE_LIST, tint)); + } + + /** + * @hide + * Equivalent to calling {@link android.widget.ProgressBar#setProgressBackgroundTintList}. + * + * @param viewId The id of the view whose tint should change + * @param tint the tint to apply, may be {@code null} to clear tint + */ + public void setProgressBackgroundTintList(int viewId, ColorStateList tint) { + addAction(new ReflectionAction(viewId, "setProgressBackgroundTintList", + ReflectionAction.COLOR_STATE_LIST, tint)); + } + + /** + * @hide + * Equivalent to calling {@link android.widget.ProgressBar#setIndeterminateTintList}. + * + * @param viewId The id of the view whose tint should change + * @param tint the tint to apply, may be {@code null} to clear tint + */ + public void setProgressIndeterminateTintList(int viewId, ColorStateList tint) { + addAction(new ReflectionAction(viewId, "setIndeterminateTintList", + ReflectionAction.COLOR_STATE_LIST, tint)); + } + + /** * Equivalent to calling {@link android.widget.TextView#setTextColor(int)}. * * @param viewId The id of the view whose text color should change @@ -2478,6 +2528,26 @@ public class RemoteViews implements Parcelable, Filter { } /** + * Equivalent to calling {@link android.view.View#setAccessibilityTraversalBefore(int)}. + * + * @param viewId The id of the view whose before view in accessibility traversal to set. + * @param nextId The id of the next in the accessibility traversal. + **/ + public void setAccessibilityTraversalBefore(int viewId, int nextId) { + setInt(viewId, "setAccessibilityTraversalBefore", nextId); + } + + /** + * Equivalent to calling {@link android.view.View#setAccessibilityTraversalAfter(int)}. + * + * @param viewId The id of the view whose after view in accessibility traversal to set. + * @param nextId The id of the next in the accessibility traversal. + **/ + public void setAccessibilityTraversalAfter(int viewId, int nextId) { + setInt(viewId, "setAccessibilityTraversalAfter", nextId); + } + + /** * Equivalent to calling View.setLabelFor(int). * * @param viewId The id of the view whose property to set. diff --git a/core/java/android/widget/SimpleMonthAdapter.java b/core/java/android/widget/SimpleMonthAdapter.java index 3bad235ebff5..5aa78c87e546 100644 --- a/core/java/android/widget/SimpleMonthAdapter.java +++ b/core/java/android/widget/SimpleMonthAdapter.java @@ -28,21 +28,30 @@ import java.util.HashMap; * An adapter for a list of {@link android.widget.SimpleMonthView} items. */ class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayClickListener { - private static final String TAG = "SimpleMonthAdapter"; + private final Calendar mMinDate = Calendar.getInstance(); + private final Calendar mMaxDate = Calendar.getInstance(); private final Context mContext; private final DatePickerController mController; - private Calendar mSelectedDay; + private Calendar mSelectedDay; private ColorStateList mCalendarTextColors; public SimpleMonthAdapter(Context context, DatePickerController controller) { mContext = context; mController = controller; + init(); setSelectedDay(mController.getSelectedDay()); } + public void setRange(Calendar min, Calendar max) { + mMinDate.setTimeInMillis(min.getTimeInMillis()); + mMaxDate.setTimeInMillis(max.getTimeInMillis()); + + notifyDataSetInvalidated(); + } + /** * Updates the selected day and related parameters. * @@ -68,10 +77,9 @@ class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayCli @Override public int getCount() { - final int diffYear = mController.getMaxYear() - mController.getMinYear(); - final int diffMonth = 1 + mController.getMaxMonth() - mController.getMinMonth() - + 12 * diffYear; - return diffMonth; + final int diffYear = mMaxDate.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR); + final int diffMonth = mMaxDate.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH); + return diffMonth + 12 * diffYear + 1; } @Override @@ -92,36 +100,34 @@ class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayCli @SuppressWarnings("unchecked") @Override public View getView(int position, View convertView, ViewGroup parent) { - SimpleMonthView v; - HashMap<String, Integer> drawingParams = null; + final SimpleMonthView v; if (convertView != null) { v = (SimpleMonthView) convertView; - // We store the drawing parameters in the view so it can be recycled - drawingParams = (HashMap<String, Integer>) v.getTag(); } else { v = new SimpleMonthView(mContext); + // Set up the new view - AbsListView.LayoutParams params = new AbsListView.LayoutParams( + final AbsListView.LayoutParams params = new AbsListView.LayoutParams( AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.MATCH_PARENT); v.setLayoutParams(params); v.setClickable(true); v.setOnDayClickListener(this); + if (mCalendarTextColors != null) { v.setTextColor(mCalendarTextColors); } } - if (drawingParams == null) { - drawingParams = new HashMap<String, Integer>(); - } else { - drawingParams.clear(); - } - final int currentMonth = position + mController.getMinMonth(); - final int month = currentMonth % 12; - final int year = currentMonth / 12 + mController.getMinYear(); - int selectedDay = -1; + final int minMonth = mMinDate.get(Calendar.MONTH); + final int minYear = mMinDate.get(Calendar.YEAR); + final int currentMonth = position + minMonth; + final int month = currentMonth % 12; + final int year = currentMonth / 12 + minYear; + final int selectedDay; if (isSelectedDayInMonth(year, month)) { selectedDay = mSelectedDay.get(Calendar.DAY_OF_MONTH); + } else { + selectedDay = -1; } // Invokes requestLayout() to ensure that the recycled view is set with the appropriate @@ -129,15 +135,15 @@ class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayCli v.reuse(); final int enabledDayRangeStart; - if (mController.getMinMonth() == month && mController.getMinYear() == year) { - enabledDayRangeStart = mController.getMinDay(); + if (minMonth == month && minYear == year) { + enabledDayRangeStart = mMinDate.get(Calendar.DAY_OF_MONTH); } else { enabledDayRangeStart = 1; } final int enabledDayRangeEnd; - if (mController.getMaxMonth() == month && mController.getMaxYear() == year) { - enabledDayRangeEnd = mController.getMaxDay(); + if (mMaxDate.get(Calendar.MONTH) == month && mMaxDate.get(Calendar.YEAR) == year) { + enabledDayRangeEnd = mMaxDate.get(Calendar.DAY_OF_MONTH); } else { enabledDayRangeEnd = 31; } @@ -155,20 +161,25 @@ class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayCli @Override public void onDayClick(SimpleMonthView view, Calendar day) { - if (day != null) { - onDayTapped(day); + if (day != null && isCalendarInRange(day)) { + onDaySelected(day); } } + private boolean isCalendarInRange(Calendar value) { + return value.compareTo(mMinDate) >= 0 && value.compareTo(mMaxDate) <= 0; + } + /** * Maintains the same hour/min/sec but moves the day to the tapped day. * * @param day The day that was tapped */ - protected void onDayTapped(Calendar day) { + private void onDaySelected(Calendar day) { mController.tryVibrate(); mController.onDayOfMonthSelected(day.get(Calendar.YEAR), day.get(Calendar.MONTH), day.get(Calendar.DAY_OF_MONTH)); + setSelectedDay(day); } } diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java index a76241ed1a50..d2a37ac111ef 100644 --- a/core/java/android/widget/SimpleMonthView.java +++ b/core/java/android/widget/SimpleMonthView.java @@ -31,6 +31,7 @@ import android.text.format.DateFormat; import android.text.format.DateUtils; import android.text.format.Time; import android.util.AttributeSet; +import android.util.IntArray; import android.util.MathUtils; import android.view.MotionEvent; import android.view.View; @@ -51,8 +52,6 @@ import java.util.Locale; * within the specified month. */ class SimpleMonthView extends View { - private static final String TAG = "SimpleMonthView"; - private static final int DEFAULT_HEIGHT = 32; private static final int MIN_HEIGHT = 10; @@ -66,15 +65,15 @@ class SimpleMonthView extends View { private static final int DAY_SEPARATOR_WIDTH = 1; + private final Formatter mFormatter; + private final StringBuilder mStringBuilder; + private final int mMiniDayNumberTextSize; private final int mMonthLabelTextSize; private final int mMonthDayLabelTextSize; private final int mMonthHeaderSize; private final int mDaySelectedCircleSize; - // used for scaling to the device density - private static float mScale = 0; - /** Single-letter (when available) formatter for the day of week label. */ private SimpleDateFormat mDayFormatter = new SimpleDateFormat("EEEEE", Locale.getDefault()); @@ -91,9 +90,6 @@ class SimpleMonthView extends View { private Paint mMonthTitlePaint; private Paint mMonthDayLabelPaint; - private final Formatter mFormatter; - private final StringBuilder mStringBuilder; - private int mMonth; private int mYear; @@ -154,11 +150,14 @@ class SimpleMonthView extends View { this(context, attrs, R.attr.datePickerStyle); } - public SimpleMonthView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs); + public SimpleMonthView(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } - final Resources res = context.getResources(); + public SimpleMonthView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + final Resources res = context.getResources(); mDayOfWeekTypeface = res.getString(R.string.day_of_week_label_typeface); mMonthTitleTypeface = res.getString(R.string.sans_serif); @@ -610,7 +609,7 @@ class SimpleMonthView extends View { } @Override - protected void getVisibleVirtualViews(List<Integer> virtualViewIds) { + protected void getVisibleVirtualViews(IntArray virtualViewIds) { for (int day = 1; day <= mNumCells; day++) { virtualViewIds.add(day); } diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java index a8980849af43..4c8aa519108c 100644 --- a/core/java/android/widget/Switch.java +++ b/core/java/android/widget/Switch.java @@ -39,6 +39,7 @@ import android.util.FloatProperty; import android.util.MathUtils; import android.view.Gravity; import android.view.MotionEvent; +import android.view.SoundEffectConstants; import android.view.VelocityTracker; import android.view.ViewConfiguration; import android.view.accessibility.AccessibilityEvent; @@ -797,6 +798,7 @@ public class Switch extends CompoundButton { // Commit the change if the event is up and not canceled and the switch // has not been disabled during the drag. final boolean commitChange = ev.getAction() == MotionEvent.ACTION_UP && isEnabled(); + final boolean oldState = isChecked(); final boolean newState; if (commitChange) { mVelocityTracker.computeCurrentVelocity(1000); @@ -807,10 +809,14 @@ public class Switch extends CompoundButton { newState = getTargetCheckedState(); } } else { - newState = isChecked(); + newState = oldState; + } + + if (newState != oldState) { + playSoundEffect(SoundEffectConstants.CLICK); + setChecked(newState); } - setChecked(newState); cancelSuperTouch(ev); } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 5cdee53abb15..0917b32e89d4 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -8518,6 +8518,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } return false; case AccessibilityNodeInfo.ACTION_SET_SELECTION: { if (isFocused() && canSelectText()) { + ensureIterableTextForAccessibilitySelectable(); CharSequence text = getIterableTextForAccessibility(); if (text == null) { return false; @@ -8543,6 +8544,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } } return false; + case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: + case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: { + ensureIterableTextForAccessibilitySelectable(); + return super.performAccessibilityAction(action, arguments); + } default: { return super.performAccessibilityAction(action, arguments); } @@ -9032,10 +9038,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ @Override public CharSequence getIterableTextForAccessibility() { + return mText; + } + + private void ensureIterableTextForAccessibilitySelectable() { if (!(mText instanceof Spannable)) { setText(mText, BufferType.SPANNABLE); } - return mText; } /** diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java index 85cf67b90e5e..26e02f8a3a24 100644 --- a/core/java/android/widget/TimePicker.java +++ b/core/java/android/widget/TimePicker.java @@ -86,12 +86,12 @@ public class TimePicker extends FrameLayout { switch (mode) { case MODE_CLOCK: - mDelegate = new TimePickerSpinnerDelegate( + mDelegate = new TimePickerClockDelegate( this, context, attrs, defStyleAttr, defStyleRes); break; case MODE_SPINNER: default: - mDelegate = new TimePickerClockDelegate( + mDelegate = new TimePickerSpinnerDelegate( this, context, attrs, defStyleAttr, defStyleRes); break; } diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java index 8917f39e7817..78ee2471dcb1 100644 --- a/core/java/android/widget/TimePickerClockDelegate.java +++ b/core/java/android/widget/TimePickerClockDelegate.java @@ -17,365 +17,376 @@ package android.widget; import android.content.Context; +import android.content.res.ColorStateList; import android.content.res.Configuration; +import android.content.res.Resources; import android.content.res.TypedArray; import android.os.Parcel; import android.os.Parcelable; +import android.text.TextUtils; import android.text.format.DateFormat; import android.text.format.DateUtils; import android.util.AttributeSet; +import android.util.Log; +import android.util.TypedValue; +import android.view.HapticFeedbackConstants; +import android.view.KeyCharacterMap; +import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.InputMethodManager; + import com.android.internal.R; -import java.text.DateFormatSymbols; +import java.util.ArrayList; import java.util.Calendar; import java.util.Locale; -import libcore.icu.LocaleData; - -import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO; -import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES; - /** - * A delegate implementing the basic TimePicker + * A delegate implementing the radial clock-based TimePicker. */ -class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { +class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate implements + RadialTimePickerView.OnValueSelectedListener { + + private static final String TAG = "TimePickerClockDelegate"; + + // Index used by RadialPickerLayout + private static final int HOUR_INDEX = 0; + private static final int MINUTE_INDEX = 1; + + // NOT a real index for the purpose of what's showing. + private static final int AMPM_INDEX = 2; + + // Also NOT a real index, just used for keyboard mode. + private static final int ENABLE_PICKER_INDEX = 3; + + static final int AM = 0; + static final int PM = 1; + private static final boolean DEFAULT_ENABLED_STATE = true; + private boolean mIsEnabled = DEFAULT_ENABLED_STATE; + private static final int HOURS_IN_HALF_DAY = 12; - // state - private boolean mIs24HourView; - private boolean mIsAm; + private final View mHeaderView; + private final TextView mHourView; + private final TextView mMinuteView; + private final View mAmPmLayout; + private final CheckedTextView mAmLabel; + private final CheckedTextView mPmLabel; + private final RadialTimePickerView mRadialTimePickerView; + private final TextView mSeparatorView; - // ui components - private final NumberPicker mHourSpinner; - private final NumberPicker mMinuteSpinner; - private final NumberPicker mAmPmSpinner; - private final EditText mHourSpinnerInput; - private final EditText mMinuteSpinnerInput; - private final EditText mAmPmSpinnerInput; - private final TextView mDivider; + private final String mAmText; + private final String mPmText; - // Note that the legacy implementation of the TimePicker is - // using a button for toggling between AM/PM while the new - // version uses a NumberPicker spinner. Therefore the code - // accommodates these two cases to be backwards compatible. - private final Button mAmPmButton; + private final float mDisabledAlpha; - private final String[] mAmPmStrings; + private boolean mAllowAutoAdvance; + private int mInitialHourOfDay; + private int mInitialMinute; + private boolean mIs24HourView; + + // For hardware IME input. + private char mPlaceholderText; + private String mDoublePlaceholderText; + private String mDeletedKeyFormat; + private boolean mInKbMode; + private ArrayList<Integer> mTypedTimes = new ArrayList<Integer>(); + private Node mLegalTimesTree; + private int mAmKeyCode; + private int mPmKeyCode; + + // Accessibility strings. + private String mHourPickerDescription; + private String mSelectHours; + private String mMinutePickerDescription; + private String mSelectMinutes; + + // Most recent time announcement values for accessibility. + private CharSequence mLastAnnouncedText; + private boolean mLastAnnouncedIsHour; - private boolean mIsEnabled = DEFAULT_ENABLED_STATE; private Calendar mTempCalendar; - private boolean mHourWithTwoDigit; - private char mHourFormat; public TimePickerClockDelegate(TimePicker delegator, Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(delegator, context); // process style attributes - final TypedArray a = mContext.obtainStyledAttributes( - attrs, R.styleable.TimePicker, defStyleAttr, defStyleRes); - final int layoutResourceId = a.getResourceId( - R.styleable.TimePicker_legacyLayout, R.layout.time_picker_legacy); - a.recycle(); + final TypedArray a = mContext.obtainStyledAttributes(attrs, + R.styleable.TimePicker, defStyleAttr, defStyleRes); + final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + final Resources res = mContext.getResources(); + + mHourPickerDescription = res.getString(R.string.hour_picker_description); + mSelectHours = res.getString(R.string.select_hours); + mMinutePickerDescription = res.getString(R.string.minute_picker_description); + mSelectMinutes = res.getString(R.string.select_minutes); + + String[] amPmStrings = TimePickerSpinnerDelegate.getAmPmStrings(context); + mAmText = amPmStrings[0]; + mPmText = amPmStrings[1]; + + final int layoutResourceId = a.getResourceId(R.styleable.TimePicker_internalLayout, + R.layout.time_picker_holo); + final View mainView = inflater.inflate(layoutResourceId, delegator); + + mHeaderView = mainView.findViewById(R.id.time_header); + mHeaderView.setBackground(a.getDrawable(R.styleable.TimePicker_headerBackground)); + + // Set up hour/minute labels. + mHourView = (TextView) mHeaderView.findViewById(R.id.hours); + mHourView.setOnClickListener(mClickListener); + mSeparatorView = (TextView) mHeaderView.findViewById(R.id.separator); + mMinuteView = (TextView) mHeaderView.findViewById(R.id.minutes); + mMinuteView.setOnClickListener(mClickListener); + + final int headerTimeTextAppearance = a.getResourceId( + R.styleable.TimePicker_headerTimeTextAppearance, 0); + if (headerTimeTextAppearance != 0) { + mHourView.setTextAppearance(context, headerTimeTextAppearance); + mSeparatorView.setTextAppearance(context, headerTimeTextAppearance); + mMinuteView.setTextAppearance(context, headerTimeTextAppearance); + } - final LayoutInflater inflater = LayoutInflater.from(mContext); - inflater.inflate(layoutResourceId, mDelegator, true); - - // hour - mHourSpinner = (NumberPicker) delegator.findViewById(R.id.hour); - mHourSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { - public void onValueChange(NumberPicker spinner, int oldVal, int newVal) { - updateInputState(); - if (!is24HourView()) { - if ((oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY) || - (oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1)) { - mIsAm = !mIsAm; - updateAmPmControl(); - } - } - onTimeChanged(); - } - }); - mHourSpinnerInput = (EditText) mHourSpinner.findViewById(R.id.numberpicker_input); - mHourSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT); - - // divider (only for the new widget style) - mDivider = (TextView) mDelegator.findViewById(R.id.divider); - if (mDivider != null) { - setDividerText(); - } - - // minute - mMinuteSpinner = (NumberPicker) mDelegator.findViewById(R.id.minute); - mMinuteSpinner.setMinValue(0); - mMinuteSpinner.setMaxValue(59); - mMinuteSpinner.setOnLongPressUpdateInterval(100); - mMinuteSpinner.setFormatter(NumberPicker.getTwoDigitFormatter()); - mMinuteSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { - public void onValueChange(NumberPicker spinner, int oldVal, int newVal) { - updateInputState(); - int minValue = mMinuteSpinner.getMinValue(); - int maxValue = mMinuteSpinner.getMaxValue(); - if (oldVal == maxValue && newVal == minValue) { - int newHour = mHourSpinner.getValue() + 1; - if (!is24HourView() && newHour == HOURS_IN_HALF_DAY) { - mIsAm = !mIsAm; - updateAmPmControl(); - } - mHourSpinner.setValue(newHour); - } else if (oldVal == minValue && newVal == maxValue) { - int newHour = mHourSpinner.getValue() - 1; - if (!is24HourView() && newHour == HOURS_IN_HALF_DAY - 1) { - mIsAm = !mIsAm; - updateAmPmControl(); - } - mHourSpinner.setValue(newHour); - } - onTimeChanged(); - } - }); - mMinuteSpinnerInput = (EditText) mMinuteSpinner.findViewById(R.id.numberpicker_input); - mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT); - - // Get the localized am/pm strings and use them in the spinner. - mAmPmStrings = getAmPmStrings(context); - - // am/pm - final View amPmView = mDelegator.findViewById(R.id.amPm); - if (amPmView instanceof Button) { - mAmPmSpinner = null; - mAmPmSpinnerInput = null; - mAmPmButton = (Button) amPmView; - mAmPmButton.setOnClickListener(new View.OnClickListener() { - public void onClick(View button) { - button.requestFocus(); - mIsAm = !mIsAm; - updateAmPmControl(); - onTimeChanged(); - } - }); - } else { - mAmPmButton = null; - mAmPmSpinner = (NumberPicker) amPmView; - mAmPmSpinner.setMinValue(0); - mAmPmSpinner.setMaxValue(1); - mAmPmSpinner.setDisplayedValues(mAmPmStrings); - mAmPmSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { - public void onValueChange(NumberPicker picker, int oldVal, int newVal) { - updateInputState(); - picker.requestFocus(); - mIsAm = !mIsAm; - updateAmPmControl(); - onTimeChanged(); - } - }); - mAmPmSpinnerInput = (EditText) mAmPmSpinner.findViewById(R.id.numberpicker_input); - mAmPmSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE); - } - - if (isAmPmAtStart()) { - // Move the am/pm view to the beginning - ViewGroup amPmParent = (ViewGroup) delegator.findViewById(R.id.timePickerLayout); - amPmParent.removeView(amPmView); - amPmParent.addView(amPmView, 0); - // Swap layout margins if needed. They may be not symmetrical (Old Standard Theme - // for example and not for Holo Theme) - ViewGroup.MarginLayoutParams lp = - (ViewGroup.MarginLayoutParams) amPmView.getLayoutParams(); - final int startMargin = lp.getMarginStart(); - final int endMargin = lp.getMarginEnd(); - if (startMargin != endMargin) { - lp.setMarginStart(endMargin); - lp.setMarginEnd(startMargin); - } + // TODO: This can be removed once we support themed color state lists. + final int headerSelectedTextColor = a.getColor( + R.styleable.TimePicker_headerSelectedTextColor, + res.getColor(R.color.timepicker_default_selector_color_material)); + mHourView.setTextColor(ColorStateList.addFirstIfMissing(mHourView.getTextColors(), + R.attr.state_selected, headerSelectedTextColor)); + mMinuteView.setTextColor(ColorStateList.addFirstIfMissing(mMinuteView.getTextColors(), + R.attr.state_selected, headerSelectedTextColor)); + + // Set up AM/PM labels. + mAmPmLayout = mHeaderView.findViewById(R.id.ampm_layout); + mAmLabel = (CheckedTextView) mAmPmLayout.findViewById(R.id.am_label); + mAmLabel.setText(amPmStrings[0]); + mAmLabel.setOnClickListener(mClickListener); + mPmLabel = (CheckedTextView) mAmPmLayout.findViewById(R.id.pm_label); + mPmLabel.setText(amPmStrings[1]); + mPmLabel.setOnClickListener(mClickListener); + + final int headerAmPmTextAppearance = a.getResourceId( + R.styleable.TimePicker_headerAmPmTextAppearance, 0); + if (headerAmPmTextAppearance != 0) { + mAmLabel.setTextAppearance(context, headerAmPmTextAppearance); + mPmLabel.setTextAppearance(context, headerAmPmTextAppearance); } - getHourFormatData(); + a.recycle(); + + // Pull disabled alpha from theme. + final TypedValue outValue = new TypedValue(); + context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, outValue, true); + mDisabledAlpha = outValue.getFloat(); - // update controls to initial state - updateHourControl(); - updateMinuteControl(); - updateAmPmControl(); + mRadialTimePickerView = (RadialTimePickerView) mainView.findViewById( + R.id.radial_picker); - // set to current time - setCurrentHour(mTempCalendar.get(Calendar.HOUR_OF_DAY)); - setCurrentMinute(mTempCalendar.get(Calendar.MINUTE)); + setupListeners(); - if (!isEnabled()) { - setEnabled(false); - } + mAllowAutoAdvance = true; - // set the content descriptions - setContentDescriptions(); + // Set up for keyboard mode. + mDoublePlaceholderText = res.getString(R.string.time_placeholder); + mDeletedKeyFormat = res.getString(R.string.deleted_key); + mPlaceholderText = mDoublePlaceholderText.charAt(0); + mAmKeyCode = mPmKeyCode = -1; + generateLegalTimesTree(); - // If not explicitly specified this view is important for accessibility. - if (mDelegator.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { - mDelegator.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); - } + // Initialize with current time + final Calendar calendar = Calendar.getInstance(mCurrentLocale); + final int currentHour = calendar.get(Calendar.HOUR_OF_DAY); + final int currentMinute = calendar.get(Calendar.MINUTE); + initialize(currentHour, currentMinute, false /* 12h */, HOUR_INDEX); } - private void getHourFormatData() { - final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale, - (mIs24HourView) ? "Hm" : "hm"); - final int lengthPattern = bestDateTimePattern.length(); - mHourWithTwoDigit = false; - char hourFormat = '\0'; - // Check if the returned pattern is single or double 'H', 'h', 'K', 'k'. We also save - // the hour format that we found. - for (int i = 0; i < lengthPattern; i++) { - final char c = bestDateTimePattern.charAt(i); - if (c == 'H' || c == 'h' || c == 'K' || c == 'k') { - mHourFormat = c; - if (i + 1 < lengthPattern && c == bestDateTimePattern.charAt(i + 1)) { - mHourWithTwoDigit = true; - } - break; - } - } + private void initialize(int hourOfDay, int minute, boolean is24HourView, int index) { + mInitialHourOfDay = hourOfDay; + mInitialMinute = minute; + mIs24HourView = is24HourView; + mInKbMode = false; + updateUI(index); } - private boolean isAmPmAtStart() { - final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale, - "hm" /* skeleton */); + private void setupListeners() { + mHeaderView.setOnKeyListener(mKeyListener); + mHeaderView.setOnFocusChangeListener(mFocusListener); + mHeaderView.setFocusable(true); - return bestDateTimePattern.startsWith("a"); + mRadialTimePickerView.setOnValueSelectedListener(this); } - /** - * The time separator is defined in the Unicode CLDR and cannot be supposed to be ":". - * - * See http://unicode.org/cldr/trac/browser/trunk/common/main - * - * We pass the correct "skeleton" depending on 12 or 24 hours view and then extract the - * separator as the character which is just after the hour marker in the returned pattern. - */ - private void setDividerText() { - final String skeleton = (mIs24HourView) ? "Hm" : "hm"; - final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale, - skeleton); - final String separatorText; - int hourIndex = bestDateTimePattern.lastIndexOf('H'); - if (hourIndex == -1) { - hourIndex = bestDateTimePattern.lastIndexOf('h'); + private void updateUI(int index) { + // Update RadialPicker values + updateRadialPicker(index); + // Enable or disable the AM/PM view. + updateHeaderAmPm(); + // Update Hour and Minutes + updateHeaderHour(mInitialHourOfDay, false); + // Update time separator + updateHeaderSeparator(); + // Update Minutes + updateHeaderMinute(mInitialMinute, false); + // Invalidate everything + mDelegator.invalidate(); + } + + private void updateRadialPicker(int index) { + mRadialTimePickerView.initialize(mInitialHourOfDay, mInitialMinute, mIs24HourView); + setCurrentItemShowing(index, false, true); + } + + private int computeMaxWidthOfNumbers(int max) { + TextView tempView = new TextView(mContext); + tempView.setTextAppearance(mContext, R.style.TextAppearance_Material_TimePicker_TimeLabel); + ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT); + tempView.setLayoutParams(lp); + int maxWidth = 0; + for (int minutes = 0; minutes < max; minutes++) { + final String text = String.format("%02d", minutes); + tempView.setText(text); + tempView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); + maxWidth = Math.max(maxWidth, tempView.getMeasuredWidth()); } - if (hourIndex == -1) { - // Default case - separatorText = ":"; + return maxWidth; + } + + private void updateHeaderAmPm() { + if (mIs24HourView) { + mAmPmLayout.setVisibility(View.GONE); } else { - int minuteIndex = bestDateTimePattern.indexOf('m', hourIndex + 1); - if (minuteIndex == -1) { - separatorText = Character.toString(bestDateTimePattern.charAt(hourIndex + 1)); + final String bestDateTimePattern = DateFormat.getBestDateTimePattern( + mCurrentLocale, "hm"); + boolean amPmOnLeft = bestDateTimePattern.startsWith("a"); + if (TextUtils.getLayoutDirectionFromLocale(mCurrentLocale) == + View.LAYOUT_DIRECTION_RTL) { + amPmOnLeft = !amPmOnLeft; + } + + final ViewGroup.MarginLayoutParams params = + (ViewGroup.MarginLayoutParams) mAmPmLayout.getLayoutParams(); + + if (amPmOnLeft) { + params.leftMargin = 0; + params.rightMargin = computeMaxWidthOfNumbers(12 /* for hours */); } else { - separatorText = bestDateTimePattern.substring(hourIndex + 1, minuteIndex); + params.leftMargin = computeMaxWidthOfNumbers(60 /* for minutes */); + params.rightMargin = 0; } + + mAmPmLayout.setLayoutParams(params); + mAmPmLayout.setVisibility(View.VISIBLE); + + updateAmPmLabelStates(mInitialHourOfDay < 12 ? AM : PM); } - mDivider.setText(separatorText); } + /** + * Set the current hour. + */ @Override public void setCurrentHour(Integer currentHour) { - setCurrentHour(currentHour, true); - } - - private void setCurrentHour(Integer currentHour, boolean notifyTimeChanged) { - // why was Integer used in the first place? - if (currentHour == null || currentHour == getCurrentHour()) { + if (mInitialHourOfDay == currentHour) { return; } - if (!is24HourView()) { - // convert [0,23] ordinal to wall clock display - if (currentHour >= HOURS_IN_HALF_DAY) { - mIsAm = false; - if (currentHour > HOURS_IN_HALF_DAY) { - currentHour = currentHour - HOURS_IN_HALF_DAY; - } - } else { - mIsAm = true; - if (currentHour == 0) { - currentHour = HOURS_IN_HALF_DAY; - } - } - updateAmPmControl(); - } - mHourSpinner.setValue(currentHour); - if (notifyTimeChanged) { - onTimeChanged(); - } + mInitialHourOfDay = currentHour; + updateHeaderHour(currentHour, true); + updateHeaderAmPm(); + mRadialTimePickerView.setCurrentHour(currentHour); + mRadialTimePickerView.setAmOrPm(mInitialHourOfDay < 12 ? AM : PM); + mDelegator.invalidate(); + onTimeChanged(); } + /** + * @return The current hour in the range (0-23). + */ @Override public Integer getCurrentHour() { - int currentHour = mHourSpinner.getValue(); - if (is24HourView()) { + int currentHour = mRadialTimePickerView.getCurrentHour(); + if (mIs24HourView) { return currentHour; - } else if (mIsAm) { - return currentHour % HOURS_IN_HALF_DAY; } else { - return (currentHour % HOURS_IN_HALF_DAY) + HOURS_IN_HALF_DAY; + switch(mRadialTimePickerView.getAmOrPm()) { + case PM: + return (currentHour % HOURS_IN_HALF_DAY) + HOURS_IN_HALF_DAY; + case AM: + default: + return currentHour % HOURS_IN_HALF_DAY; + } } } + /** + * Set the current minute (0-59). + */ @Override public void setCurrentMinute(Integer currentMinute) { - if (currentMinute == getCurrentMinute()) { + if (mInitialMinute == currentMinute) { return; } - mMinuteSpinner.setValue(currentMinute); + mInitialMinute = currentMinute; + updateHeaderMinute(currentMinute, true); + mRadialTimePickerView.setCurrentMinute(currentMinute); + mDelegator.invalidate(); onTimeChanged(); } + /** + * @return The current minute. + */ @Override public Integer getCurrentMinute() { - return mMinuteSpinner.getValue(); + return mRadialTimePickerView.getCurrentMinute(); } + /** + * Set whether in 24 hour or AM/PM mode. + * + * @param is24HourView True = 24 hour mode. False = AM/PM. + */ @Override public void setIs24HourView(Boolean is24HourView) { - if (mIs24HourView == is24HourView) { + if (is24HourView == mIs24HourView) { return; } - // cache the current hour since spinner range changes and BEFORE changing mIs24HourView!! - int currentHour = getCurrentHour(); - // Order is important here. mIs24HourView = is24HourView; - getHourFormatData(); - updateHourControl(); - // set value after spinner range is updated - setCurrentHour(currentHour, false); - updateMinuteControl(); - updateAmPmControl(); + generateLegalTimesTree(); + int hour = mRadialTimePickerView.getCurrentHour(); + mInitialHourOfDay = hour; + updateHeaderHour(hour, false); + updateHeaderAmPm(); + updateRadialPicker(mRadialTimePickerView.getCurrentItemShowing()); + mDelegator.invalidate(); } + /** + * @return true if this is in 24 hour view else false. + */ @Override public boolean is24HourView() { return mIs24HourView; } @Override - public void setOnTimeChangedListener(TimePicker.OnTimeChangedListener onTimeChangedListener) { - mOnTimeChangedListener = onTimeChangedListener; + public void setOnTimeChangedListener(TimePicker.OnTimeChangedListener callback) { + mOnTimeChangedListener = callback; } @Override public void setEnabled(boolean enabled) { - mMinuteSpinner.setEnabled(enabled); - if (mDivider != null) { - mDivider.setEnabled(enabled); - } - mHourSpinner.setEnabled(enabled); - if (mAmPmSpinner != null) { - mAmPmSpinner.setEnabled(enabled); - } else { - mAmPmButton.setEnabled(enabled); - } + mHourView.setEnabled(enabled); + mMinuteView.setEnabled(enabled); + mAmLabel.setEnabled(enabled); + mPmLabel.setEnabled(enabled); + mRadialTimePickerView.setEnabled(enabled); mIsEnabled = enabled; } @@ -386,24 +397,38 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { @Override public int getBaseline() { - return mHourSpinner.getBaseline(); + // does not support baseline alignment + return -1; } @Override public void onConfigurationChanged(Configuration newConfig) { - setCurrentLocale(newConfig.locale); + updateUI(mRadialTimePickerView.getCurrentItemShowing()); } @Override public Parcelable onSaveInstanceState(Parcelable superState) { - return new SavedState(superState, getCurrentHour(), getCurrentMinute()); + return new SavedState(superState, getCurrentHour(), getCurrentMinute(), + is24HourView(), inKbMode(), getTypedTimes(), getCurrentItemShowing()); } @Override public void onRestoreInstanceState(Parcelable state) { SavedState ss = (SavedState) state; - setCurrentHour(ss.getHour()); - setCurrentMinute(ss.getMinute()); + setInKbMode(ss.inKbMode()); + setTypedTimes(ss.getTypesTimes()); + initialize(ss.getHour(), ss.getMinute(), ss.is24HourMode(), ss.getCurrentItemShowing()); + mRadialTimePickerView.invalidate(); + if (mInKbMode) { + tryStartingKbMode(-1); + mHourView.invalidate(); + } + } + + @Override + public void setCurrentLocale(Locale locale) { + super.setCurrentLocale(locale); + mTempCalendar = Calendar.getInstance(locale); } @Override @@ -422,9 +447,9 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { } mTempCalendar.set(Calendar.HOUR_OF_DAY, getCurrentHour()); mTempCalendar.set(Calendar.MINUTE, getCurrentMinute()); - String selectedDateUtterance = DateUtils.formatDateTime(mContext, + String selectedDate = DateUtils.formatDateTime(mContext, mTempCalendar.getTimeInMillis(), flags); - event.getText().add(selectedDateUtterance); + event.getText().add(selectedDate); } @Override @@ -437,121 +462,48 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { info.setClassName(TimePicker.class.getName()); } - private void updateInputState() { - // Make sure that if the user changes the value and the IME is active - // for one of the inputs if this widget, the IME is closed. If the user - // changed the value via the IME and there is a next input the IME will - // be shown, otherwise the user chose another means of changing the - // value and having the IME up makes no sense. - InputMethodManager inputMethodManager = InputMethodManager.peekInstance(); - if (inputMethodManager != null) { - if (inputMethodManager.isActive(mHourSpinnerInput)) { - mHourSpinnerInput.clearFocus(); - inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0); - } else if (inputMethodManager.isActive(mMinuteSpinnerInput)) { - mMinuteSpinnerInput.clearFocus(); - inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0); - } else if (inputMethodManager.isActive(mAmPmSpinnerInput)) { - mAmPmSpinnerInput.clearFocus(); - inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0); - } - } - } - - private void updateAmPmControl() { - if (is24HourView()) { - if (mAmPmSpinner != null) { - mAmPmSpinner.setVisibility(View.GONE); - } else { - mAmPmButton.setVisibility(View.GONE); - } - } else { - int index = mIsAm ? Calendar.AM : Calendar.PM; - if (mAmPmSpinner != null) { - mAmPmSpinner.setValue(index); - mAmPmSpinner.setVisibility(View.VISIBLE); - } else { - mAmPmButton.setText(mAmPmStrings[index]); - mAmPmButton.setVisibility(View.VISIBLE); - } - } - mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); - } - /** - * Sets the current locale. + * Set whether in keyboard mode or not. * - * @param locale The current locale. + * @param inKbMode True means in keyboard mode. */ - @Override - public void setCurrentLocale(Locale locale) { - super.setCurrentLocale(locale); - mTempCalendar = Calendar.getInstance(locale); + private void setInKbMode(boolean inKbMode) { + mInKbMode = inKbMode; } - private void onTimeChanged() { - mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); - if (mOnTimeChangedListener != null) { - mOnTimeChangedListener.onTimeChanged(mDelegator, getCurrentHour(), - getCurrentMinute()); - } + /** + * @return true if in keyboard mode + */ + private boolean inKbMode() { + return mInKbMode; } - private void updateHourControl() { - if (is24HourView()) { - // 'k' means 1-24 hour - if (mHourFormat == 'k') { - mHourSpinner.setMinValue(1); - mHourSpinner.setMaxValue(24); - } else { - mHourSpinner.setMinValue(0); - mHourSpinner.setMaxValue(23); - } - } else { - // 'K' means 0-11 hour - if (mHourFormat == 'K') { - mHourSpinner.setMinValue(0); - mHourSpinner.setMaxValue(11); - } else { - mHourSpinner.setMinValue(1); - mHourSpinner.setMaxValue(12); - } - } - mHourSpinner.setFormatter(mHourWithTwoDigit ? NumberPicker.getTwoDigitFormatter() : null); + private void setTypedTimes(ArrayList<Integer> typeTimes) { + mTypedTimes = typeTimes; } - private void updateMinuteControl() { - if (is24HourView()) { - mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE); - } else { - mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT); - } + /** + * @return an array of typed times + */ + private ArrayList<Integer> getTypedTimes() { + return mTypedTimes; } - private void setContentDescriptions() { - // Minute - trySetContentDescription(mMinuteSpinner, R.id.increment, - R.string.time_picker_increment_minute_button); - trySetContentDescription(mMinuteSpinner, R.id.decrement, - R.string.time_picker_decrement_minute_button); - // Hour - trySetContentDescription(mHourSpinner, R.id.increment, - R.string.time_picker_increment_hour_button); - trySetContentDescription(mHourSpinner, R.id.decrement, - R.string.time_picker_decrement_hour_button); - // AM/PM - if (mAmPmSpinner != null) { - trySetContentDescription(mAmPmSpinner, R.id.increment, - R.string.time_picker_increment_set_pm_button); - trySetContentDescription(mAmPmSpinner, R.id.decrement, - R.string.time_picker_decrement_set_am_button); - } + /** + * @return the index of the current item showing + */ + private int getCurrentItemShowing() { + return mRadialTimePickerView.getCurrentItemShowing(); } - private void trySetContentDescription(View root, int viewId, int contDescResId) { - View target = root.findViewById(viewId); - if (target != null) { - target.setContentDescription(mContext.getString(contDescResId)); + /** + * Propagate the time change + */ + private void onTimeChanged() { + mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); + if (mOnTimeChangedListener != null) { + mOnTimeChangedListener.onTimeChanged(mDelegator, + getCurrentHour(), getCurrentMinute()); } } @@ -559,19 +511,34 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { * Used to save / restore state of time picker */ private static class SavedState extends View.BaseSavedState { + private final int mHour; private final int mMinute; - - private SavedState(Parcelable superState, int hour, int minute) { + private final boolean mIs24HourMode; + private final boolean mInKbMode; + private final ArrayList<Integer> mTypedTimes; + private final int mCurrentItemShowing; + + private SavedState(Parcelable superState, int hour, int minute, boolean is24HourMode, + boolean isKbMode, ArrayList<Integer> typedTimes, + int currentItemShowing) { super(superState); mHour = hour; mMinute = minute; + mIs24HourMode = is24HourMode; + mInKbMode = isKbMode; + mTypedTimes = typedTimes; + mCurrentItemShowing = currentItemShowing; } private SavedState(Parcel in) { super(in); mHour = in.readInt(); mMinute = in.readInt(); + mIs24HourMode = (in.readInt() == 1); + mInKbMode = (in.readInt() == 1); + mTypedTimes = in.readArrayList(getClass().getClassLoader()); + mCurrentItemShowing = in.readInt(); } public int getHour() { @@ -582,11 +549,31 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { return mMinute; } + public boolean is24HourMode() { + return mIs24HourMode; + } + + public boolean inKbMode() { + return mInKbMode; + } + + public ArrayList<Integer> getTypesTimes() { + return mTypedTimes; + } + + public int getCurrentItemShowing() { + return mCurrentItemShowing; + } + @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeInt(mHour); dest.writeInt(mMinute); + dest.writeInt(mIs24HourMode ? 1 : 0); + dest.writeInt(mInKbMode ? 1 : 0); + dest.writeList(mTypedTimes); + dest.writeInt(mCurrentItemShowing); } @SuppressWarnings({"unused", "hiding"}) @@ -601,11 +588,696 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { }; } - public static String[] getAmPmStrings(Context context) { - String[] result = new String[2]; - LocaleData d = LocaleData.get(context.getResources().getConfiguration().locale); - result[0] = d.amPm[0].length() > 2 ? d.narrowAm : d.amPm[0]; - result[1] = d.amPm[1].length() > 2 ? d.narrowPm : d.amPm[1]; - return result; + private void tryVibrate() { + mDelegator.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK); + } + + private void updateAmPmLabelStates(int amOrPm) { + final boolean isAm = amOrPm == AM; + mAmLabel.setChecked(isAm); + mAmLabel.setAlpha(isAm ? 1 : mDisabledAlpha); + + final boolean isPm = amOrPm == PM; + mPmLabel.setChecked(isPm); + mPmLabel.setAlpha(isPm ? 1 : mDisabledAlpha); + } + + /** + * Called by the picker for updating the header display. + */ + @Override + public void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance) { + if (pickerIndex == HOUR_INDEX) { + if (mAllowAutoAdvance && autoAdvance) { + updateHeaderHour(newValue, false); + setCurrentItemShowing(MINUTE_INDEX, true, false); + mDelegator.announceForAccessibility(newValue + ". " + mSelectMinutes); + } else { + updateHeaderHour(newValue, true); + } + } else if (pickerIndex == MINUTE_INDEX){ + updateHeaderMinute(newValue, true); + } else if (pickerIndex == AMPM_INDEX) { + updateAmPmLabelStates(newValue); + } else if (pickerIndex == ENABLE_PICKER_INDEX) { + if (!isTypedTimeFullyLegal()) { + mTypedTimes.clear(); + } + finishKbMode(); + } + } + + private void updateHeaderHour(int value, boolean announce) { + final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale, + (mIs24HourView) ? "Hm" : "hm"); + final int lengthPattern = bestDateTimePattern.length(); + boolean hourWithTwoDigit = false; + char hourFormat = '\0'; + // Check if the returned pattern is single or double 'H', 'h', 'K', 'k'. We also save + // the hour format that we found. + for (int i = 0; i < lengthPattern; i++) { + final char c = bestDateTimePattern.charAt(i); + if (c == 'H' || c == 'h' || c == 'K' || c == 'k') { + hourFormat = c; + if (i + 1 < lengthPattern && c == bestDateTimePattern.charAt(i + 1)) { + hourWithTwoDigit = true; + } + break; + } + } + final String format; + if (hourWithTwoDigit) { + format = "%02d"; + } else { + format = "%d"; + } + if (mIs24HourView) { + // 'k' means 1-24 hour + if (hourFormat == 'k' && value == 0) { + value = 24; + } + } else { + // 'K' means 0-11 hour + value = modulo12(value, hourFormat == 'K'); + } + CharSequence text = String.format(format, value); + mHourView.setText(text); + if (announce) { + tryAnnounceForAccessibility(text, true); + } + } + + private void tryAnnounceForAccessibility(CharSequence text, boolean isHour) { + if (mLastAnnouncedIsHour != isHour || !text.equals(mLastAnnouncedText)) { + // TODO: Find a better solution, potentially live regions? + mDelegator.announceForAccessibility(text); + mLastAnnouncedText = text; + mLastAnnouncedIsHour = isHour; + } + } + + private static int modulo12(int n, boolean startWithZero) { + int value = n % 12; + if (value == 0 && !startWithZero) { + value = 12; + } + return value; + } + + /** + * The time separator is defined in the Unicode CLDR and cannot be supposed to be ":". + * + * See http://unicode.org/cldr/trac/browser/trunk/common/main + * + * We pass the correct "skeleton" depending on 12 or 24 hours view and then extract the + * separator as the character which is just after the hour marker in the returned pattern. + */ + private void updateHeaderSeparator() { + final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale, + (mIs24HourView) ? "Hm" : "hm"); + final String separatorText; + // See http://www.unicode.org/reports/tr35/tr35-dates.html for hour formats + final char[] hourFormats = {'H', 'h', 'K', 'k'}; + int hIndex = lastIndexOfAny(bestDateTimePattern, hourFormats); + if (hIndex == -1) { + // Default case + separatorText = ":"; + } else { + separatorText = Character.toString(bestDateTimePattern.charAt(hIndex + 1)); + } + mSeparatorView.setText(separatorText); + } + + static private int lastIndexOfAny(String str, char[] any) { + final int lengthAny = any.length; + if (lengthAny > 0) { + for (int i = str.length() - 1; i >= 0; i--) { + char c = str.charAt(i); + for (int j = 0; j < lengthAny; j++) { + if (c == any[j]) { + return i; + } + } + } + } + return -1; + } + + private void updateHeaderMinute(int value, boolean announceForAccessibility) { + if (value == 60) { + value = 0; + } + final CharSequence text = String.format(mCurrentLocale, "%02d", value); + mMinuteView.setText(text); + if (announceForAccessibility) { + tryAnnounceForAccessibility(text, false); + } + } + + /** + * Show either Hours or Minutes. + */ + private void setCurrentItemShowing(int index, boolean animateCircle, boolean announce) { + mRadialTimePickerView.setCurrentItemShowing(index, animateCircle); + + if (index == HOUR_INDEX) { + if (announce) { + mDelegator.announceForAccessibility(mSelectHours); + } + } else { + if (announce) { + mDelegator.announceForAccessibility(mSelectMinutes); + } + } + + mHourView.setSelected(index == HOUR_INDEX); + mMinuteView.setSelected(index == MINUTE_INDEX); + } + + private void setAmOrPm(int amOrPm) { + updateAmPmLabelStates(amOrPm); + mRadialTimePickerView.setAmOrPm(amOrPm); + } + + /** + * For keyboard mode, processes key events. + * + * @param keyCode the pressed key. + * + * @return true if the key was successfully processed, false otherwise. + */ + private boolean processKeyUp(int keyCode) { + if (keyCode == KeyEvent.KEYCODE_DEL) { + if (mInKbMode) { + if (!mTypedTimes.isEmpty()) { + int deleted = deleteLastTypedKey(); + String deletedKeyStr; + if (deleted == getAmOrPmKeyCode(AM)) { + deletedKeyStr = mAmText; + } else if (deleted == getAmOrPmKeyCode(PM)) { + deletedKeyStr = mPmText; + } else { + deletedKeyStr = String.format("%d", getValFromKeyCode(deleted)); + } + mDelegator.announceForAccessibility( + String.format(mDeletedKeyFormat, deletedKeyStr)); + updateDisplay(true); + } + } + } else if (keyCode == KeyEvent.KEYCODE_0 || keyCode == KeyEvent.KEYCODE_1 + || keyCode == KeyEvent.KEYCODE_2 || keyCode == KeyEvent.KEYCODE_3 + || keyCode == KeyEvent.KEYCODE_4 || keyCode == KeyEvent.KEYCODE_5 + || keyCode == KeyEvent.KEYCODE_6 || keyCode == KeyEvent.KEYCODE_7 + || keyCode == KeyEvent.KEYCODE_8 || keyCode == KeyEvent.KEYCODE_9 + || (!mIs24HourView && + (keyCode == getAmOrPmKeyCode(AM) || keyCode == getAmOrPmKeyCode(PM)))) { + if (!mInKbMode) { + if (mRadialTimePickerView == null) { + // Something's wrong, because time picker should definitely not be null. + Log.e(TAG, "Unable to initiate keyboard mode, TimePicker was null."); + return true; + } + mTypedTimes.clear(); + tryStartingKbMode(keyCode); + return true; + } + // We're already in keyboard mode. + if (addKeyIfLegal(keyCode)) { + updateDisplay(false); + } + return true; + } + return false; + } + + /** + * Try to start keyboard mode with the specified key. + * + * @param keyCode The key to use as the first press. Keyboard mode will not be started if the + * key is not legal to start with. Or, pass in -1 to get into keyboard mode without a starting + * key. + */ + private void tryStartingKbMode(int keyCode) { + if (keyCode == -1 || addKeyIfLegal(keyCode)) { + mInKbMode = true; + onValidationChanged(false); + updateDisplay(false); + mRadialTimePickerView.setInputEnabled(false); + } } + + private boolean addKeyIfLegal(int keyCode) { + // If we're in 24hour mode, we'll need to check if the input is full. If in AM/PM mode, + // we'll need to see if AM/PM have been typed. + if ((mIs24HourView && mTypedTimes.size() == 4) || + (!mIs24HourView && isTypedTimeFullyLegal())) { + return false; + } + + mTypedTimes.add(keyCode); + if (!isTypedTimeLegalSoFar()) { + deleteLastTypedKey(); + return false; + } + + int val = getValFromKeyCode(keyCode); + mDelegator.announceForAccessibility(String.format("%d", val)); + // Automatically fill in 0's if AM or PM was legally entered. + if (isTypedTimeFullyLegal()) { + if (!mIs24HourView && mTypedTimes.size() <= 3) { + mTypedTimes.add(mTypedTimes.size() - 1, KeyEvent.KEYCODE_0); + mTypedTimes.add(mTypedTimes.size() - 1, KeyEvent.KEYCODE_0); + } + onValidationChanged(true); + } + + return true; + } + + /** + * Traverse the tree to see if the keys that have been typed so far are legal as is, + * or may become legal as more keys are typed (excluding backspace). + */ + private boolean isTypedTimeLegalSoFar() { + Node node = mLegalTimesTree; + for (int keyCode : mTypedTimes) { + node = node.canReach(keyCode); + if (node == null) { + return false; + } + } + return true; + } + + /** + * Check if the time that has been typed so far is completely legal, as is. + */ + private boolean isTypedTimeFullyLegal() { + if (mIs24HourView) { + // For 24-hour mode, the time is legal if the hours and minutes are each legal. Note: + // getEnteredTime() will ONLY call isTypedTimeFullyLegal() when NOT in 24hour mode. + int[] values = getEnteredTime(null); + return (values[0] >= 0 && values[1] >= 0 && values[1] < 60); + } else { + // For AM/PM mode, the time is legal if it contains an AM or PM, as those can only be + // legally added at specific times based on the tree's algorithm. + return (mTypedTimes.contains(getAmOrPmKeyCode(AM)) || + mTypedTimes.contains(getAmOrPmKeyCode(PM))); + } + } + + private int deleteLastTypedKey() { + int deleted = mTypedTimes.remove(mTypedTimes.size() - 1); + if (!isTypedTimeFullyLegal()) { + onValidationChanged(false); + } + return deleted; + } + + /** + * Get out of keyboard mode. If there is nothing in typedTimes, revert to TimePicker's time. + */ + private void finishKbMode() { + mInKbMode = false; + if (!mTypedTimes.isEmpty()) { + int values[] = getEnteredTime(null); + mRadialTimePickerView.setCurrentHour(values[0]); + mRadialTimePickerView.setCurrentMinute(values[1]); + if (!mIs24HourView) { + mRadialTimePickerView.setAmOrPm(values[2]); + } + mTypedTimes.clear(); + } + updateDisplay(false); + mRadialTimePickerView.setInputEnabled(true); + } + + /** + * Update the hours, minutes, and AM/PM displays with the typed times. If the typedTimes is + * empty, either show an empty display (filled with the placeholder text), or update from the + * timepicker's values. + * + * @param allowEmptyDisplay if true, then if the typedTimes is empty, use the placeholder text. + * Otherwise, revert to the timepicker's values. + */ + private void updateDisplay(boolean allowEmptyDisplay) { + if (!allowEmptyDisplay && mTypedTimes.isEmpty()) { + int hour = mRadialTimePickerView.getCurrentHour(); + int minute = mRadialTimePickerView.getCurrentMinute(); + updateHeaderHour(hour, false); + updateHeaderMinute(minute, false); + if (!mIs24HourView) { + updateAmPmLabelStates(hour < 12 ? AM : PM); + } + setCurrentItemShowing(mRadialTimePickerView.getCurrentItemShowing(), true, true); + onValidationChanged(true); + } else { + boolean[] enteredZeros = {false, false}; + int[] values = getEnteredTime(enteredZeros); + String hourFormat = enteredZeros[0] ? "%02d" : "%2d"; + String minuteFormat = (enteredZeros[1]) ? "%02d" : "%2d"; + String hourStr = (values[0] == -1) ? mDoublePlaceholderText : + String.format(hourFormat, values[0]).replace(' ', mPlaceholderText); + String minuteStr = (values[1] == -1) ? mDoublePlaceholderText : + String.format(minuteFormat, values[1]).replace(' ', mPlaceholderText); + mHourView.setText(hourStr); + mHourView.setSelected(false); + mMinuteView.setText(minuteStr); + mMinuteView.setSelected(false); + if (!mIs24HourView) { + updateAmPmLabelStates(values[2]); + } + } + } + + private int getValFromKeyCode(int keyCode) { + switch (keyCode) { + case KeyEvent.KEYCODE_0: + return 0; + case KeyEvent.KEYCODE_1: + return 1; + case KeyEvent.KEYCODE_2: + return 2; + case KeyEvent.KEYCODE_3: + return 3; + case KeyEvent.KEYCODE_4: + return 4; + case KeyEvent.KEYCODE_5: + return 5; + case KeyEvent.KEYCODE_6: + return 6; + case KeyEvent.KEYCODE_7: + return 7; + case KeyEvent.KEYCODE_8: + return 8; + case KeyEvent.KEYCODE_9: + return 9; + default: + return -1; + } + } + + /** + * Get the currently-entered time, as integer values of the hours and minutes typed. + * + * @param enteredZeros A size-2 boolean array, which the caller should initialize, and which + * may then be used for the caller to know whether zeros had been explicitly entered as either + * hours of minutes. This is helpful for deciding whether to show the dashes, or actual 0's. + * + * @return A size-3 int array. The first value will be the hours, the second value will be the + * minutes, and the third will be either AM or PM. + */ + private int[] getEnteredTime(boolean[] enteredZeros) { + int amOrPm = -1; + int startIndex = 1; + if (!mIs24HourView && isTypedTimeFullyLegal()) { + int keyCode = mTypedTimes.get(mTypedTimes.size() - 1); + if (keyCode == getAmOrPmKeyCode(AM)) { + amOrPm = AM; + } else if (keyCode == getAmOrPmKeyCode(PM)){ + amOrPm = PM; + } + startIndex = 2; + } + int minute = -1; + int hour = -1; + for (int i = startIndex; i <= mTypedTimes.size(); i++) { + int val = getValFromKeyCode(mTypedTimes.get(mTypedTimes.size() - i)); + if (i == startIndex) { + minute = val; + } else if (i == startIndex+1) { + minute += 10 * val; + if (enteredZeros != null && val == 0) { + enteredZeros[1] = true; + } + } else if (i == startIndex+2) { + hour = val; + } else if (i == startIndex+3) { + hour += 10 * val; + if (enteredZeros != null && val == 0) { + enteredZeros[0] = true; + } + } + } + + return new int[] { hour, minute, amOrPm }; + } + + /** + * Get the keycode value for AM and PM in the current language. + */ + private int getAmOrPmKeyCode(int amOrPm) { + // Cache the codes. + if (mAmKeyCode == -1 || mPmKeyCode == -1) { + // Find the first character in the AM/PM text that is unique. + KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); + char amChar; + char pmChar; + for (int i = 0; i < Math.max(mAmText.length(), mPmText.length()); i++) { + amChar = mAmText.toLowerCase(mCurrentLocale).charAt(i); + pmChar = mPmText.toLowerCase(mCurrentLocale).charAt(i); + if (amChar != pmChar) { + KeyEvent[] events = kcm.getEvents(new char[]{amChar, pmChar}); + // There should be 4 events: a down and up for both AM and PM. + if (events != null && events.length == 4) { + mAmKeyCode = events[0].getKeyCode(); + mPmKeyCode = events[2].getKeyCode(); + } else { + Log.e(TAG, "Unable to find keycodes for AM and PM."); + } + break; + } + } + } + if (amOrPm == AM) { + return mAmKeyCode; + } else if (amOrPm == PM) { + return mPmKeyCode; + } + + return -1; + } + + /** + * Create a tree for deciding what keys can legally be typed. + */ + private void generateLegalTimesTree() { + // Create a quick cache of numbers to their keycodes. + final int k0 = KeyEvent.KEYCODE_0; + final int k1 = KeyEvent.KEYCODE_1; + final int k2 = KeyEvent.KEYCODE_2; + final int k3 = KeyEvent.KEYCODE_3; + final int k4 = KeyEvent.KEYCODE_4; + final int k5 = KeyEvent.KEYCODE_5; + final int k6 = KeyEvent.KEYCODE_6; + final int k7 = KeyEvent.KEYCODE_7; + final int k8 = KeyEvent.KEYCODE_8; + final int k9 = KeyEvent.KEYCODE_9; + + // The root of the tree doesn't contain any numbers. + mLegalTimesTree = new Node(); + if (mIs24HourView) { + // We'll be re-using these nodes, so we'll save them. + Node minuteFirstDigit = new Node(k0, k1, k2, k3, k4, k5); + Node minuteSecondDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9); + // The first digit must be followed by the second digit. + minuteFirstDigit.addChild(minuteSecondDigit); + + // The first digit may be 0-1. + Node firstDigit = new Node(k0, k1); + mLegalTimesTree.addChild(firstDigit); + + // When the first digit is 0-1, the second digit may be 0-5. + Node secondDigit = new Node(k0, k1, k2, k3, k4, k5); + firstDigit.addChild(secondDigit); + // We may now be followed by the first minute digit. E.g. 00:09, 15:58. + secondDigit.addChild(minuteFirstDigit); + + // When the first digit is 0-1, and the second digit is 0-5, the third digit may be 6-9. + Node thirdDigit = new Node(k6, k7, k8, k9); + // The time must now be finished. E.g. 0:55, 1:08. + secondDigit.addChild(thirdDigit); + + // When the first digit is 0-1, the second digit may be 6-9. + secondDigit = new Node(k6, k7, k8, k9); + firstDigit.addChild(secondDigit); + // We must now be followed by the first minute digit. E.g. 06:50, 18:20. + secondDigit.addChild(minuteFirstDigit); + + // The first digit may be 2. + firstDigit = new Node(k2); + mLegalTimesTree.addChild(firstDigit); + + // When the first digit is 2, the second digit may be 0-3. + secondDigit = new Node(k0, k1, k2, k3); + firstDigit.addChild(secondDigit); + // We must now be followed by the first minute digit. E.g. 20:50, 23:09. + secondDigit.addChild(minuteFirstDigit); + + // When the first digit is 2, the second digit may be 4-5. + secondDigit = new Node(k4, k5); + firstDigit.addChild(secondDigit); + // We must now be followd by the last minute digit. E.g. 2:40, 2:53. + secondDigit.addChild(minuteSecondDigit); + + // The first digit may be 3-9. + firstDigit = new Node(k3, k4, k5, k6, k7, k8, k9); + mLegalTimesTree.addChild(firstDigit); + // We must now be followed by the first minute digit. E.g. 3:57, 8:12. + firstDigit.addChild(minuteFirstDigit); + } else { + // We'll need to use the AM/PM node a lot. + // Set up AM and PM to respond to "a" and "p". + Node ampm = new Node(getAmOrPmKeyCode(AM), getAmOrPmKeyCode(PM)); + + // The first hour digit may be 1. + Node firstDigit = new Node(k1); + mLegalTimesTree.addChild(firstDigit); + // We'll allow quick input of on-the-hour times. E.g. 1pm. + firstDigit.addChild(ampm); + + // When the first digit is 1, the second digit may be 0-2. + Node secondDigit = new Node(k0, k1, k2); + firstDigit.addChild(secondDigit); + // Also for quick input of on-the-hour times. E.g. 10pm, 12am. + secondDigit.addChild(ampm); + + // When the first digit is 1, and the second digit is 0-2, the third digit may be 0-5. + Node thirdDigit = new Node(k0, k1, k2, k3, k4, k5); + secondDigit.addChild(thirdDigit); + // The time may be finished now. E.g. 1:02pm, 1:25am. + thirdDigit.addChild(ampm); + + // When the first digit is 1, the second digit is 0-2, and the third digit is 0-5, + // the fourth digit may be 0-9. + Node fourthDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9); + thirdDigit.addChild(fourthDigit); + // The time must be finished now. E.g. 10:49am, 12:40pm. + fourthDigit.addChild(ampm); + + // When the first digit is 1, and the second digit is 0-2, the third digit may be 6-9. + thirdDigit = new Node(k6, k7, k8, k9); + secondDigit.addChild(thirdDigit); + // The time must be finished now. E.g. 1:08am, 1:26pm. + thirdDigit.addChild(ampm); + + // When the first digit is 1, the second digit may be 3-5. + secondDigit = new Node(k3, k4, k5); + firstDigit.addChild(secondDigit); + + // When the first digit is 1, and the second digit is 3-5, the third digit may be 0-9. + thirdDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9); + secondDigit.addChild(thirdDigit); + // The time must be finished now. E.g. 1:39am, 1:50pm. + thirdDigit.addChild(ampm); + + // The hour digit may be 2-9. + firstDigit = new Node(k2, k3, k4, k5, k6, k7, k8, k9); + mLegalTimesTree.addChild(firstDigit); + // We'll allow quick input of on-the-hour-times. E.g. 2am, 5pm. + firstDigit.addChild(ampm); + + // When the first digit is 2-9, the second digit may be 0-5. + secondDigit = new Node(k0, k1, k2, k3, k4, k5); + firstDigit.addChild(secondDigit); + + // When the first digit is 2-9, and the second digit is 0-5, the third digit may be 0-9. + thirdDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9); + secondDigit.addChild(thirdDigit); + // The time must be finished now. E.g. 2:57am, 9:30pm. + thirdDigit.addChild(ampm); + } + } + + /** + * Simple node class to be used for traversal to check for legal times. + * mLegalKeys represents the keys that can be typed to get to the node. + * mChildren are the children that can be reached from this node. + */ + private class Node { + private int[] mLegalKeys; + private ArrayList<Node> mChildren; + + public Node(int... legalKeys) { + mLegalKeys = legalKeys; + mChildren = new ArrayList<Node>(); + } + + public void addChild(Node child) { + mChildren.add(child); + } + + public boolean containsKey(int key) { + for (int i = 0; i < mLegalKeys.length; i++) { + if (mLegalKeys[i] == key) { + return true; + } + } + return false; + } + + public Node canReach(int key) { + if (mChildren == null) { + return null; + } + for (Node child : mChildren) { + if (child.containsKey(key)) { + return child; + } + } + return null; + } + } + + private final View.OnClickListener mClickListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + + final int amOrPm; + switch (v.getId()) { + case R.id.am_label: + setAmOrPm(AM); + break; + case R.id.pm_label: + setAmOrPm(PM); + break; + case R.id.hours: + setCurrentItemShowing(HOUR_INDEX, true, true); + break; + case R.id.minutes: + setCurrentItemShowing(MINUTE_INDEX, true, true); + break; + default: + // Failed to handle this click, don't vibrate. + return; + } + + tryVibrate(); + } + }; + + private final View.OnKeyListener mKeyListener = new View.OnKeyListener() { + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_UP) { + return processKeyUp(keyCode); + } + return false; + } + }; + + private final View.OnFocusChangeListener mFocusListener = new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (!hasFocus && mInKbMode && isTypedTimeFullyLegal()) { + finishKbMode(); + + if (mOnTimeChangedListener != null) { + mOnTimeChangedListener.onTimeChanged(mDelegator, + mRadialTimePickerView.getCurrentHour(), + mRadialTimePickerView.getCurrentMinute()); + } + } + } + }; } diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java index 73e05e8d4932..e162f4ab67e8 100644 --- a/core/java/android/widget/TimePickerSpinnerDelegate.java +++ b/core/java/android/widget/TimePickerSpinnerDelegate.java @@ -17,380 +17,365 @@ package android.widget; import android.content.Context; -import android.content.res.ColorStateList; import android.content.res.Configuration; -import android.content.res.Resources; import android.content.res.TypedArray; import android.os.Parcel; import android.os.Parcelable; -import android.text.TextUtils; import android.text.format.DateFormat; import android.text.format.DateUtils; import android.util.AttributeSet; -import android.util.Log; -import android.view.HapticFeedbackConstants; -import android.view.KeyCharacterMap; -import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; - +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; import com.android.internal.R; -import java.util.ArrayList; +import java.text.DateFormatSymbols; import java.util.Calendar; import java.util.Locale; -/** - * A view for selecting the time of day, in either 24 hour or AM/PM mode. - */ -class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate implements - RadialTimePickerView.OnValueSelectedListener { - - private static final String TAG = "TimePickerDelegate"; - - // Index used by RadialPickerLayout - private static final int HOUR_INDEX = 0; - private static final int MINUTE_INDEX = 1; - - // NOT a real index for the purpose of what's showing. - private static final int AMPM_INDEX = 2; +import libcore.icu.LocaleData; - // Also NOT a real index, just used for keyboard mode. - private static final int ENABLE_PICKER_INDEX = 3; - - private static final int AM = 0; - private static final int PM = 1; +import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO; +import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES; +/** + * A delegate implementing the basic spinner-based TimePicker. + */ +class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate { private static final boolean DEFAULT_ENABLED_STATE = true; - private boolean mIsEnabled = DEFAULT_ENABLED_STATE; - private static final int HOURS_IN_HALF_DAY = 12; - private View mHeaderView; - private TextView mHourView; - private TextView mMinuteView; - private TextView mAmPmTextView; - private RadialTimePickerView mRadialTimePickerView; - private TextView mSeparatorView; + // state + private boolean mIs24HourView; + private boolean mIsAm; - private String mAmText; - private String mPmText; + // ui components + private final NumberPicker mHourSpinner; + private final NumberPicker mMinuteSpinner; + private final NumberPicker mAmPmSpinner; + private final EditText mHourSpinnerInput; + private final EditText mMinuteSpinnerInput; + private final EditText mAmPmSpinnerInput; + private final TextView mDivider; - private boolean mAllowAutoAdvance; - private int mInitialHourOfDay; - private int mInitialMinute; - private boolean mIs24HourView; + // Note that the legacy implementation of the TimePicker is + // using a button for toggling between AM/PM while the new + // version uses a NumberPicker spinner. Therefore the code + // accommodates these two cases to be backwards compatible. + private final Button mAmPmButton; - // For hardware IME input. - private char mPlaceholderText; - private String mDoublePlaceholderText; - private String mDeletedKeyFormat; - private boolean mInKbMode; - private ArrayList<Integer> mTypedTimes = new ArrayList<Integer>(); - private Node mLegalTimesTree; - private int mAmKeyCode; - private int mPmKeyCode; - - // Accessibility strings. - private String mHourPickerDescription; - private String mSelectHours; - private String mMinutePickerDescription; - private String mSelectMinutes; + private final String[] mAmPmStrings; + private boolean mIsEnabled = DEFAULT_ENABLED_STATE; private Calendar mTempCalendar; + private boolean mHourWithTwoDigit; + private char mHourFormat; public TimePickerSpinnerDelegate(TimePicker delegator, Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(delegator, context); // process style attributes - final TypedArray a = mContext.obtainStyledAttributes(attrs, - R.styleable.TimePicker, defStyleAttr, defStyleRes); - final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - final Resources res = mContext.getResources(); - - mHourPickerDescription = res.getString(R.string.hour_picker_description); - mSelectHours = res.getString(R.string.select_hours); - mMinutePickerDescription = res.getString(R.string.minute_picker_description); - mSelectMinutes = res.getString(R.string.select_minutes); - - String[] amPmStrings = TimePickerClockDelegate.getAmPmStrings(context); - mAmText = amPmStrings[0]; - mPmText = amPmStrings[1]; - - final int layoutResourceId = a.getResourceId(R.styleable.TimePicker_internalLayout, - R.layout.time_picker_holo); - final View mainView = inflater.inflate(layoutResourceId, null); - mDelegator.addView(mainView); - - mHourView = (TextView) mainView.findViewById(R.id.hours); - mSeparatorView = (TextView) mainView.findViewById(R.id.separator); - mMinuteView = (TextView) mainView.findViewById(R.id.minutes); - mAmPmTextView = (TextView) mainView.findViewById(R.id.ampm_label); - - // Set up text appearances from style. - final int headerTimeTextAppearance = a.getResourceId( - R.styleable.TimePicker_headerTimeTextAppearance, 0); - if (headerTimeTextAppearance != 0) { - mHourView.setTextAppearance(context, headerTimeTextAppearance); - mSeparatorView.setTextAppearance(context, headerTimeTextAppearance); - mMinuteView.setTextAppearance(context, headerTimeTextAppearance); - } + final TypedArray a = mContext.obtainStyledAttributes( + attrs, R.styleable.TimePicker, defStyleAttr, defStyleRes); + final int layoutResourceId = a.getResourceId( + R.styleable.TimePicker_legacyLayout, R.layout.time_picker_legacy); + a.recycle(); - final int headerSelectedTextColor = a.getColor( - R.styleable.TimePicker_headerSelectedTextColor, - res.getColor(R.color.timepicker_default_selector_color_material)); - mHourView.setTextColor(ColorStateList.addFirstIfMissing(mHourView.getTextColors(), - R.attr.state_selected, headerSelectedTextColor)); - mMinuteView.setTextColor(ColorStateList.addFirstIfMissing(mMinuteView.getTextColors(), - R.attr.state_selected, headerSelectedTextColor)); - - final int headerAmPmTextAppearance = a.getResourceId( - R.styleable.TimePicker_headerAmPmTextAppearance, 0); - if (headerAmPmTextAppearance != 0) { - mAmPmTextView.setTextAppearance(context, headerAmPmTextAppearance); + final LayoutInflater inflater = LayoutInflater.from(mContext); + inflater.inflate(layoutResourceId, mDelegator, true); + + // hour + mHourSpinner = (NumberPicker) delegator.findViewById(R.id.hour); + mHourSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { + public void onValueChange(NumberPicker spinner, int oldVal, int newVal) { + updateInputState(); + if (!is24HourView()) { + if ((oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY) || + (oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1)) { + mIsAm = !mIsAm; + updateAmPmControl(); + } + } + onTimeChanged(); + } + }); + mHourSpinnerInput = (EditText) mHourSpinner.findViewById(R.id.numberpicker_input); + mHourSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT); + + // divider (only for the new widget style) + mDivider = (TextView) mDelegator.findViewById(R.id.divider); + if (mDivider != null) { + setDividerText(); + } + + // minute + mMinuteSpinner = (NumberPicker) mDelegator.findViewById(R.id.minute); + mMinuteSpinner.setMinValue(0); + mMinuteSpinner.setMaxValue(59); + mMinuteSpinner.setOnLongPressUpdateInterval(100); + mMinuteSpinner.setFormatter(NumberPicker.getTwoDigitFormatter()); + mMinuteSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { + public void onValueChange(NumberPicker spinner, int oldVal, int newVal) { + updateInputState(); + int minValue = mMinuteSpinner.getMinValue(); + int maxValue = mMinuteSpinner.getMaxValue(); + if (oldVal == maxValue && newVal == minValue) { + int newHour = mHourSpinner.getValue() + 1; + if (!is24HourView() && newHour == HOURS_IN_HALF_DAY) { + mIsAm = !mIsAm; + updateAmPmControl(); + } + mHourSpinner.setValue(newHour); + } else if (oldVal == minValue && newVal == maxValue) { + int newHour = mHourSpinner.getValue() - 1; + if (!is24HourView() && newHour == HOURS_IN_HALF_DAY - 1) { + mIsAm = !mIsAm; + updateAmPmControl(); + } + mHourSpinner.setValue(newHour); + } + onTimeChanged(); + } + }); + mMinuteSpinnerInput = (EditText) mMinuteSpinner.findViewById(R.id.numberpicker_input); + mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT); + + // Get the localized am/pm strings and use them in the spinner. + mAmPmStrings = getAmPmStrings(context); + + // am/pm + final View amPmView = mDelegator.findViewById(R.id.amPm); + if (amPmView instanceof Button) { + mAmPmSpinner = null; + mAmPmSpinnerInput = null; + mAmPmButton = (Button) amPmView; + mAmPmButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View button) { + button.requestFocus(); + mIsAm = !mIsAm; + updateAmPmControl(); + onTimeChanged(); + } + }); + } else { + mAmPmButton = null; + mAmPmSpinner = (NumberPicker) amPmView; + mAmPmSpinner.setMinValue(0); + mAmPmSpinner.setMaxValue(1); + mAmPmSpinner.setDisplayedValues(mAmPmStrings); + mAmPmSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + updateInputState(); + picker.requestFocus(); + mIsAm = !mIsAm; + updateAmPmControl(); + onTimeChanged(); + } + }); + mAmPmSpinnerInput = (EditText) mAmPmSpinner.findViewById(R.id.numberpicker_input); + mAmPmSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE); + } + + if (isAmPmAtStart()) { + // Move the am/pm view to the beginning + ViewGroup amPmParent = (ViewGroup) delegator.findViewById(R.id.timePickerLayout); + amPmParent.removeView(amPmView); + amPmParent.addView(amPmView, 0); + // Swap layout margins if needed. They may be not symmetrical (Old Standard Theme + // for example and not for Holo Theme) + ViewGroup.MarginLayoutParams lp = + (ViewGroup.MarginLayoutParams) amPmView.getLayoutParams(); + final int startMargin = lp.getMarginStart(); + final int endMargin = lp.getMarginEnd(); + if (startMargin != endMargin) { + lp.setMarginStart(endMargin); + lp.setMarginEnd(startMargin); + } } - mHeaderView = mainView.findViewById(R.id.time_header); - mHeaderView.setBackground(a.getDrawable(R.styleable.TimePicker_headerBackground)); - - a.recycle(); + getHourFormatData(); - mRadialTimePickerView = (RadialTimePickerView) mainView.findViewById( - R.id.radial_picker); + // update controls to initial state + updateHourControl(); + updateMinuteControl(); + updateAmPmControl(); - setupListeners(); + // set to current time + setCurrentHour(mTempCalendar.get(Calendar.HOUR_OF_DAY)); + setCurrentMinute(mTempCalendar.get(Calendar.MINUTE)); - mAllowAutoAdvance = true; + if (!isEnabled()) { + setEnabled(false); + } - // Set up for keyboard mode. - mDoublePlaceholderText = res.getString(R.string.time_placeholder); - mDeletedKeyFormat = res.getString(R.string.deleted_key); - mPlaceholderText = mDoublePlaceholderText.charAt(0); - mAmKeyCode = mPmKeyCode = -1; - generateLegalTimesTree(); + // set the content descriptions + setContentDescriptions(); - // Initialize with current time - final Calendar calendar = Calendar.getInstance(mCurrentLocale); - final int currentHour = calendar.get(Calendar.HOUR_OF_DAY); - final int currentMinute = calendar.get(Calendar.MINUTE); - initialize(currentHour, currentMinute, false /* 12h */, HOUR_INDEX); - } - - private void initialize(int hourOfDay, int minute, boolean is24HourView, int index) { - mInitialHourOfDay = hourOfDay; - mInitialMinute = minute; - mIs24HourView = is24HourView; - mInKbMode = false; - updateUI(index); + // If not explicitly specified this view is important for accessibility. + if (mDelegator.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { + mDelegator.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); + } } - private void setupListeners() { - mHeaderView.setOnKeyListener(mKeyListener); - mHeaderView.setOnFocusChangeListener(mFocusListener); - mHeaderView.setFocusable(true); - - mRadialTimePickerView.setOnValueSelectedListener(this); - - mHourView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - setCurrentItemShowing(HOUR_INDEX, true, true); - tryVibrate(); - } - }); - mMinuteView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - setCurrentItemShowing(MINUTE_INDEX, true, true); - tryVibrate(); + private void getHourFormatData() { + final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale, + (mIs24HourView) ? "Hm" : "hm"); + final int lengthPattern = bestDateTimePattern.length(); + mHourWithTwoDigit = false; + char hourFormat = '\0'; + // Check if the returned pattern is single or double 'H', 'h', 'K', 'k'. We also save + // the hour format that we found. + for (int i = 0; i < lengthPattern; i++) { + final char c = bestDateTimePattern.charAt(i); + if (c == 'H' || c == 'h' || c == 'K' || c == 'k') { + mHourFormat = c; + if (i + 1 < lengthPattern && c == bestDateTimePattern.charAt(i + 1)) { + mHourWithTwoDigit = true; + } + break; } - }); + } } - private void updateUI(int index) { - // Update RadialPicker values - updateRadialPicker(index); - // Enable or disable the AM/PM view. - updateHeaderAmPm(); - // Update Hour and Minutes - updateHeaderHour(mInitialHourOfDay, true); - // Update time separator - updateHeaderSeparator(); - // Update Minutes - updateHeaderMinute(mInitialMinute); - // Invalidate everything - mDelegator.invalidate(); - } + private boolean isAmPmAtStart() { + final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale, + "hm" /* skeleton */); - private void updateRadialPicker(int index) { - mRadialTimePickerView.initialize(mInitialHourOfDay, mInitialMinute, mIs24HourView); - setCurrentItemShowing(index, false, true); + return bestDateTimePattern.startsWith("a"); } - private int computeMaxWidthOfNumbers(int max) { - TextView tempView = new TextView(mContext); - tempView.setTextAppearance(mContext, R.style.TextAppearance_Material_TimePicker_TimeLabel); - ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT); - tempView.setLayoutParams(lp); - int maxWidth = 0; - for (int minutes = 0; minutes < max; minutes++) { - final String text = String.format("%02d", minutes); - tempView.setText(text); - tempView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); - maxWidth = Math.max(maxWidth, tempView.getMeasuredWidth()); + /** + * The time separator is defined in the Unicode CLDR and cannot be supposed to be ":". + * + * See http://unicode.org/cldr/trac/browser/trunk/common/main + * + * We pass the correct "skeleton" depending on 12 or 24 hours view and then extract the + * separator as the character which is just after the hour marker in the returned pattern. + */ + private void setDividerText() { + final String skeleton = (mIs24HourView) ? "Hm" : "hm"; + final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale, + skeleton); + final String separatorText; + int hourIndex = bestDateTimePattern.lastIndexOf('H'); + if (hourIndex == -1) { + hourIndex = bestDateTimePattern.lastIndexOf('h'); } - return maxWidth; - } - - private void updateHeaderAmPm() { - if (mIs24HourView) { - mAmPmTextView.setVisibility(View.GONE); + if (hourIndex == -1) { + // Default case + separatorText = ":"; } else { - mAmPmTextView.setVisibility(View.VISIBLE); - final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale, - "hm"); - - boolean amPmOnLeft = bestDateTimePattern.startsWith("a"); - if (TextUtils.getLayoutDirectionFromLocale(mCurrentLocale) == - View.LAYOUT_DIRECTION_RTL) { - amPmOnLeft = !amPmOnLeft; - } - - RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) - mAmPmTextView.getLayoutParams(); - - if (amPmOnLeft) { - layoutParams.rightMargin = computeMaxWidthOfNumbers(12 /* for hours */); - layoutParams.removeRule(RelativeLayout.RIGHT_OF); - layoutParams.addRule(RelativeLayout.LEFT_OF, R.id.separator); + int minuteIndex = bestDateTimePattern.indexOf('m', hourIndex + 1); + if (minuteIndex == -1) { + separatorText = Character.toString(bestDateTimePattern.charAt(hourIndex + 1)); } else { - layoutParams.leftMargin = computeMaxWidthOfNumbers(60 /* for minutes */); - layoutParams.removeRule(RelativeLayout.LEFT_OF); - layoutParams.addRule(RelativeLayout.RIGHT_OF, R.id.separator); + separatorText = bestDateTimePattern.substring(hourIndex + 1, minuteIndex); } - - updateAmPmDisplay(mInitialHourOfDay < 12 ? AM : PM); - mAmPmTextView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - tryVibrate(); - int amOrPm = mRadialTimePickerView.getAmOrPm(); - if (amOrPm == AM) { - amOrPm = PM; - } else if (amOrPm == PM){ - amOrPm = AM; - } - updateAmPmDisplay(amOrPm); - mRadialTimePickerView.setAmOrPm(amOrPm); - } - }); } + mDivider.setText(separatorText); } - /** - * Set the current hour. - */ @Override public void setCurrentHour(Integer currentHour) { - if (mInitialHourOfDay == currentHour) { + setCurrentHour(currentHour, true); + } + + private void setCurrentHour(Integer currentHour, boolean notifyTimeChanged) { + // why was Integer used in the first place? + if (currentHour == null || currentHour == getCurrentHour()) { return; } - mInitialHourOfDay = currentHour; - updateHeaderHour(currentHour, true /* accessibility announce */); - updateHeaderAmPm(); - mRadialTimePickerView.setCurrentHour(currentHour); - mRadialTimePickerView.setAmOrPm(mInitialHourOfDay < 12 ? AM : PM); - mDelegator.invalidate(); - onTimeChanged(); + if (!is24HourView()) { + // convert [0,23] ordinal to wall clock display + if (currentHour >= HOURS_IN_HALF_DAY) { + mIsAm = false; + if (currentHour > HOURS_IN_HALF_DAY) { + currentHour = currentHour - HOURS_IN_HALF_DAY; + } + } else { + mIsAm = true; + if (currentHour == 0) { + currentHour = HOURS_IN_HALF_DAY; + } + } + updateAmPmControl(); + } + mHourSpinner.setValue(currentHour); + if (notifyTimeChanged) { + onTimeChanged(); + } } - /** - * @return The current hour in the range (0-23). - */ @Override public Integer getCurrentHour() { - int currentHour = mRadialTimePickerView.getCurrentHour(); - if (mIs24HourView) { + int currentHour = mHourSpinner.getValue(); + if (is24HourView()) { return currentHour; + } else if (mIsAm) { + return currentHour % HOURS_IN_HALF_DAY; } else { - switch(mRadialTimePickerView.getAmOrPm()) { - case PM: - return (currentHour % HOURS_IN_HALF_DAY) + HOURS_IN_HALF_DAY; - case AM: - default: - return currentHour % HOURS_IN_HALF_DAY; - } + return (currentHour % HOURS_IN_HALF_DAY) + HOURS_IN_HALF_DAY; } } - /** - * Set the current minute (0-59). - */ @Override public void setCurrentMinute(Integer currentMinute) { - if (mInitialMinute == currentMinute) { + if (currentMinute == getCurrentMinute()) { return; } - mInitialMinute = currentMinute; - updateHeaderMinute(currentMinute); - mRadialTimePickerView.setCurrentMinute(currentMinute); - mDelegator.invalidate(); + mMinuteSpinner.setValue(currentMinute); onTimeChanged(); } - /** - * @return The current minute. - */ @Override public Integer getCurrentMinute() { - return mRadialTimePickerView.getCurrentMinute(); + return mMinuteSpinner.getValue(); } - /** - * Set whether in 24 hour or AM/PM mode. - * - * @param is24HourView True = 24 hour mode. False = AM/PM. - */ @Override public void setIs24HourView(Boolean is24HourView) { - if (is24HourView == mIs24HourView) { + if (mIs24HourView == is24HourView) { return; } + // cache the current hour since spinner range changes and BEFORE changing mIs24HourView!! + int currentHour = getCurrentHour(); + // Order is important here. mIs24HourView = is24HourView; - generateLegalTimesTree(); - int hour = mRadialTimePickerView.getCurrentHour(); - mInitialHourOfDay = hour; - updateHeaderHour(hour, false /* no accessibility announce */); - updateHeaderAmPm(); - updateRadialPicker(mRadialTimePickerView.getCurrentItemShowing()); - mDelegator.invalidate(); + getHourFormatData(); + updateHourControl(); + // set value after spinner range is updated + setCurrentHour(currentHour, false); + updateMinuteControl(); + updateAmPmControl(); } - /** - * @return true if this is in 24 hour view else false. - */ @Override public boolean is24HourView() { return mIs24HourView; } @Override - public void setOnTimeChangedListener(TimePicker.OnTimeChangedListener callback) { - mOnTimeChangedListener = callback; + public void setOnTimeChangedListener(TimePicker.OnTimeChangedListener onTimeChangedListener) { + mOnTimeChangedListener = onTimeChangedListener; } @Override public void setEnabled(boolean enabled) { - mHourView.setEnabled(enabled); - mMinuteView.setEnabled(enabled); - mAmPmTextView.setEnabled(enabled); - mRadialTimePickerView.setEnabled(enabled); + mMinuteSpinner.setEnabled(enabled); + if (mDivider != null) { + mDivider.setEnabled(enabled); + } + mHourSpinner.setEnabled(enabled); + if (mAmPmSpinner != null) { + mAmPmSpinner.setEnabled(enabled); + } else { + mAmPmButton.setEnabled(enabled); + } mIsEnabled = enabled; } @@ -401,38 +386,24 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im @Override public int getBaseline() { - // does not support baseline alignment - return -1; + return mHourSpinner.getBaseline(); } @Override public void onConfigurationChanged(Configuration newConfig) { - updateUI(mRadialTimePickerView.getCurrentItemShowing()); + setCurrentLocale(newConfig.locale); } @Override public Parcelable onSaveInstanceState(Parcelable superState) { - return new SavedState(superState, getCurrentHour(), getCurrentMinute(), - is24HourView(), inKbMode(), getTypedTimes(), getCurrentItemShowing()); + return new SavedState(superState, getCurrentHour(), getCurrentMinute()); } @Override public void onRestoreInstanceState(Parcelable state) { SavedState ss = (SavedState) state; - setInKbMode(ss.inKbMode()); - setTypedTimes(ss.getTypesTimes()); - initialize(ss.getHour(), ss.getMinute(), ss.is24HourMode(), ss.getCurrentItemShowing()); - mRadialTimePickerView.invalidate(); - if (mInKbMode) { - tryStartingKbMode(-1); - mHourView.invalidate(); - } - } - - @Override - public void setCurrentLocale(Locale locale) { - super.setCurrentLocale(locale); - mTempCalendar = Calendar.getInstance(locale); + setCurrentHour(ss.getHour()); + setCurrentMinute(ss.getMinute()); } @Override @@ -451,9 +422,9 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im } mTempCalendar.set(Calendar.HOUR_OF_DAY, getCurrentHour()); mTempCalendar.set(Calendar.MINUTE, getCurrentMinute()); - String selectedDate = DateUtils.formatDateTime(mContext, + String selectedDateUtterance = DateUtils.formatDateTime(mContext, mTempCalendar.getTimeInMillis(), flags); - event.getText().add(selectedDate); + event.getText().add(selectedDateUtterance); } @Override @@ -466,48 +437,121 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im info.setClassName(TimePicker.class.getName()); } + private void updateInputState() { + // Make sure that if the user changes the value and the IME is active + // for one of the inputs if this widget, the IME is closed. If the user + // changed the value via the IME and there is a next input the IME will + // be shown, otherwise the user chose another means of changing the + // value and having the IME up makes no sense. + InputMethodManager inputMethodManager = InputMethodManager.peekInstance(); + if (inputMethodManager != null) { + if (inputMethodManager.isActive(mHourSpinnerInput)) { + mHourSpinnerInput.clearFocus(); + inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0); + } else if (inputMethodManager.isActive(mMinuteSpinnerInput)) { + mMinuteSpinnerInput.clearFocus(); + inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0); + } else if (inputMethodManager.isActive(mAmPmSpinnerInput)) { + mAmPmSpinnerInput.clearFocus(); + inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0); + } + } + } + + private void updateAmPmControl() { + if (is24HourView()) { + if (mAmPmSpinner != null) { + mAmPmSpinner.setVisibility(View.GONE); + } else { + mAmPmButton.setVisibility(View.GONE); + } + } else { + int index = mIsAm ? Calendar.AM : Calendar.PM; + if (mAmPmSpinner != null) { + mAmPmSpinner.setValue(index); + mAmPmSpinner.setVisibility(View.VISIBLE); + } else { + mAmPmButton.setText(mAmPmStrings[index]); + mAmPmButton.setVisibility(View.VISIBLE); + } + } + mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); + } + /** - * Set whether in keyboard mode or not. + * Sets the current locale. * - * @param inKbMode True means in keyboard mode. + * @param locale The current locale. */ - private void setInKbMode(boolean inKbMode) { - mInKbMode = inKbMode; + @Override + public void setCurrentLocale(Locale locale) { + super.setCurrentLocale(locale); + mTempCalendar = Calendar.getInstance(locale); } - /** - * @return true if in keyboard mode - */ - private boolean inKbMode() { - return mInKbMode; + private void onTimeChanged() { + mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); + if (mOnTimeChangedListener != null) { + mOnTimeChangedListener.onTimeChanged(mDelegator, getCurrentHour(), + getCurrentMinute()); + } } - private void setTypedTimes(ArrayList<Integer> typeTimes) { - mTypedTimes = typeTimes; + private void updateHourControl() { + if (is24HourView()) { + // 'k' means 1-24 hour + if (mHourFormat == 'k') { + mHourSpinner.setMinValue(1); + mHourSpinner.setMaxValue(24); + } else { + mHourSpinner.setMinValue(0); + mHourSpinner.setMaxValue(23); + } + } else { + // 'K' means 0-11 hour + if (mHourFormat == 'K') { + mHourSpinner.setMinValue(0); + mHourSpinner.setMaxValue(11); + } else { + mHourSpinner.setMinValue(1); + mHourSpinner.setMaxValue(12); + } + } + mHourSpinner.setFormatter(mHourWithTwoDigit ? NumberPicker.getTwoDigitFormatter() : null); } - /** - * @return an array of typed times - */ - private ArrayList<Integer> getTypedTimes() { - return mTypedTimes; + private void updateMinuteControl() { + if (is24HourView()) { + mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE); + } else { + mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT); + } } - /** - * @return the index of the current item showing - */ - private int getCurrentItemShowing() { - return mRadialTimePickerView.getCurrentItemShowing(); + private void setContentDescriptions() { + // Minute + trySetContentDescription(mMinuteSpinner, R.id.increment, + R.string.time_picker_increment_minute_button); + trySetContentDescription(mMinuteSpinner, R.id.decrement, + R.string.time_picker_decrement_minute_button); + // Hour + trySetContentDescription(mHourSpinner, R.id.increment, + R.string.time_picker_increment_hour_button); + trySetContentDescription(mHourSpinner, R.id.decrement, + R.string.time_picker_decrement_hour_button); + // AM/PM + if (mAmPmSpinner != null) { + trySetContentDescription(mAmPmSpinner, R.id.increment, + R.string.time_picker_increment_set_pm_button); + trySetContentDescription(mAmPmSpinner, R.id.decrement, + R.string.time_picker_decrement_set_am_button); + } } - /** - * Propagate the time change - */ - private void onTimeChanged() { - mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); - if (mOnTimeChangedListener != null) { - mOnTimeChangedListener.onTimeChanged(mDelegator, - getCurrentHour(), getCurrentMinute()); + private void trySetContentDescription(View root, int viewId, int contDescResId) { + View target = root.findViewById(viewId); + if (target != null) { + target.setContentDescription(mContext.getString(contDescResId)); } } @@ -515,34 +559,19 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im * Used to save / restore state of time picker */ private static class SavedState extends View.BaseSavedState { - private final int mHour; private final int mMinute; - private final boolean mIs24HourMode; - private final boolean mInKbMode; - private final ArrayList<Integer> mTypedTimes; - private final int mCurrentItemShowing; - - private SavedState(Parcelable superState, int hour, int minute, boolean is24HourMode, - boolean isKbMode, ArrayList<Integer> typedTimes, - int currentItemShowing) { + + private SavedState(Parcelable superState, int hour, int minute) { super(superState); mHour = hour; mMinute = minute; - mIs24HourMode = is24HourMode; - mInKbMode = isKbMode; - mTypedTimes = typedTimes; - mCurrentItemShowing = currentItemShowing; } private SavedState(Parcel in) { super(in); mHour = in.readInt(); mMinute = in.readInt(); - mIs24HourMode = (in.readInt() == 1); - mInKbMode = (in.readInt() == 1); - mTypedTimes = in.readArrayList(getClass().getClassLoader()); - mCurrentItemShowing = in.readInt(); } public int getHour() { @@ -553,31 +582,11 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im return mMinute; } - public boolean is24HourMode() { - return mIs24HourMode; - } - - public boolean inKbMode() { - return mInKbMode; - } - - public ArrayList<Integer> getTypesTimes() { - return mTypedTimes; - } - - public int getCurrentItemShowing() { - return mCurrentItemShowing; - } - @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeInt(mHour); dest.writeInt(mMinute); - dest.writeInt(mIs24HourMode ? 1 : 0); - dest.writeInt(mInKbMode ? 1 : 0); - dest.writeList(mTypedTimes); - dest.writeInt(mCurrentItemShowing); } @SuppressWarnings({"unused", "hiding"}) @@ -592,667 +601,11 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im }; } - private void tryVibrate() { - mDelegator.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK); - } - - private void updateAmPmDisplay(int amOrPm) { - if (amOrPm == AM) { - mAmPmTextView.setText(mAmText); - mRadialTimePickerView.announceForAccessibility(mAmText); - } else if (amOrPm == PM){ - mAmPmTextView.setText(mPmText); - mRadialTimePickerView.announceForAccessibility(mPmText); - } else { - mAmPmTextView.setText(mDoublePlaceholderText); - } - } - - /** - * Called by the picker for updating the header display. - */ - @Override - public void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance) { - if (pickerIndex == HOUR_INDEX) { - updateHeaderHour(newValue, false); - String announcement = String.format("%d", newValue); - if (mAllowAutoAdvance && autoAdvance) { - setCurrentItemShowing(MINUTE_INDEX, true, false); - announcement += ". " + mSelectMinutes; - } else { - mRadialTimePickerView.setContentDescription( - mHourPickerDescription + ": " + newValue); - } - - mRadialTimePickerView.announceForAccessibility(announcement); - } else if (pickerIndex == MINUTE_INDEX){ - updateHeaderMinute(newValue); - mRadialTimePickerView.setContentDescription(mMinutePickerDescription + ": " + newValue); - } else if (pickerIndex == AMPM_INDEX) { - updateAmPmDisplay(newValue); - } else if (pickerIndex == ENABLE_PICKER_INDEX) { - if (!isTypedTimeFullyLegal()) { - mTypedTimes.clear(); - } - finishKbMode(); - } - } - - private void updateHeaderHour(int value, boolean announce) { - final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale, - (mIs24HourView) ? "Hm" : "hm"); - final int lengthPattern = bestDateTimePattern.length(); - boolean hourWithTwoDigit = false; - char hourFormat = '\0'; - // Check if the returned pattern is single or double 'H', 'h', 'K', 'k'. We also save - // the hour format that we found. - for (int i = 0; i < lengthPattern; i++) { - final char c = bestDateTimePattern.charAt(i); - if (c == 'H' || c == 'h' || c == 'K' || c == 'k') { - hourFormat = c; - if (i + 1 < lengthPattern && c == bestDateTimePattern.charAt(i + 1)) { - hourWithTwoDigit = true; - } - break; - } - } - final String format; - if (hourWithTwoDigit) { - format = "%02d"; - } else { - format = "%d"; - } - if (mIs24HourView) { - // 'k' means 1-24 hour - if (hourFormat == 'k' && value == 0) { - value = 24; - } - } else { - // 'K' means 0-11 hour - value = modulo12(value, hourFormat == 'K'); - } - CharSequence text = String.format(format, value); - mHourView.setText(text); - if (announce) { - mRadialTimePickerView.announceForAccessibility(text); - } - } - - private static int modulo12(int n, boolean startWithZero) { - int value = n % 12; - if (value == 0 && !startWithZero) { - value = 12; - } - return value; - } - - /** - * The time separator is defined in the Unicode CLDR and cannot be supposed to be ":". - * - * See http://unicode.org/cldr/trac/browser/trunk/common/main - * - * We pass the correct "skeleton" depending on 12 or 24 hours view and then extract the - * separator as the character which is just after the hour marker in the returned pattern. - */ - private void updateHeaderSeparator() { - final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale, - (mIs24HourView) ? "Hm" : "hm"); - final String separatorText; - // See http://www.unicode.org/reports/tr35/tr35-dates.html for hour formats - final char[] hourFormats = {'H', 'h', 'K', 'k'}; - int hIndex = lastIndexOfAny(bestDateTimePattern, hourFormats); - if (hIndex == -1) { - // Default case - separatorText = ":"; - } else { - separatorText = Character.toString(bestDateTimePattern.charAt(hIndex + 1)); - } - mSeparatorView.setText(separatorText); - } - - static private int lastIndexOfAny(String str, char[] any) { - final int lengthAny = any.length; - if (lengthAny > 0) { - for (int i = str.length() - 1; i >= 0; i--) { - char c = str.charAt(i); - for (int j = 0; j < lengthAny; j++) { - if (c == any[j]) { - return i; - } - } - } - } - return -1; - } - - private void updateHeaderMinute(int value) { - if (value == 60) { - value = 0; - } - CharSequence text = String.format(mCurrentLocale, "%02d", value); - mRadialTimePickerView.announceForAccessibility(text); - mMinuteView.setText(text); - } - - /** - * Show either Hours or Minutes. - */ - private void setCurrentItemShowing(int index, boolean animateCircle, boolean announce) { - mRadialTimePickerView.setCurrentItemShowing(index, animateCircle); - - if (index == HOUR_INDEX) { - int hours = mRadialTimePickerView.getCurrentHour(); - if (!mIs24HourView) { - hours = hours % 12; - } - mRadialTimePickerView.setContentDescription(mHourPickerDescription + ": " + hours); - if (announce) { - mRadialTimePickerView.announceForAccessibility(mSelectHours); - } - } else { - int minutes = mRadialTimePickerView.getCurrentMinute(); - mRadialTimePickerView.setContentDescription(mMinutePickerDescription + ": " + minutes); - if (announce) { - mRadialTimePickerView.announceForAccessibility(mSelectMinutes); - } - } - - mHourView.setSelected(index == HOUR_INDEX); - mMinuteView.setSelected(index == MINUTE_INDEX); - } - - /** - * For keyboard mode, processes key events. - * - * @param keyCode the pressed key. - * - * @return true if the key was successfully processed, false otherwise. - */ - private boolean processKeyUp(int keyCode) { - if (keyCode == KeyEvent.KEYCODE_DEL) { - if (mInKbMode) { - if (!mTypedTimes.isEmpty()) { - int deleted = deleteLastTypedKey(); - String deletedKeyStr; - if (deleted == getAmOrPmKeyCode(AM)) { - deletedKeyStr = mAmText; - } else if (deleted == getAmOrPmKeyCode(PM)) { - deletedKeyStr = mPmText; - } else { - deletedKeyStr = String.format("%d", getValFromKeyCode(deleted)); - } - mRadialTimePickerView.announceForAccessibility( - String.format(mDeletedKeyFormat, deletedKeyStr)); - updateDisplay(true); - } - } - } else if (keyCode == KeyEvent.KEYCODE_0 || keyCode == KeyEvent.KEYCODE_1 - || keyCode == KeyEvent.KEYCODE_2 || keyCode == KeyEvent.KEYCODE_3 - || keyCode == KeyEvent.KEYCODE_4 || keyCode == KeyEvent.KEYCODE_5 - || keyCode == KeyEvent.KEYCODE_6 || keyCode == KeyEvent.KEYCODE_7 - || keyCode == KeyEvent.KEYCODE_8 || keyCode == KeyEvent.KEYCODE_9 - || (!mIs24HourView && - (keyCode == getAmOrPmKeyCode(AM) || keyCode == getAmOrPmKeyCode(PM)))) { - if (!mInKbMode) { - if (mRadialTimePickerView == null) { - // Something's wrong, because time picker should definitely not be null. - Log.e(TAG, "Unable to initiate keyboard mode, TimePicker was null."); - return true; - } - mTypedTimes.clear(); - tryStartingKbMode(keyCode); - return true; - } - // We're already in keyboard mode. - if (addKeyIfLegal(keyCode)) { - updateDisplay(false); - } - return true; - } - return false; - } - - /** - * Try to start keyboard mode with the specified key. - * - * @param keyCode The key to use as the first press. Keyboard mode will not be started if the - * key is not legal to start with. Or, pass in -1 to get into keyboard mode without a starting - * key. - */ - private void tryStartingKbMode(int keyCode) { - if (keyCode == -1 || addKeyIfLegal(keyCode)) { - mInKbMode = true; - onValidationChanged(false); - updateDisplay(false); - mRadialTimePickerView.setInputEnabled(false); - } - } - - private boolean addKeyIfLegal(int keyCode) { - // If we're in 24hour mode, we'll need to check if the input is full. If in AM/PM mode, - // we'll need to see if AM/PM have been typed. - if ((mIs24HourView && mTypedTimes.size() == 4) || - (!mIs24HourView && isTypedTimeFullyLegal())) { - return false; - } - - mTypedTimes.add(keyCode); - if (!isTypedTimeLegalSoFar()) { - deleteLastTypedKey(); - return false; - } - - int val = getValFromKeyCode(keyCode); - mRadialTimePickerView.announceForAccessibility(String.format("%d", val)); - // Automatically fill in 0's if AM or PM was legally entered. - if (isTypedTimeFullyLegal()) { - if (!mIs24HourView && mTypedTimes.size() <= 3) { - mTypedTimes.add(mTypedTimes.size() - 1, KeyEvent.KEYCODE_0); - mTypedTimes.add(mTypedTimes.size() - 1, KeyEvent.KEYCODE_0); - } - onValidationChanged(true); - } - - return true; + public static String[] getAmPmStrings(Context context) { + String[] result = new String[2]; + LocaleData d = LocaleData.get(context.getResources().getConfiguration().locale); + result[0] = d.amPm[0].length() > 2 ? d.narrowAm : d.amPm[0]; + result[1] = d.amPm[1].length() > 2 ? d.narrowPm : d.amPm[1]; + return result; } - - /** - * Traverse the tree to see if the keys that have been typed so far are legal as is, - * or may become legal as more keys are typed (excluding backspace). - */ - private boolean isTypedTimeLegalSoFar() { - Node node = mLegalTimesTree; - for (int keyCode : mTypedTimes) { - node = node.canReach(keyCode); - if (node == null) { - return false; - } - } - return true; - } - - /** - * Check if the time that has been typed so far is completely legal, as is. - */ - private boolean isTypedTimeFullyLegal() { - if (mIs24HourView) { - // For 24-hour mode, the time is legal if the hours and minutes are each legal. Note: - // getEnteredTime() will ONLY call isTypedTimeFullyLegal() when NOT in 24hour mode. - int[] values = getEnteredTime(null); - return (values[0] >= 0 && values[1] >= 0 && values[1] < 60); - } else { - // For AM/PM mode, the time is legal if it contains an AM or PM, as those can only be - // legally added at specific times based on the tree's algorithm. - return (mTypedTimes.contains(getAmOrPmKeyCode(AM)) || - mTypedTimes.contains(getAmOrPmKeyCode(PM))); - } - } - - private int deleteLastTypedKey() { - int deleted = mTypedTimes.remove(mTypedTimes.size() - 1); - if (!isTypedTimeFullyLegal()) { - onValidationChanged(false); - } - return deleted; - } - - /** - * Get out of keyboard mode. If there is nothing in typedTimes, revert to TimePicker's time. - */ - private void finishKbMode() { - mInKbMode = false; - if (!mTypedTimes.isEmpty()) { - int values[] = getEnteredTime(null); - mRadialTimePickerView.setCurrentHour(values[0]); - mRadialTimePickerView.setCurrentMinute(values[1]); - if (!mIs24HourView) { - mRadialTimePickerView.setAmOrPm(values[2]); - } - mTypedTimes.clear(); - } - updateDisplay(false); - mRadialTimePickerView.setInputEnabled(true); - } - - /** - * Update the hours, minutes, and AM/PM displays with the typed times. If the typedTimes is - * empty, either show an empty display (filled with the placeholder text), or update from the - * timepicker's values. - * - * @param allowEmptyDisplay if true, then if the typedTimes is empty, use the placeholder text. - * Otherwise, revert to the timepicker's values. - */ - private void updateDisplay(boolean allowEmptyDisplay) { - if (!allowEmptyDisplay && mTypedTimes.isEmpty()) { - int hour = mRadialTimePickerView.getCurrentHour(); - int minute = mRadialTimePickerView.getCurrentMinute(); - updateHeaderHour(hour, true); - updateHeaderMinute(minute); - if (!mIs24HourView) { - updateAmPmDisplay(hour < 12 ? AM : PM); - } - setCurrentItemShowing(mRadialTimePickerView.getCurrentItemShowing(), true, true); - onValidationChanged(true); - } else { - boolean[] enteredZeros = {false, false}; - int[] values = getEnteredTime(enteredZeros); - String hourFormat = enteredZeros[0] ? "%02d" : "%2d"; - String minuteFormat = (enteredZeros[1]) ? "%02d" : "%2d"; - String hourStr = (values[0] == -1) ? mDoublePlaceholderText : - String.format(hourFormat, values[0]).replace(' ', mPlaceholderText); - String minuteStr = (values[1] == -1) ? mDoublePlaceholderText : - String.format(minuteFormat, values[1]).replace(' ', mPlaceholderText); - mHourView.setText(hourStr); - mHourView.setSelected(false); - mMinuteView.setText(minuteStr); - mMinuteView.setSelected(false); - if (!mIs24HourView) { - updateAmPmDisplay(values[2]); - } - } - } - - private int getValFromKeyCode(int keyCode) { - switch (keyCode) { - case KeyEvent.KEYCODE_0: - return 0; - case KeyEvent.KEYCODE_1: - return 1; - case KeyEvent.KEYCODE_2: - return 2; - case KeyEvent.KEYCODE_3: - return 3; - case KeyEvent.KEYCODE_4: - return 4; - case KeyEvent.KEYCODE_5: - return 5; - case KeyEvent.KEYCODE_6: - return 6; - case KeyEvent.KEYCODE_7: - return 7; - case KeyEvent.KEYCODE_8: - return 8; - case KeyEvent.KEYCODE_9: - return 9; - default: - return -1; - } - } - - /** - * Get the currently-entered time, as integer values of the hours and minutes typed. - * - * @param enteredZeros A size-2 boolean array, which the caller should initialize, and which - * may then be used for the caller to know whether zeros had been explicitly entered as either - * hours of minutes. This is helpful for deciding whether to show the dashes, or actual 0's. - * - * @return A size-3 int array. The first value will be the hours, the second value will be the - * minutes, and the third will be either AM or PM. - */ - private int[] getEnteredTime(boolean[] enteredZeros) { - int amOrPm = -1; - int startIndex = 1; - if (!mIs24HourView && isTypedTimeFullyLegal()) { - int keyCode = mTypedTimes.get(mTypedTimes.size() - 1); - if (keyCode == getAmOrPmKeyCode(AM)) { - amOrPm = AM; - } else if (keyCode == getAmOrPmKeyCode(PM)){ - amOrPm = PM; - } - startIndex = 2; - } - int minute = -1; - int hour = -1; - for (int i = startIndex; i <= mTypedTimes.size(); i++) { - int val = getValFromKeyCode(mTypedTimes.get(mTypedTimes.size() - i)); - if (i == startIndex) { - minute = val; - } else if (i == startIndex+1) { - minute += 10 * val; - if (enteredZeros != null && val == 0) { - enteredZeros[1] = true; - } - } else if (i == startIndex+2) { - hour = val; - } else if (i == startIndex+3) { - hour += 10 * val; - if (enteredZeros != null && val == 0) { - enteredZeros[0] = true; - } - } - } - - return new int[] { hour, minute, amOrPm }; - } - - /** - * Get the keycode value for AM and PM in the current language. - */ - private int getAmOrPmKeyCode(int amOrPm) { - // Cache the codes. - if (mAmKeyCode == -1 || mPmKeyCode == -1) { - // Find the first character in the AM/PM text that is unique. - KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); - char amChar; - char pmChar; - for (int i = 0; i < Math.max(mAmText.length(), mPmText.length()); i++) { - amChar = mAmText.toLowerCase(mCurrentLocale).charAt(i); - pmChar = mPmText.toLowerCase(mCurrentLocale).charAt(i); - if (amChar != pmChar) { - KeyEvent[] events = kcm.getEvents(new char[]{amChar, pmChar}); - // There should be 4 events: a down and up for both AM and PM. - if (events != null && events.length == 4) { - mAmKeyCode = events[0].getKeyCode(); - mPmKeyCode = events[2].getKeyCode(); - } else { - Log.e(TAG, "Unable to find keycodes for AM and PM."); - } - break; - } - } - } - if (amOrPm == AM) { - return mAmKeyCode; - } else if (amOrPm == PM) { - return mPmKeyCode; - } - - return -1; - } - - /** - * Create a tree for deciding what keys can legally be typed. - */ - private void generateLegalTimesTree() { - // Create a quick cache of numbers to their keycodes. - final int k0 = KeyEvent.KEYCODE_0; - final int k1 = KeyEvent.KEYCODE_1; - final int k2 = KeyEvent.KEYCODE_2; - final int k3 = KeyEvent.KEYCODE_3; - final int k4 = KeyEvent.KEYCODE_4; - final int k5 = KeyEvent.KEYCODE_5; - final int k6 = KeyEvent.KEYCODE_6; - final int k7 = KeyEvent.KEYCODE_7; - final int k8 = KeyEvent.KEYCODE_8; - final int k9 = KeyEvent.KEYCODE_9; - - // The root of the tree doesn't contain any numbers. - mLegalTimesTree = new Node(); - if (mIs24HourView) { - // We'll be re-using these nodes, so we'll save them. - Node minuteFirstDigit = new Node(k0, k1, k2, k3, k4, k5); - Node minuteSecondDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9); - // The first digit must be followed by the second digit. - minuteFirstDigit.addChild(minuteSecondDigit); - - // The first digit may be 0-1. - Node firstDigit = new Node(k0, k1); - mLegalTimesTree.addChild(firstDigit); - - // When the first digit is 0-1, the second digit may be 0-5. - Node secondDigit = new Node(k0, k1, k2, k3, k4, k5); - firstDigit.addChild(secondDigit); - // We may now be followed by the first minute digit. E.g. 00:09, 15:58. - secondDigit.addChild(minuteFirstDigit); - - // When the first digit is 0-1, and the second digit is 0-5, the third digit may be 6-9. - Node thirdDigit = new Node(k6, k7, k8, k9); - // The time must now be finished. E.g. 0:55, 1:08. - secondDigit.addChild(thirdDigit); - - // When the first digit is 0-1, the second digit may be 6-9. - secondDigit = new Node(k6, k7, k8, k9); - firstDigit.addChild(secondDigit); - // We must now be followed by the first minute digit. E.g. 06:50, 18:20. - secondDigit.addChild(minuteFirstDigit); - - // The first digit may be 2. - firstDigit = new Node(k2); - mLegalTimesTree.addChild(firstDigit); - - // When the first digit is 2, the second digit may be 0-3. - secondDigit = new Node(k0, k1, k2, k3); - firstDigit.addChild(secondDigit); - // We must now be followed by the first minute digit. E.g. 20:50, 23:09. - secondDigit.addChild(minuteFirstDigit); - - // When the first digit is 2, the second digit may be 4-5. - secondDigit = new Node(k4, k5); - firstDigit.addChild(secondDigit); - // We must now be followd by the last minute digit. E.g. 2:40, 2:53. - secondDigit.addChild(minuteSecondDigit); - - // The first digit may be 3-9. - firstDigit = new Node(k3, k4, k5, k6, k7, k8, k9); - mLegalTimesTree.addChild(firstDigit); - // We must now be followed by the first minute digit. E.g. 3:57, 8:12. - firstDigit.addChild(minuteFirstDigit); - } else { - // We'll need to use the AM/PM node a lot. - // Set up AM and PM to respond to "a" and "p". - Node ampm = new Node(getAmOrPmKeyCode(AM), getAmOrPmKeyCode(PM)); - - // The first hour digit may be 1. - Node firstDigit = new Node(k1); - mLegalTimesTree.addChild(firstDigit); - // We'll allow quick input of on-the-hour times. E.g. 1pm. - firstDigit.addChild(ampm); - - // When the first digit is 1, the second digit may be 0-2. - Node secondDigit = new Node(k0, k1, k2); - firstDigit.addChild(secondDigit); - // Also for quick input of on-the-hour times. E.g. 10pm, 12am. - secondDigit.addChild(ampm); - - // When the first digit is 1, and the second digit is 0-2, the third digit may be 0-5. - Node thirdDigit = new Node(k0, k1, k2, k3, k4, k5); - secondDigit.addChild(thirdDigit); - // The time may be finished now. E.g. 1:02pm, 1:25am. - thirdDigit.addChild(ampm); - - // When the first digit is 1, the second digit is 0-2, and the third digit is 0-5, - // the fourth digit may be 0-9. - Node fourthDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9); - thirdDigit.addChild(fourthDigit); - // The time must be finished now. E.g. 10:49am, 12:40pm. - fourthDigit.addChild(ampm); - - // When the first digit is 1, and the second digit is 0-2, the third digit may be 6-9. - thirdDigit = new Node(k6, k7, k8, k9); - secondDigit.addChild(thirdDigit); - // The time must be finished now. E.g. 1:08am, 1:26pm. - thirdDigit.addChild(ampm); - - // When the first digit is 1, the second digit may be 3-5. - secondDigit = new Node(k3, k4, k5); - firstDigit.addChild(secondDigit); - - // When the first digit is 1, and the second digit is 3-5, the third digit may be 0-9. - thirdDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9); - secondDigit.addChild(thirdDigit); - // The time must be finished now. E.g. 1:39am, 1:50pm. - thirdDigit.addChild(ampm); - - // The hour digit may be 2-9. - firstDigit = new Node(k2, k3, k4, k5, k6, k7, k8, k9); - mLegalTimesTree.addChild(firstDigit); - // We'll allow quick input of on-the-hour-times. E.g. 2am, 5pm. - firstDigit.addChild(ampm); - - // When the first digit is 2-9, the second digit may be 0-5. - secondDigit = new Node(k0, k1, k2, k3, k4, k5); - firstDigit.addChild(secondDigit); - - // When the first digit is 2-9, and the second digit is 0-5, the third digit may be 0-9. - thirdDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9); - secondDigit.addChild(thirdDigit); - // The time must be finished now. E.g. 2:57am, 9:30pm. - thirdDigit.addChild(ampm); - } - } - - /** - * Simple node class to be used for traversal to check for legal times. - * mLegalKeys represents the keys that can be typed to get to the node. - * mChildren are the children that can be reached from this node. - */ - private class Node { - private int[] mLegalKeys; - private ArrayList<Node> mChildren; - - public Node(int... legalKeys) { - mLegalKeys = legalKeys; - mChildren = new ArrayList<Node>(); - } - - public void addChild(Node child) { - mChildren.add(child); - } - - public boolean containsKey(int key) { - for (int i = 0; i < mLegalKeys.length; i++) { - if (mLegalKeys[i] == key) { - return true; - } - } - return false; - } - - public Node canReach(int key) { - if (mChildren == null) { - return null; - } - for (Node child : mChildren) { - if (child.containsKey(key)) { - return child; - } - } - return null; - } - } - - private final View.OnKeyListener mKeyListener = new View.OnKeyListener() { - @Override - public boolean onKey(View v, int keyCode, KeyEvent event) { - if (event.getAction() == KeyEvent.ACTION_UP) { - return processKeyUp(keyCode); - } - return false; - } - }; - - private final View.OnFocusChangeListener mFocusListener = new View.OnFocusChangeListener() { - @Override - public void onFocusChange(View v, boolean hasFocus) { - if (!hasFocus && mInKbMode && isTypedTimeFullyLegal()) { - finishKbMode(); - - if (mOnTimeChangedListener != null) { - mOnTimeChangedListener.onTimeChanged(mDelegator, - mRadialTimePickerView.getCurrentHour(), - mRadialTimePickerView.getCurrentMinute()); - } - } - } - }; } diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java index dd165ae94ecb..be4cdc16e1d3 100644 --- a/core/java/android/widget/Toast.java +++ b/core/java/android/widget/Toast.java @@ -235,6 +235,14 @@ public class Toast { public int getYOffset() { return mTN.mY; } + + /** + * Gets the LayoutParams for the Toast window. + * @hide + */ + public WindowManager.LayoutParams getWindowParams() { + return mTN.mParams; + } /** * Make a standard toast that just contains a text view. diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java index 1ce19ce05066..d4d186c94e23 100644 --- a/core/java/android/widget/Toolbar.java +++ b/core/java/android/widget/Toolbar.java @@ -66,7 +66,9 @@ import java.util.List; * <li><em>A navigation button.</em> This may be an Up arrow, navigation menu toggle, close, * collapse, done or another glyph of the app's choosing. This button should always be used * to access other navigational destinations within the container of the Toolbar and - * its signified content or otherwise leave the current context signified by the Toolbar.</li> + * its signified content or otherwise leave the current context signified by the Toolbar. + * The navigation button is vertically aligned within the Toolbar's + * {@link android.R.styleable#View_minHeight minimum height}, if set.</li> * <li><em>A branded logo image.</em> This may extend to the height of the bar and can be * arbitrarily wide.</li> * <li><em>A title and subtitle.</em> The title should be a signpost for the Toolbar's current @@ -82,8 +84,9 @@ import java.util.List; * <li><em>An {@link ActionMenuView action menu}.</em> The menu of actions will pin to the * end of the Toolbar offering a few * <a href="http://developer.android.com/design/patterns/actionbar.html#ActionButtons"> - * frequent, important or typical</a> actions along with an optional overflow menu for - * additional actions.</li> + * frequent, important or typical</a> actions along with an optional overflow menu for + * additional actions. Action buttons are vertically aligned within the Toolbar's + * {@link android.R.styleable#View_minHeight minimum height}, if set.</li> * </ul> * </p> * @@ -101,6 +104,7 @@ public class Toolbar extends ViewGroup { private ImageView mLogoView; private Drawable mCollapseIcon; + private CharSequence mCollapseDescription; private ImageButton mCollapseButtonView; View mExpandedActionView; @@ -235,6 +239,7 @@ public class Toolbar extends ViewGroup { } mCollapseIcon = a.getDrawable(R.styleable.Toolbar_collapseIcon); + mCollapseDescription = a.getText(R.styleable.Toolbar_collapseContentDescription); final CharSequence title = a.getText(R.styleable.Toolbar_title); if (!TextUtils.isEmpty(title)) { @@ -995,6 +1000,7 @@ public class Toolbar extends ViewGroup { if (mCollapseButtonView == null) { mCollapseButtonView = new ImageButton(getContext(), null, 0, mNavButtonStyle); mCollapseButtonView.setImageDrawable(mCollapseIcon); + mCollapseButtonView.setContentDescription(mCollapseDescription); final LayoutParams lp = generateDefaultLayoutParams(); lp.gravity = Gravity.START | (mButtonGravity & Gravity.VERTICAL_GRAVITY_MASK); lp.mViewType = LayoutParams.EXPANDED; diff --git a/core/java/android/widget/YearPickerView.java b/core/java/android/widget/YearPickerView.java index 2bf07f93de11..24ed7cec0dde 100644 --- a/core/java/android/widget/YearPickerView.java +++ b/core/java/android/widget/YearPickerView.java @@ -18,7 +18,6 @@ package android.widget; import android.content.Context; import android.content.res.Resources; -import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; @@ -33,10 +32,15 @@ import com.android.internal.R; */ class YearPickerView extends ListView implements AdapterView.OnItemClickListener, OnDateChangedListener { + private final Calendar mMinDate = Calendar.getInstance(); + private final Calendar mMaxDate = Calendar.getInstance(); + + private final YearAdapter mAdapter; + private final int mViewSize; + private final int mChildSize; + private DatePickerController mController; - private YearAdapter mAdapter; - private int mViewSize; - private int mChildSize; + private int mSelectedPosition = -1; private int mYearSelectedCircleColor; @@ -72,15 +76,23 @@ class YearPickerView extends ListView implements AdapterView.OnItemClickListener setOnItemClickListener(this); setDividerHeight(0); + + mAdapter = new YearAdapter(getContext(), R.layout.year_label_text_view); + setAdapter(mAdapter); + } + + public void setRange(Calendar min, Calendar max) { + mMinDate.setTimeInMillis(min.getTimeInMillis()); + mMaxDate.setTimeInMillis(max.getTimeInMillis()); + + updateAdapterData(); } public void init(DatePickerController controller) { mController = controller; mController.registerOnDateChangedListener(this); - mAdapter = new YearAdapter(getContext(), R.layout.year_label_text_view); updateAdapterData(); - setAdapter(mAdapter); onDateChanged(); } @@ -98,8 +110,9 @@ class YearPickerView extends ListView implements AdapterView.OnItemClickListener private void updateAdapterData() { mAdapter.clear(); - final int maxYear = mController.getMaxYear(); - for (int year = mController.getMinYear(); year <= maxYear; year++) { + + final int maxYear = mMaxDate.get(Calendar.YEAR); + for (int year = mMinDate.get(Calendar.YEAR); year <= maxYear; year++) { mAdapter.add(year); } } @@ -173,12 +186,13 @@ class YearPickerView extends ListView implements AdapterView.OnItemClickListener updateAdapterData(); mAdapter.notifyDataSetChanged(); postSetSelectionCentered( - mController.getSelectedDay().get(Calendar.YEAR) - mController.getMinYear()); + mController.getSelectedDay().get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR)); } @Override public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); + if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) { event.setFromIndex(0); event.setToIndex(0); diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java index 0183e4511721..35e03c3b7a80 100644 --- a/core/java/com/android/internal/app/AlertController.java +++ b/core/java/com/android/internal/app/AlertController.java @@ -26,7 +26,6 @@ import android.content.DialogInterface; import android.content.res.TypedArray; import android.database.Cursor; import android.graphics.drawable.Drawable; -import android.os.Build; import android.os.Handler; import android.os.Message; import android.text.TextUtils; @@ -38,9 +37,12 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; +import android.view.ViewParent; +import android.view.ViewTreeObserver; import android.view.Window; import android.view.WindowInsets; import android.view.WindowManager; +import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; @@ -449,11 +451,11 @@ public class AlertController { } private void setupView() { - final LinearLayout contentPanel = (LinearLayout) mWindow.findViewById(R.id.contentPanel); + final ViewGroup contentPanel = (ViewGroup) mWindow.findViewById(R.id.contentPanel); setupContent(contentPanel); final boolean hasButtons = setupButtons(); - final LinearLayout topPanel = (LinearLayout) mWindow.findViewById(R.id.topPanel); + final ViewGroup topPanel = (ViewGroup) mWindow.findViewById(R.id.topPanel); final TypedArray a = mContext.obtainStyledAttributes( null, R.styleable.AlertDialog, R.attr.alertDialogStyle, 0); final boolean hasTitle = setupTitle(topPanel); @@ -521,13 +523,13 @@ public class AlertController { a.recycle(); } - private boolean setupTitle(LinearLayout topPanel) { + private boolean setupTitle(ViewGroup topPanel) { boolean hasTitle = true; if (mCustomTitleView != null) { // Add the custom title view directly to the topPanel layout - LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); + LayoutParams lp = new LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); topPanel.addView(mCustomTitleView, 0, lp); @@ -571,7 +573,7 @@ public class AlertController { return hasTitle; } - private void setupContent(LinearLayout contentPanel) { + private void setupContent(ViewGroup contentPanel) { mScrollView = (ScrollView) mWindow.findViewById(R.id.scrollView); mScrollView.setFocusable(false); @@ -588,14 +590,77 @@ public class AlertController { mScrollView.removeView(mMessageView); if (mListView != null) { - contentPanel.removeView(mWindow.findViewById(R.id.scrollView)); - contentPanel.addView(mListView, - new LinearLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)); - contentPanel.setLayoutParams(new LinearLayout.LayoutParams(MATCH_PARENT, 0, 1.0f)); + final ViewGroup scrollParent = (ViewGroup) mScrollView.getParent(); + final int childIndex = scrollParent.indexOfChild(mScrollView); + scrollParent.removeViewAt(childIndex); + scrollParent.addView(mListView, childIndex, + new LayoutParams(MATCH_PARENT, MATCH_PARENT)); } else { contentPanel.setVisibility(View.GONE); } } + + // Set up scroll indicators (if present). + final View indicatorUp = mWindow.findViewById(R.id.scrollIndicatorUp); + final View indicatorDown = mWindow.findViewById(R.id.scrollIndicatorDown); + if (indicatorUp != null || indicatorDown != null) { + if (mMessage != null) { + // We're just showing the ScrollView, set up listener. + mScrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() { + @Override + public void onScrollChange(View v, int scrollX, int scrollY, + int oldScrollX, int oldScrollY) { + manageScrollIndicators(v, indicatorUp, indicatorDown); + } + }); + // Set up the indicators following layout. + mScrollView.post(new Runnable() { + @Override + public void run() { + manageScrollIndicators(mScrollView, indicatorUp, indicatorDown); + } + }); + + } else if (mListView != null) { + // We're just showing the AbsListView, set up listener. + mListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + // That's cool, I guess? + } + + @Override + public void onScroll(AbsListView v, int firstVisibleItem, + int visibleItemCount, int totalItemCount) { + manageScrollIndicators(v, indicatorUp, indicatorDown); + } + }); + // Set up the indicators following layout. + mListView.post(new Runnable() { + @Override + public void run() { + manageScrollIndicators(mListView, indicatorUp, indicatorDown); + } + }); + } else { + // We don't have any content to scroll, remove the indicators. + if (indicatorUp != null) { + contentPanel.removeView(indicatorUp); + } + if (indicatorDown != null) { + contentPanel.removeView(indicatorDown); + } + } + } + } + + private static void manageScrollIndicators(View v, View upIndicator, View downIndicator) { + if (upIndicator != null) { + upIndicator.setVisibility(v.canScrollVertically(-1) ? View.VISIBLE : View.INVISIBLE); + } + if (downIndicator != null) { + downIndicator.setVisibility(v.canScrollVertically(1) ? View.VISIBLE : View.INVISIBLE); + } } private boolean setupButtons() { diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 526781175b6c..0bc1a8d4e5fd 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -16,13 +16,20 @@ package com.android.internal.app; +import android.app.Activity; +import android.content.ComponentName; import android.content.Intent; +import android.content.IntentSender; import android.os.Bundle; import android.os.Parcelable; import android.util.Log; +import android.util.Slog; public class ChooserActivity extends ResolverActivity { + private static final String TAG = "ChooserActivity"; + private Bundle mReplacementExtras; + private IntentSender mChosenComponentSender; @Override protected void onCreate(Bundle savedInstanceState) { @@ -60,11 +67,14 @@ public class ChooserActivity extends ResolverActivity { initialIntents[i] = in; } } + mChosenComponentSender = intent.getParcelableExtra( + Intent.EXTRA_CHOSEN_COMPONENT_INTENT_SENDER); setSafeForwardingMode(true); super.onCreate(savedInstanceState, target, title, defaultTitleRes, initialIntents, null, false); } + @Override public Intent getReplacementIntent(String packageName, Intent defIntent) { if (mReplacementExtras != null) { final Bundle replExtras = mReplacementExtras.getBundle(packageName); @@ -77,6 +87,22 @@ public class ChooserActivity extends ResolverActivity { return defIntent; } + @Override + public void onActivityStarted(Intent intent) { + if (mChosenComponentSender != null) { + final ComponentName target = intent.getComponent(); + if (target != null) { + final Intent fillIn = new Intent().putExtra(Intent.EXTRA_CHOSEN_COMPONENT, target); + try { + mChosenComponentSender.sendIntent(this, Activity.RESULT_OK, fillIn, null, null); + } catch (IntentSender.SendIntentException e) { + Slog.e(TAG, "Unable to launch supplied IntentSender to report " + + "the chosen component: " + e); + } + } + } + } + private void modifyTargetIntent(Intent in) { final String action = in.getAction(); if (Intent.ACTION_SEND.equals(action) || diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 0062e2d53746..7df76e533e74 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -74,6 +74,9 @@ import java.util.List; import java.util.Map; import java.util.Set; +import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; +import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; + /** * This activity is displayed when the system attempts to start an Intent for * which there is more than one matching activity, allowing the user to decide @@ -269,12 +272,15 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic mListView = (ListView) findViewById(R.id.resolver_list); mListView.setVisibility(View.GONE); } + // Prevent the Resolver window from becoming the top fullscreen window and thus from taking + // control of the system bars. + getWindow().clearFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR); final ResolverDrawerLayout rdl = (ResolverDrawerLayout) findViewById(R.id.contentPanel); if (rdl != null) { - rdl.setOnClickOutsideListener(new View.OnClickListener() { + rdl.setOnDismissedListener(new ResolverDrawerLayout.OnDismissedListener() { @Override - public void onClick(View v) { + public void onDismissed() { finish(); } }); @@ -638,10 +644,12 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic public void safelyStartActivity(Intent intent) { if (!mSafeForwardingMode) { startActivity(intent); + onActivityStarted(intent); return; } try { startActivityAsCaller(intent, null, UserHandle.USER_NULL); + onActivityStarted(intent); } catch (RuntimeException e) { String launchedFromPackage; try { @@ -656,6 +664,10 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic } } + public void onActivityStarted(Intent intent) { + // Do nothing + } + void showAppDetails(ResolveInfo ri) { Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) .setData(Uri.fromParts("package", ri.activityInfo.packageName, null)) @@ -819,6 +831,11 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic } ResolveInfo ri = new ResolveInfo(); ri.activityInfo = ai; + UserManager userManager = + (UserManager) getSystemService(Context.USER_SERVICE); + if (userManager.isManagedProfile()) { + ri.noResourceId = true; + } if (ii instanceof LabeledIntent) { LabeledIntent li = (LabeledIntent)ii; ri.resolvePackageName = li.getSourcePackage(); diff --git a/core/java/com/android/internal/app/ToolbarActionBar.java b/core/java/com/android/internal/app/ToolbarActionBar.java index 4410f2544624..34b9dcb9366f 100644 --- a/core/java/com/android/internal/app/ToolbarActionBar.java +++ b/core/java/com/android/internal/app/ToolbarActionBar.java @@ -40,7 +40,6 @@ import com.android.internal.widget.ToolbarWidgetWrapper; import java.util.ArrayList; public class ToolbarActionBar extends ActionBar { - private Toolbar mToolbar; private DecorToolbar mDecorToolbar; private boolean mToolbarMenuPrepared; private Window.Callback mWindowCallback; @@ -66,7 +65,6 @@ public class ToolbarActionBar extends ActionBar { }; public ToolbarActionBar(Toolbar toolbar, CharSequence title, Window.Callback windowCallback) { - mToolbar = toolbar; mDecorToolbar = new ToolbarWidgetWrapper(toolbar, false); mWindowCallback = new ToolbarCallbackWrapper(windowCallback); mDecorToolbar.setWindowCallback(mWindowCallback); @@ -91,8 +89,8 @@ public class ToolbarActionBar extends ActionBar { @Override public void setCustomView(int resId) { - final LayoutInflater inflater = LayoutInflater.from(mToolbar.getContext()); - setCustomView(inflater.inflate(resId, mToolbar, false)); + final LayoutInflater inflater = LayoutInflater.from(mDecorToolbar.getContext()); + setCustomView(inflater.inflate(resId, mDecorToolbar.getViewGroup(), false)); } @Override @@ -132,17 +130,17 @@ public class ToolbarActionBar extends ActionBar { @Override public void setElevation(float elevation) { - mToolbar.setElevation(elevation); + mDecorToolbar.getViewGroup().setElevation(elevation); } @Override public float getElevation() { - return mToolbar.getElevation(); + return mDecorToolbar.getViewGroup().getElevation(); } @Override public Context getThemedContext() { - return mToolbar.getContext(); + return mDecorToolbar.getContext(); } @Override @@ -152,12 +150,12 @@ public class ToolbarActionBar extends ActionBar { @Override public void setHomeAsUpIndicator(Drawable indicator) { - mToolbar.setNavigationIcon(indicator); + mDecorToolbar.setNavigationIcon(indicator); } @Override public void setHomeAsUpIndicator(int resId) { - mToolbar.setNavigationIcon(resId); + mDecorToolbar.setNavigationIcon(resId); } @Override @@ -280,7 +278,7 @@ public class ToolbarActionBar extends ActionBar { @Override public void setBackgroundDrawable(@Nullable Drawable d) { - mToolbar.setBackground(d); + mDecorToolbar.setBackgroundDrawable(d); } @Override @@ -290,12 +288,12 @@ public class ToolbarActionBar extends ActionBar { @Override public CharSequence getTitle() { - return mToolbar.getTitle(); + return mDecorToolbar.getTitle(); } @Override public CharSequence getSubtitle() { - return mToolbar.getSubtitle(); + return mDecorToolbar.getSubtitle(); } @Override @@ -389,44 +387,44 @@ public class ToolbarActionBar extends ActionBar { @Override public int getHeight() { - return mToolbar.getHeight(); + return mDecorToolbar.getHeight(); } @Override public void show() { // TODO: Consider a better transition for this. // Right now use no automatic transition so that the app can supply one if desired. - mToolbar.setVisibility(View.VISIBLE); + mDecorToolbar.setVisibility(View.VISIBLE); } @Override public void hide() { // TODO: Consider a better transition for this. // Right now use no automatic transition so that the app can supply one if desired. - mToolbar.setVisibility(View.GONE); + mDecorToolbar.setVisibility(View.GONE); } @Override public boolean isShowing() { - return mToolbar.getVisibility() == View.VISIBLE; + return mDecorToolbar.getVisibility() == View.VISIBLE; } @Override public boolean openOptionsMenu() { - return mToolbar.showOverflowMenu(); + return mDecorToolbar.showOverflowMenu(); } @Override public boolean invalidateOptionsMenu() { - mToolbar.removeCallbacks(mMenuInvalidator); - mToolbar.postOnAnimation(mMenuInvalidator); + mDecorToolbar.getViewGroup().removeCallbacks(mMenuInvalidator); + mDecorToolbar.getViewGroup().postOnAnimation(mMenuInvalidator); return true; } @Override public boolean collapseActionView() { - if (mToolbar.hasExpandedActionView()) { - mToolbar.collapseActionView(); + if (mDecorToolbar.hasExpandedActionView()) { + mDecorToolbar.collapseActionView(); return true; } return false; @@ -434,10 +432,10 @@ public class ToolbarActionBar extends ActionBar { void populateOptionsMenu() { if (!mMenuCallbackSet) { - mToolbar.setMenuCallbacks(new ActionMenuPresenterCallback(), new MenuBuilderCallback()); + mDecorToolbar.setMenuCallbacks(new ActionMenuPresenterCallback(), new MenuBuilderCallback()); mMenuCallbackSet = true; } - final Menu menu = mToolbar.getMenu(); + final Menu menu = mDecorToolbar.getMenu(); final MenuBuilder mb = menu instanceof MenuBuilder ? (MenuBuilder) menu : null; if (mb != null) { mb.stopDispatchingItemsChanged(); @@ -518,7 +516,7 @@ public class ToolbarActionBar extends ActionBar { } mClosingActionMenu = true; - mToolbar.dismissPopupMenus(); + mDecorToolbar.dismissPopupMenus(); if (mWindowCallback != null) { mWindowCallback.onPanelClosed(Window.FEATURE_ACTION_BAR, menu); } @@ -536,7 +534,7 @@ public class ToolbarActionBar extends ActionBar { @Override public void onMenuModeChange(MenuBuilder menu) { if (mWindowCallback != null) { - if (mToolbar.isOverflowMenuShowing()) { + if (mDecorToolbar.isOverflowMenuShowing()) { mWindowCallback.onPanelClosed(Window.FEATURE_ACTION_BAR, menu); } else if (mWindowCallback.onPreparePanel(Window.FEATURE_OPTIONS_PANEL, null, menu)) { diff --git a/core/java/com/android/internal/app/WindowDecorActionBar.java b/core/java/com/android/internal/app/WindowDecorActionBar.java index 2377c22b488d..d95f0e591e0e 100644 --- a/core/java/com/android/internal/app/WindowDecorActionBar.java +++ b/core/java/com/android/internal/app/WindowDecorActionBar.java @@ -496,7 +496,7 @@ public class WindowDecorActionBar extends ActionBar implements mOverlayLayout.setHideOnContentScrollEnabled(false); mContextView.killMode(); - ActionModeImpl mode = new ActionModeImpl(callback); + ActionModeImpl mode = new ActionModeImpl(mContextView.getContext(), callback); if (mode.dispatchOnCreate()) { mode.invalidate(); mContextView.initForMode(mode); @@ -876,7 +876,7 @@ public class WindowDecorActionBar extends ActionBar implements currentTheme.resolveAttribute(com.android.internal.R.attr.actionBarWidgetTheme, outValue, true); final int targetThemeRes = outValue.resourceId; - + if (targetThemeRes != 0 && mContext.getThemeResId() != targetThemeRes) { mThemedContext = new ContextThemeWrapper(mContext, targetThemeRes); } else { @@ -885,7 +885,7 @@ public class WindowDecorActionBar extends ActionBar implements } return mThemedContext; } - + @Override public boolean isTitleTruncated() { return mDecorToolbar != null && mDecorToolbar.isTitleTruncated(); @@ -933,23 +933,26 @@ public class WindowDecorActionBar extends ActionBar implements } /** - * @hide + * @hide */ public class ActionModeImpl extends ActionMode implements MenuBuilder.Callback { + private final Context mActionModeContext; + private final MenuBuilder mMenu; + private ActionMode.Callback mCallback; - private MenuBuilder mMenu; private WeakReference<View> mCustomView; - - public ActionModeImpl(ActionMode.Callback callback) { + + public ActionModeImpl(Context context, ActionMode.Callback callback) { + mActionModeContext = context; mCallback = callback; - mMenu = new MenuBuilder(getThemedContext()) + mMenu = new MenuBuilder(context) .setDefaultShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); mMenu.setCallback(this); } @Override public MenuInflater getMenuInflater() { - return new MenuInflater(getThemedContext()); + return new MenuInflater(mActionModeContext); } @Override @@ -1042,7 +1045,7 @@ public class WindowDecorActionBar extends ActionBar implements public CharSequence getSubtitle() { return mContextView.getSubtitle(); } - + @Override public void setTitleOptionalHint(boolean titleOptional) { super.setTitleOptionalHint(titleOptional); diff --git a/core/java/com/android/internal/http/multipart/FilePart.java b/core/java/com/android/internal/http/multipart/FilePart.java index bfcda0074f0f..45e4be68dd16 100644 --- a/core/java/com/android/internal/http/multipart/FilePart.java +++ b/core/java/com/android/internal/http/multipart/FilePart.java @@ -51,9 +51,14 @@ import org.apache.commons.logging.LogFactory; * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a> * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a> * - * @since 2.0 + * @since 2.0 * + * @deprecated Please use {@link java.net.URLConnection} and friends instead. + * The Apache HTTP client is no longer maintained and may be removed in a future + * release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a> + * for further details. */ +@Deprecated public class FilePart extends PartBase { /** Default content encoding of file attachments. */ diff --git a/core/java/com/android/internal/http/multipart/MultipartEntity.java b/core/java/com/android/internal/http/multipart/MultipartEntity.java index 2c5e7f64e33e..531925174453 100644 --- a/core/java/com/android/internal/http/multipart/MultipartEntity.java +++ b/core/java/com/android/internal/http/multipart/MultipartEntity.java @@ -80,7 +80,13 @@ import org.apache.commons.logging.LogFactory; * </pre> * * @since 3.0 + * + * @deprecated Please use {@link java.net.URLConnection} and friends instead. + * The Apache HTTP client is no longer maintained and may be removed in a future + * release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a> + * for further details. */ +@Deprecated public class MultipartEntity extends AbstractHttpEntity { private static final Log log = LogFactory.getLog(MultipartEntity.class); diff --git a/core/java/com/android/internal/http/multipart/Part.java b/core/java/com/android/internal/http/multipart/Part.java index cb1b5465389f..1d66dc674331 100644 --- a/core/java/com/android/internal/http/multipart/Part.java +++ b/core/java/com/android/internal/http/multipart/Part.java @@ -48,7 +48,13 @@ import org.apache.commons.logging.LogFactory; * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a> * * @since 2.0 + * + * @deprecated Please use {@link java.net.URLConnection} and friends instead. + * The Apache HTTP client is no longer maintained and may be removed in a future + * release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a> + * for further details. */ +@Deprecated public abstract class Part { /** Log object for this class. */ diff --git a/core/java/com/android/internal/http/multipart/StringPart.java b/core/java/com/android/internal/http/multipart/StringPart.java index c98257e27041..73d0f908ac2a 100644 --- a/core/java/com/android/internal/http/multipart/StringPart.java +++ b/core/java/com/android/internal/http/multipart/StringPart.java @@ -46,7 +46,13 @@ import org.apache.commons.logging.LogFactory; * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a> * * @since 2.0 + * + * @deprecated Please use {@link java.net.URLConnection} and friends instead. + * The Apache HTTP client is no longer maintained and may be removed in a future + * release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a> + * for further details. */ +@Deprecated public class StringPart extends PartBase { /** Log object for this class. */ diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index 8794d319e179..e6bcea1eb4ab 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -43,6 +43,7 @@ interface IStatusBarService void onPanelRevealed(); void onPanelHidden(); void onNotificationClick(String key); + void onNotificationActionClick(String key, int actionIndex); void onNotificationError(String pkg, String tag, int id, int uid, int initialPid, String message, int userId); void onClearAllNotifications(int userId); diff --git a/core/java/com/android/internal/util/MemInfoReader.java b/core/java/com/android/internal/util/MemInfoReader.java index 5f240f73b5be..b71fa0674b4e 100644 --- a/core/java/com/android/internal/util/MemInfoReader.java +++ b/core/java/com/android/internal/util/MemInfoReader.java @@ -34,40 +34,65 @@ public final class MemInfoReader { } } + /** + * Total amount of RAM available to the kernel. + */ public long getTotalSize() { return mInfos[Debug.MEMINFO_TOTAL] * 1024; } + /** + * Amount of RAM that is not being used for anything. + */ public long getFreeSize() { return mInfos[Debug.MEMINFO_FREE] * 1024; } + /** + * Amount of RAM that the kernel is being used for caches, not counting caches + * that are mapped in to processes. + */ public long getCachedSize() { - return mInfos[Debug.MEMINFO_CACHED] * 1024; + return getCachedSizeKb() * 1024; } + /** + * Amount of RAM that is in use by the kernel for actual allocations. + */ + public long getKernelUsedSize() { + return getKernelUsedSizeKb() * 1024; + } + + /** + * Total amount of RAM available to the kernel. + */ public long getTotalSizeKb() { return mInfos[Debug.MEMINFO_TOTAL]; } + /** + * Amount of RAM that is not being used for anything. + */ public long getFreeSizeKb() { return mInfos[Debug.MEMINFO_FREE]; } + /** + * Amount of RAM that the kernel is being used for caches, not counting caches + * that are mapped in to processes. + */ public long getCachedSizeKb() { - return mInfos[Debug.MEMINFO_CACHED]; - } - - public long getBuffersSizeKb() { - return mInfos[Debug.MEMINFO_BUFFERS]; + return mInfos[Debug.MEMINFO_BUFFERS] + + mInfos[Debug.MEMINFO_CACHED] - mInfos[Debug.MEMINFO_MAPPED]; } - public long getShmemSizeKb() { - return mInfos[Debug.MEMINFO_SHMEM]; - } - - public long getSlabSizeKb() { - return mInfos[Debug.MEMINFO_SLAB]; + /** + * Amount of RAM that is in use by the kernel for actual allocations. + */ + public long getKernelUsedSizeKb() { + return mInfos[Debug.MEMINFO_SHMEM] + mInfos[Debug.MEMINFO_SLAB] + + mInfos[Debug.MEMINFO_VM_ALLOC_USED] + mInfos[Debug.MEMINFO_PAGE_TABLES] + + mInfos[Debug.MEMINFO_KERNEL_STACK]; } public long getSwapTotalSizeKb() { @@ -81,4 +106,8 @@ public final class MemInfoReader { public long getZramTotalSizeKb() { return mInfos[Debug.MEMINFO_ZRAM_TOTAL]; } + + public long[] getRawInfo() { + return mInfos; + } } diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java index 50a7a5e17be1..993ab58c6e44 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -102,4 +102,8 @@ public class BaseIWindow extends IWindow.Stub { @Override public void doneAnimating() { } + + @Override + public void dispatchWindowShown() { + } } diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java index 40f58e96eef4..99bb1ac9c6ca 100644 --- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java +++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java @@ -54,6 +54,7 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On private final boolean mOverflowOnly; private final int mPopupMaxWidth; private final int mPopupStyleAttr; + private final int mPopupStyleRes; private View mAnchorView; private ListPopupWindow mPopup; @@ -73,21 +74,27 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On private int mDropDownGravity = Gravity.NO_GRAVITY; public MenuPopupHelper(Context context, MenuBuilder menu) { - this(context, menu, null, false, com.android.internal.R.attr.popupMenuStyle); + this(context, menu, null, false, com.android.internal.R.attr.popupMenuStyle, 0); } public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView) { - this(context, menu, anchorView, false, com.android.internal.R.attr.popupMenuStyle); + this(context, menu, anchorView, false, com.android.internal.R.attr.popupMenuStyle, 0); } public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView, boolean overflowOnly, int popupStyleAttr) { + this(context, menu, anchorView, overflowOnly, popupStyleAttr, 0); + } + + public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView, + boolean overflowOnly, int popupStyleAttr, int popupStyleRes) { mContext = context; mInflater = LayoutInflater.from(context); mMenu = menu; mAdapter = new MenuAdapter(mMenu); mOverflowOnly = overflowOnly; mPopupStyleAttr = popupStyleAttr; + mPopupStyleRes = popupStyleRes; final Resources res = context.getResources(); mPopupMaxWidth = Math.max(res.getDisplayMetrics().widthPixels / 2, @@ -122,7 +129,7 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On } public boolean tryShow() { - mPopup = new ListPopupWindow(mContext, null, mPopupStyleAttr); + mPopup = new ListPopupWindow(mContext, null, mPopupStyleAttr, mPopupStyleRes); mPopup.setOnDismissListener(this); mPopup.setOnItemClickListener(this); mPopup.setAdapter(mAdapter); diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java index 062a9b1c39b3..7c671e8923ee 100644 --- a/core/java/com/android/internal/widget/ActionBarContextView.java +++ b/core/java/com/android/internal/widget/ActionBarContextView.java @@ -241,7 +241,7 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi if (!mSplitActionBar) { menu.addMenuPresenter(mActionMenuPresenter, mPopupContext); mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); - mMenuView.setBackgroundDrawable(null); + mMenuView.setBackground(null); addView(mMenuView, layoutParams); } else { // Allow full screen width in split mode. diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java index 91e53307d997..654d08b40763 100644 --- a/core/java/com/android/internal/widget/ActionBarView.java +++ b/core/java/com/android/internal/widget/ActionBarView.java @@ -19,8 +19,6 @@ package com.android.internal.widget; import android.animation.LayoutTransition; import android.app.ActionBar; import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; @@ -29,9 +27,7 @@ import android.os.Parcelable; import android.text.Layout; import android.text.TextUtils; import android.util.AttributeSet; -import android.util.TypedValue; import android.view.CollapsibleActionView; -import android.view.ContextThemeWrapper; import android.view.Gravity; import android.view.LayoutInflater; import android.view.Menu; @@ -111,10 +107,10 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar { private int mProgressBarPadding; private int mItemPadding; - private int mTitleStyleRes; - private int mSubtitleStyleRes; - private int mProgressStyle; - private int mIndeterminateProgressStyle; + private final int mTitleStyleRes; + private final int mSubtitleStyleRes; + private final int mProgressStyle; + private final int mIndeterminateProgressStyle; private boolean mUserTitle; private boolean mIncludeTabs; @@ -1345,6 +1341,22 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar { updateHomeAccessibility(mUpGoerFive.isEnabled()); } + @Override + public void setMenuCallbacks(MenuPresenter.Callback presenterCallback, + MenuBuilder.Callback menuBuilderCallback) { + if (mActionMenuPresenter != null) { + mActionMenuPresenter.setCallback(presenterCallback); + } + if (mOptionsMenu != null) { + mOptionsMenu.setCallback(menuBuilderCallback); + } + } + + @Override + public Menu getMenu() { + return mOptionsMenu; + } + static class SavedState extends BaseSavedState { int expandedMenuItemId; boolean isOverflowOpen; diff --git a/core/java/com/android/internal/widget/DecorToolbar.java b/core/java/com/android/internal/widget/DecorToolbar.java index f89f0b7d6ef7..fb413b573d2e 100644 --- a/core/java/com/android/internal/widget/DecorToolbar.java +++ b/core/java/com/android/internal/widget/DecorToolbar.java @@ -27,6 +27,8 @@ import android.view.ViewGroup; import android.view.Window; import android.widget.AdapterView; import android.widget.SpinnerAdapter; + +import com.android.internal.view.menu.MenuBuilder; import com.android.internal.view.menu.MenuPresenter; /** @@ -93,4 +95,11 @@ public interface DecorToolbar { void setDefaultNavigationIcon(Drawable icon); void saveHierarchyState(SparseArray<Parcelable> toolbarStates); void restoreHierarchyState(SparseArray<Parcelable> toolbarStates); + void setBackgroundDrawable(Drawable d); + int getHeight(); + void setVisibility(int visible); + int getVisibility(); + void setMenuCallbacks(MenuPresenter.Callback presenterCallback, + MenuBuilder.Callback menuBuilderCallback); + Menu getMenu(); } diff --git a/core/java/com/android/internal/widget/ExploreByTouchHelper.java b/core/java/com/android/internal/widget/ExploreByTouchHelper.java index 11c4ca1f65dd..0e046cb21609 100644 --- a/core/java/com/android/internal/widget/ExploreByTouchHelper.java +++ b/core/java/com/android/internal/widget/ExploreByTouchHelper.java @@ -19,6 +19,7 @@ package com.android.internal.widget; import android.content.Context; import android.graphics.Rect; import android.os.Bundle; +import android.util.IntArray; import android.view.accessibility.*; import android.view.MotionEvent; import android.view.View; @@ -26,11 +27,9 @@ import android.view.ViewParent; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.view.accessibility.AccessibilityNodeProvider; -import java.util.LinkedList; -import java.util.List; - /** * ExploreByTouchHelper is a utility class for implementing accessibility * support in custom {@link android.view.View}s that represent a collection of View-like @@ -54,14 +53,20 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate { /** Default class name used for virtual views. */ private static final String DEFAULT_CLASS_NAME = View.class.getName(); - // Temporary, reusable data structures. - private final Rect mTempScreenRect = new Rect(); - private final Rect mTempParentRect = new Rect(); - private final Rect mTempVisibleRect = new Rect(); - private final int[] mTempGlobalRect = new int[2]; + /** Default bounds used to determine if the client didn't set any. */ + private static final Rect INVALID_PARENT_BOUNDS = new Rect( + Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE); + + // Lazily-created temporary data structures used when creating nodes. + private Rect mTempScreenRect; + private Rect mTempParentRect; + private int[] mTempGlobalRect; + + /** Lazily-created temporary data structure used to compute visibility. */ + private Rect mTempVisibleRect; - /** View's context **/ - private Context mContext; + /** Lazily-created temporary data structure used to obtain child IDs. */ + private IntArray mTempArray; /** System accessibility manager, used to check state and send events. */ private final AccessibilityManager mManager; @@ -69,6 +74,9 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate { /** View whose internal structure is exposed through this helper. */ private final View mView; + /** Context of the host view. **/ + private final Context mContext; + /** Node provider that handles creating nodes and performing actions. */ private ExploreByTouchNodeProvider mNodeProvider; @@ -328,11 +336,17 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate { onInitializeAccessibilityNodeInfo(mView, node); // Add the virtual descendants. - final LinkedList<Integer> virtualViewIds = new LinkedList<Integer>(); + if (mTempArray == null) { + mTempArray = new IntArray(); + } else { + mTempArray.clear(); + } + final IntArray virtualViewIds = mTempArray; getVisibleVirtualViews(virtualViewIds); - for (Integer childVirtualViewId : virtualViewIds) { - node.addChild(mView, childVirtualViewId); + final int N = virtualViewIds.size(); + for (int i = 0; i < N; i++) { + node.addChild(mView, virtualViewIds.get(i)); } return node; @@ -367,11 +381,17 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate { * @return An {@link AccessibilityNodeInfo} for the specified item. */ private AccessibilityNodeInfo createNodeForChild(int virtualViewId) { + ensureTempRects(); + final Rect tempParentRect = mTempParentRect; + final int[] tempGlobalRect = mTempGlobalRect; + final Rect tempScreenRect = mTempScreenRect; + final AccessibilityNodeInfo node = AccessibilityNodeInfo.obtain(); // Ensure the client has good defaults. node.setEnabled(true); node.setClassName(DEFAULT_CLASS_NAME); + node.setBoundsInParent(INVALID_PARENT_BOUNDS); // Allow the client to populate the node. onPopulateNodeForVirtualView(virtualViewId, node); @@ -382,8 +402,8 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate { + "populateNodeForVirtualViewId()"); } - node.getBoundsInParent(mTempParentRect); - if (mTempParentRect.isEmpty()) { + node.getBoundsInParent(tempParentRect); + if (tempParentRect.equals(INVALID_PARENT_BOUNDS)) { throw new RuntimeException("Callbacks must set parent bounds in " + "populateNodeForVirtualViewId()"); } @@ -406,29 +426,35 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate { // Manage internal accessibility focus state. if (mFocusedVirtualViewId == virtualViewId) { node.setAccessibilityFocused(true); - node.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); + node.addAction(AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS); } else { node.setAccessibilityFocused(false); - node.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); + node.addAction(AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS); } // Set the visibility based on the parent bound. - if (intersectVisibleToUser(mTempParentRect)) { + if (intersectVisibleToUser(tempParentRect)) { node.setVisibleToUser(true); - node.setBoundsInParent(mTempParentRect); + node.setBoundsInParent(tempParentRect); } // Calculate screen-relative bound. - mView.getLocationOnScreen(mTempGlobalRect); - final int offsetX = mTempGlobalRect[0]; - final int offsetY = mTempGlobalRect[1]; - mTempScreenRect.set(mTempParentRect); - mTempScreenRect.offset(offsetX, offsetY); - node.setBoundsInScreen(mTempScreenRect); + mView.getLocationOnScreen(tempGlobalRect); + final int offsetX = tempGlobalRect[0]; + final int offsetY = tempGlobalRect[1]; + tempScreenRect.set(tempParentRect); + tempScreenRect.offset(offsetX, offsetY); + node.setBoundsInScreen(tempScreenRect); return node; } + private void ensureTempRects() { + mTempGlobalRect = new int[2]; + mTempParentRect = new Rect(); + mTempScreenRect = new Rect(); + } + private boolean performAction(int virtualViewId, int action, Bundle arguments) { switch (virtualViewId) { case View.NO_ID: @@ -446,13 +472,13 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate { switch (action) { case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: - return manageFocusForChild(virtualViewId, action, arguments); + return manageFocusForChild(virtualViewId, action); default: return onPerformActionForVirtualView(virtualViewId, action, arguments); } } - private boolean manageFocusForChild(int virtualViewId, int action, Bundle arguments) { + private boolean manageFocusForChild(int virtualViewId, int action) { switch (action) { case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: return requestAccessibilityFocus(virtualViewId); @@ -498,12 +524,16 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate { } // If no portion of the parent is visible, this view is not visible. - if (!mView.getLocalVisibleRect(mTempVisibleRect)) { + if (mTempVisibleRect == null) { + mTempVisibleRect = new Rect(); + } + final Rect tempVisibleRect = mTempVisibleRect; + if (!mView.getLocalVisibleRect(tempVisibleRect)) { return false; } // Check if the view intersects the visible portion of the parent. - return localRect.intersect(mTempVisibleRect); + return localRect.intersect(tempVisibleRect); } /** @@ -583,7 +613,7 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate { * * @param virtualViewIds The list to populate with visible items */ - protected abstract void getVisibleVirtualViews(List<Integer> virtualViewIds); + protected abstract void getVisibleVirtualViews(IntArray virtualViewIds); /** * Populates an {@link AccessibilityEvent} with information about the diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java index 375822fa184a..25b494528a98 100644 --- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java +++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java @@ -63,18 +63,22 @@ public class ResolverDrawerLayout extends ViewGroup { private float mCollapseOffset; private int mCollapsibleHeight; + private int mUncollapsibleHeight; private int mTopOffset; private boolean mIsDragging; private boolean mOpenOnClick; private boolean mOpenOnLayout; + private boolean mDismissOnScrollerFinished; private final int mTouchSlop; private final float mMinFlingVelocity; private final OverScroller mScroller; private final VelocityTracker mVelocityTracker; - private OnClickListener mClickOutsideListener; + private OnDismissedListener mOnDismissedListener; + private RunOnDismissedListener mRunOnDismissedListener; + private float mInitialTouchX; private float mInitialTouchY; private float mLastTouchY; @@ -143,8 +147,8 @@ public class ResolverDrawerLayout extends ViewGroup { return isSmallCollapsed() ? mMaxCollapsedHeightSmall : mMaxCollapsedHeight; } - public void setOnClickOutsideListener(OnClickListener listener) { - mClickOutsideListener = listener; + public void setOnDismissedListener(OnDismissedListener listener) { + mOnDismissedListener = listener; } @Override @@ -194,7 +198,7 @@ public class ResolverDrawerLayout extends ViewGroup { } if (mIsDragging) { - mScroller.abortAnimation(); + abortAnimation(); } return mIsDragging || mOpenOnClick; } @@ -213,12 +217,9 @@ public class ResolverDrawerLayout extends ViewGroup { mInitialTouchX = x; mInitialTouchY = mLastTouchY = y; mActivePointerId = ev.getPointerId(0); - if (findChildUnder(mInitialTouchX, mInitialTouchY) == null && - mClickOutsideListener != null) { - mIsDragging = handled = true; - } - handled |= mCollapsibleHeight > 0; - mScroller.abortAnimation(); + mIsDragging = findChildUnder(mInitialTouchX, mInitialTouchY) != null; + handled = (!mIsDragging && mOnDismissedListener != null) || mCollapsibleHeight > 0; + abortAnimation(); } break; @@ -264,11 +265,12 @@ public class ResolverDrawerLayout extends ViewGroup { break; case MotionEvent.ACTION_UP: { + final boolean wasDragging = mIsDragging; mIsDragging = false; - if (!mIsDragging && findChildUnder(mInitialTouchX, mInitialTouchY) == null && + if (!wasDragging && findChildUnder(mInitialTouchX, mInitialTouchY) == null && findChildUnder(ev.getX(), ev.getY()) == null) { - if (mClickOutsideListener != null) { - mClickOutsideListener.onClick(this); + if (mOnDismissedListener != null) { + dispatchOnDismissed(); resetTouch(); return true; } @@ -281,7 +283,13 @@ public class ResolverDrawerLayout extends ViewGroup { mVelocityTracker.computeCurrentVelocity(1000); final float yvel = mVelocityTracker.getYVelocity(mActivePointerId); if (Math.abs(yvel) > mMinFlingVelocity) { - smoothScrollTo(yvel < 0 ? 0 : mCollapsibleHeight, yvel); + if (mOnDismissedListener != null + && yvel > 0 && mCollapseOffset > mCollapsibleHeight) { + smoothScrollTo(mCollapsibleHeight + mUncollapsibleHeight, yvel); + mDismissOnScrollerFinished = true; + } else { + smoothScrollTo(yvel < 0 ? 0 : mCollapsibleHeight, yvel); + } } else { smoothScrollTo( mCollapseOffset < mCollapsibleHeight / 2 ? 0 : mCollapsibleHeight, 0); @@ -327,17 +335,27 @@ public class ResolverDrawerLayout extends ViewGroup { @Override public void computeScroll() { super.computeScroll(); - if (!mScroller.isFinished()) { - final boolean keepGoing = mScroller.computeScrollOffset(); + if (mScroller.computeScrollOffset()) { + final boolean keepGoing = !mScroller.isFinished(); performDrag(mScroller.getCurrY() - mCollapseOffset); if (keepGoing) { postInvalidateOnAnimation(); + } else if (mDismissOnScrollerFinished && mOnDismissedListener != null) { + mRunOnDismissedListener = new RunOnDismissedListener(); + post(mRunOnDismissedListener); } } } + private void abortAnimation() { + mScroller.abortAnimation(); + mRunOnDismissedListener = null; + mDismissOnScrollerFinished = false; + } + private float performDrag(float dy) { - final float newPos = Math.max(0, Math.min(mCollapseOffset + dy, mCollapsibleHeight)); + final float newPos = Math.max(0, Math.min(mCollapseOffset + dy, + mCollapsibleHeight + mUncollapsibleHeight)); if (newPos != mCollapseOffset) { dy = newPos - mCollapseOffset; final int childCount = getChildCount(); @@ -356,11 +374,18 @@ public class ResolverDrawerLayout extends ViewGroup { return 0; } - private void smoothScrollTo(int yOffset, float velocity) { - if (getMaxCollapsedHeight() == 0) { - return; + void dispatchOnDismissed() { + if (mOnDismissedListener != null) { + mOnDismissedListener.onDismissed(); } - mScroller.abortAnimation(); + if (mRunOnDismissedListener != null) { + removeCallbacks(mRunOnDismissedListener); + mRunOnDismissedListener = null; + } + } + + private void smoothScrollTo(int yOffset, float velocity) { + abortAnimation(); final int sy = (int) mCollapseOffset; int dy = yOffset - sy; if (dy == 0) { @@ -490,6 +515,7 @@ public class ResolverDrawerLayout extends ViewGroup { protected void onDetachedFromWindow() { super.onDetachedFromWindow(); getViewTreeObserver().removeOnTouchModeChangeListener(mTouchModeChangeListener); + abortAnimation(); } @Override @@ -585,6 +611,7 @@ public class ResolverDrawerLayout extends ViewGroup { mCollapsibleHeight = Math.max(0, heightUsed - alwaysShowHeight - getMaxCollapsedHeight()); + mUncollapsibleHeight = heightUsed - mCollapsibleHeight; if (isLaidOut()) { mCollapseOffset = Math.min(mCollapseOffset, mCollapsibleHeight); @@ -734,4 +761,15 @@ public class ResolverDrawerLayout extends ViewGroup { } }; } + + public interface OnDismissedListener { + public void onDismissed(); + } + + private class RunOnDismissedListener implements Runnable { + @Override + public void run() { + dispatchOnDismissed(); + } + } } diff --git a/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java b/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java index 324a6c998683..054ca30c71f4 100644 --- a/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java +++ b/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java @@ -657,4 +657,36 @@ public class ToolbarWidgetWrapper implements DecorToolbar { mToolbar.restoreHierarchyState(toolbarStates); } + @Override + public void setBackgroundDrawable(Drawable d) { + //noinspection deprecation + mToolbar.setBackgroundDrawable(d); + } + + @Override + public int getHeight() { + return mToolbar.getHeight(); + } + + @Override + public void setVisibility(int visible) { + mToolbar.setVisibility(visible); + } + + @Override + public int getVisibility() { + return mToolbar.getVisibility(); + } + + @Override + public void setMenuCallbacks(MenuPresenter.Callback presenterCallback, + MenuBuilder.Callback menuBuilderCallback) { + mToolbar.setMenuCallbacks(presenterCallback, menuBuilderCallback); + } + + @Override + public Menu getMenu() { + return mToolbar.getMenu(); + } + } diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 1f4105fdca98..4d178779e32d 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -856,7 +856,7 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) parseRuntimeOption("dalvik.vm.profiler.type", profileType, "-Xprofile-type:"); // Depth of bounded stack data - parseRuntimeOption("dalvik.vm.profile.max-stack-depth", + parseRuntimeOption("dalvik.vm.profile.stack-depth", profileMaxStackDepth, "-Xprofile-max-stack-depth:"); @@ -929,8 +929,8 @@ jstring AndroidRuntime::NewStringLatin1(JNIEnv* env, const char* bytes) { */ void AndroidRuntime::start(const char* className, const Vector<String8>& options) { - ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n", - className != NULL ? className : "(unknown)"); + ALOGD(">>>>>> START %s uid %d <<<<<<\n", + className != NULL ? className : "(unknown)", getuid()); static const String8 startSystemServer("start-system-server"); diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp index 8ea28eca476b..a578b5db7d91 100644 --- a/core/jni/android/graphics/BitmapFactory.cpp +++ b/core/jni/android/graphics/BitmapFactory.cpp @@ -315,7 +315,8 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding } SkBitmap decodingBitmap; - if (!decoder->decode(stream, &decodingBitmap, prefColorType, decodeMode)) { + if (decoder->decode(stream, &decodingBitmap, prefColorType, decodeMode) + != SkImageDecoder::kSuccess) { return nullObjectReturn("decoder->decode returned false"); } @@ -478,7 +479,7 @@ static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fi NPE_CHECK_RETURN_ZERO(env, fileDescriptor); - jint descriptor = jniGetFDFromFileDescriptor(env, fileDescriptor); + int descriptor = jniGetFDFromFileDescriptor(env, fileDescriptor); struct stat fdStat; if (fstat(descriptor, &fdStat) == -1) { @@ -486,16 +487,27 @@ static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fi return nullObjectReturn("fstat return -1"); } - // Restore the descriptor's offset on exiting this function. + // Restore the descriptor's offset on exiting this function. Even though + // we dup the descriptor, both the original and dup refer to the same open + // file description and changes to the file offset in one impact the other. AutoFDSeek autoRestore(descriptor); - FILE* file = fdopen(descriptor, "r"); + // Duplicate the descriptor here to prevent leaking memory. A leak occurs + // if we only close the file descriptor and not the file object it is used to + // create. If we don't explicitly clean up the file (which in turn closes the + // descriptor) the buffers allocated internally by fseek will be leaked. + int dupDescriptor = dup(descriptor); + + FILE* file = fdopen(dupDescriptor, "r"); if (file == NULL) { + // cleanup the duplicated descriptor since it will not be closed when the + // file is cleaned up (fclose). + close(dupDescriptor); return nullObjectReturn("Could not open file"); } SkAutoTUnref<SkFILEStream> fileStream(new SkFILEStream(file, - SkFILEStream::kCallerRetains_Ownership)); + SkFILEStream::kCallerPasses_Ownership)); // Use a buffered stream. Although an SkFILEStream can be rewound, this // ensures that SkImageDecoder::Factory never rewinds beyond the diff --git a/core/jni/android/graphics/Matrix.cpp b/core/jni/android/graphics/Matrix.cpp index cbd20e90105a..01ab6992a944 100644 --- a/core/jni/android/graphics/Matrix.cpp +++ b/core/jni/android/graphics/Matrix.cpp @@ -308,46 +308,47 @@ public: static JNINativeMethod methods[] = { {"finalizer", "(J)V", (void*) SkMatrixGlue::finalizer}, {"native_create","(J)J", (void*) SkMatrixGlue::create}, - {"native_isIdentity","(J)Z", (void*) SkMatrixGlue::isIdentity}, - {"native_isAffine","(J)Z", (void*) SkMatrixGlue::isAffine}, - {"native_rectStaysRect","(J)Z", (void*) SkMatrixGlue::rectStaysRect}, - {"native_reset","(J)V", (void*) SkMatrixGlue::reset}, - {"native_set","(JJ)V", (void*) SkMatrixGlue::set}, - {"native_setTranslate","(JFF)V", (void*) SkMatrixGlue::setTranslate}, - {"native_setScale","(JFFFF)V", (void*) SkMatrixGlue::setScale__FFFF}, - {"native_setScale","(JFF)V", (void*) SkMatrixGlue::setScale__FF}, - {"native_setRotate","(JFFF)V", (void*) SkMatrixGlue::setRotate__FFF}, - {"native_setRotate","(JF)V", (void*) SkMatrixGlue::setRotate__F}, - {"native_setSinCos","(JFFFF)V", (void*) SkMatrixGlue::setSinCos__FFFF}, - {"native_setSinCos","(JFF)V", (void*) SkMatrixGlue::setSinCos__FF}, - {"native_setSkew","(JFFFF)V", (void*) SkMatrixGlue::setSkew__FFFF}, - {"native_setSkew","(JFF)V", (void*) SkMatrixGlue::setSkew__FF}, - {"native_setConcat","(JJJ)V", (void*) SkMatrixGlue::setConcat}, - {"native_preTranslate","(JFF)V", (void*) SkMatrixGlue::preTranslate}, - {"native_preScale","(JFFFF)V", (void*) SkMatrixGlue::preScale__FFFF}, - {"native_preScale","(JFF)V", (void*) SkMatrixGlue::preScale__FF}, - {"native_preRotate","(JFFF)V", (void*) SkMatrixGlue::preRotate__FFF}, - {"native_preRotate","(JF)V", (void*) SkMatrixGlue::preRotate__F}, - {"native_preSkew","(JFFFF)V", (void*) SkMatrixGlue::preSkew__FFFF}, - {"native_preSkew","(JFF)V", (void*) SkMatrixGlue::preSkew__FF}, - {"native_preConcat","(JJ)V", (void*) SkMatrixGlue::preConcat}, - {"native_postTranslate","(JFF)V", (void*) SkMatrixGlue::postTranslate}, - {"native_postScale","(JFFFF)V", (void*) SkMatrixGlue::postScale__FFFF}, - {"native_postScale","(JFF)V", (void*) SkMatrixGlue::postScale__FF}, - {"native_postRotate","(JFFF)V", (void*) SkMatrixGlue::postRotate__FFF}, - {"native_postRotate","(JF)V", (void*) SkMatrixGlue::postRotate__F}, - {"native_postSkew","(JFFFF)V", (void*) SkMatrixGlue::postSkew__FFFF}, - {"native_postSkew","(JFF)V", (void*) SkMatrixGlue::postSkew__FF}, - {"native_postConcat","(JJ)V", (void*) SkMatrixGlue::postConcat}, - {"native_setRectToRect","(JLandroid/graphics/RectF;Landroid/graphics/RectF;I)Z", (void*) SkMatrixGlue::setRectToRect}, - {"native_setPolyToPoly","(J[FI[FII)Z", (void*) SkMatrixGlue::setPolyToPoly}, - {"native_invert","(JJ)Z", (void*) SkMatrixGlue::invert}, - {"native_mapPoints","(J[FI[FIIZ)V", (void*) SkMatrixGlue::mapPoints}, - {"native_mapRect","(JLandroid/graphics/RectF;Landroid/graphics/RectF;)Z", (void*) SkMatrixGlue::mapRect__RectFRectF}, - {"native_mapRadius","(JF)F", (void*) SkMatrixGlue::mapRadius}, - {"native_getValues","(J[F)V", (void*) SkMatrixGlue::getValues}, - {"native_setValues","(J[F)V", (void*) SkMatrixGlue::setValues}, - {"native_equals", "(JJ)Z", (void*) SkMatrixGlue::equals} + + {"native_isIdentity","!(J)Z", (void*) SkMatrixGlue::isIdentity}, + {"native_isAffine","!(J)Z", (void*) SkMatrixGlue::isAffine}, + {"native_rectStaysRect","!(J)Z", (void*) SkMatrixGlue::rectStaysRect}, + {"native_reset","!(J)V", (void*) SkMatrixGlue::reset}, + {"native_set","!(JJ)V", (void*) SkMatrixGlue::set}, + {"native_setTranslate","!(JFF)V", (void*) SkMatrixGlue::setTranslate}, + {"native_setScale","!(JFFFF)V", (void*) SkMatrixGlue::setScale__FFFF}, + {"native_setScale","!(JFF)V", (void*) SkMatrixGlue::setScale__FF}, + {"native_setRotate","!(JFFF)V", (void*) SkMatrixGlue::setRotate__FFF}, + {"native_setRotate","!(JF)V", (void*) SkMatrixGlue::setRotate__F}, + {"native_setSinCos","!(JFFFF)V", (void*) SkMatrixGlue::setSinCos__FFFF}, + {"native_setSinCos","!(JFF)V", (void*) SkMatrixGlue::setSinCos__FF}, + {"native_setSkew","!(JFFFF)V", (void*) SkMatrixGlue::setSkew__FFFF}, + {"native_setSkew","!(JFF)V", (void*) SkMatrixGlue::setSkew__FF}, + {"native_setConcat","!(JJJ)V", (void*) SkMatrixGlue::setConcat}, + {"native_preTranslate","!(JFF)V", (void*) SkMatrixGlue::preTranslate}, + {"native_preScale","!(JFFFF)V", (void*) SkMatrixGlue::preScale__FFFF}, + {"native_preScale","!(JFF)V", (void*) SkMatrixGlue::preScale__FF}, + {"native_preRotate","!(JFFF)V", (void*) SkMatrixGlue::preRotate__FFF}, + {"native_preRotate","!(JF)V", (void*) SkMatrixGlue::preRotate__F}, + {"native_preSkew","!(JFFFF)V", (void*) SkMatrixGlue::preSkew__FFFF}, + {"native_preSkew","!(JFF)V", (void*) SkMatrixGlue::preSkew__FF}, + {"native_preConcat","!(JJ)V", (void*) SkMatrixGlue::preConcat}, + {"native_postTranslate","!(JFF)V", (void*) SkMatrixGlue::postTranslate}, + {"native_postScale","!(JFFFF)V", (void*) SkMatrixGlue::postScale__FFFF}, + {"native_postScale","!(JFF)V", (void*) SkMatrixGlue::postScale__FF}, + {"native_postRotate","!(JFFF)V", (void*) SkMatrixGlue::postRotate__FFF}, + {"native_postRotate","!(JF)V", (void*) SkMatrixGlue::postRotate__F}, + {"native_postSkew","!(JFFFF)V", (void*) SkMatrixGlue::postSkew__FFFF}, + {"native_postSkew","!(JFF)V", (void*) SkMatrixGlue::postSkew__FF}, + {"native_postConcat","!(JJ)V", (void*) SkMatrixGlue::postConcat}, + {"native_setRectToRect","!(JLandroid/graphics/RectF;Landroid/graphics/RectF;I)Z", (void*) SkMatrixGlue::setRectToRect}, + {"native_setPolyToPoly","!(J[FI[FII)Z", (void*) SkMatrixGlue::setPolyToPoly}, + {"native_invert","!(JJ)Z", (void*) SkMatrixGlue::invert}, + {"native_mapPoints","!(J[FI[FIIZ)V", (void*) SkMatrixGlue::mapPoints}, + {"native_mapRect","!(JLandroid/graphics/RectF;Landroid/graphics/RectF;)Z", (void*) SkMatrixGlue::mapRect__RectFRectF}, + {"native_mapRadius","!(JF)F", (void*) SkMatrixGlue::mapRadius}, + {"native_getValues","!(J[F)V", (void*) SkMatrixGlue::getValues}, + {"native_setValues","!(J[F)V", (void*) SkMatrixGlue::setValues}, + {"native_equals", "!(JJ)Z", (void*) SkMatrixGlue::equals} }; static jfieldID sNativeInstanceField; diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp index 4bb31fcd169c..6b02326b6fba 100644 --- a/core/jni/android/graphics/Paint.cpp +++ b/core/jni/android/graphics/Paint.cpp @@ -939,58 +939,60 @@ static JNINativeMethod methods[] = { {"finalizer", "(J)V", (void*) PaintGlue::finalizer}, {"native_init","()J", (void*) PaintGlue::init}, {"native_initWithPaint","(J)J", (void*) PaintGlue::initWithPaint}, - {"native_reset","(J)V", (void*) PaintGlue::reset}, - {"native_set","(JJ)V", (void*) PaintGlue::assign}, - {"getFlags","()I", (void*) PaintGlue::getFlags}, - {"setFlags","(I)V", (void*) PaintGlue::setFlags}, - {"getHinting","()I", (void*) PaintGlue::getHinting}, - {"setHinting","(I)V", (void*) PaintGlue::setHinting}, - {"setAntiAlias","(Z)V", (void*) PaintGlue::setAntiAlias}, - {"setSubpixelText","(Z)V", (void*) PaintGlue::setSubpixelText}, - {"setLinearText","(Z)V", (void*) PaintGlue::setLinearText}, - {"setUnderlineText","(Z)V", (void*) PaintGlue::setUnderlineText}, - {"setStrikeThruText","(Z)V", (void*) PaintGlue::setStrikeThruText}, - {"setFakeBoldText","(Z)V", (void*) PaintGlue::setFakeBoldText}, - {"setFilterBitmap","(Z)V", (void*) PaintGlue::setFilterBitmap}, - {"setDither","(Z)V", (void*) PaintGlue::setDither}, - {"native_getStyle","(J)I", (void*) PaintGlue::getStyle}, - {"native_setStyle","(JI)V", (void*) PaintGlue::setStyle}, - {"getColor","()I", (void*) PaintGlue::getColor}, - {"setColor","(I)V", (void*) PaintGlue::setColor}, - {"getAlpha","()I", (void*) PaintGlue::getAlpha}, - {"setAlpha","(I)V", (void*) PaintGlue::setAlpha}, - {"getStrokeWidth","()F", (void*) PaintGlue::getStrokeWidth}, - {"setStrokeWidth","(F)V", (void*) PaintGlue::setStrokeWidth}, - {"getStrokeMiter","()F", (void*) PaintGlue::getStrokeMiter}, - {"setStrokeMiter","(F)V", (void*) PaintGlue::setStrokeMiter}, - {"native_getStrokeCap","(J)I", (void*) PaintGlue::getStrokeCap}, - {"native_setStrokeCap","(JI)V", (void*) PaintGlue::setStrokeCap}, - {"native_getStrokeJoin","(J)I", (void*) PaintGlue::getStrokeJoin}, - {"native_setStrokeJoin","(JI)V", (void*) PaintGlue::setStrokeJoin}, - {"native_getFillPath","(JJJ)Z", (void*) PaintGlue::getFillPath}, - {"native_setShader","(JJ)J", (void*) PaintGlue::setShader}, - {"native_setColorFilter","(JJ)J", (void*) PaintGlue::setColorFilter}, - {"native_setXfermode","(JJ)J", (void*) PaintGlue::setXfermode}, - {"native_setPathEffect","(JJ)J", (void*) PaintGlue::setPathEffect}, - {"native_setMaskFilter","(JJ)J", (void*) PaintGlue::setMaskFilter}, - {"native_setTypeface","(JJ)J", (void*) PaintGlue::setTypeface}, - {"native_setRasterizer","(JJ)J", (void*) PaintGlue::setRasterizer}, - {"native_getTextAlign","(J)I", (void*) PaintGlue::getTextAlign}, - {"native_setTextAlign","(JI)V", (void*) PaintGlue::setTextAlign}, - {"native_setTextLocale","(JLjava/lang/String;)V", (void*) PaintGlue::setTextLocale}, - {"isElegantTextHeight","()Z", (void*) PaintGlue::isElegantTextHeight}, - {"setElegantTextHeight","(Z)V", (void*) PaintGlue::setElegantTextHeight}, - {"getTextSize","()F", (void*) PaintGlue::getTextSize}, - {"setTextSize","(F)V", (void*) PaintGlue::setTextSize}, - {"getTextScaleX","()F", (void*) PaintGlue::getTextScaleX}, - {"setTextScaleX","(F)V", (void*) PaintGlue::setTextScaleX}, - {"getTextSkewX","()F", (void*) PaintGlue::getTextSkewX}, - {"setTextSkewX","(F)V", (void*) PaintGlue::setTextSkewX}, - {"native_getLetterSpacing","(J)F", (void*) PaintGlue::getLetterSpacing}, - {"native_setLetterSpacing","(JF)V", (void*) PaintGlue::setLetterSpacing}, + + {"native_reset","!(J)V", (void*) PaintGlue::reset}, + {"native_set","!(JJ)V", (void*) PaintGlue::assign}, + {"getFlags","!()I", (void*) PaintGlue::getFlags}, + {"setFlags","!(I)V", (void*) PaintGlue::setFlags}, + {"getHinting","!()I", (void*) PaintGlue::getHinting}, + {"setHinting","!(I)V", (void*) PaintGlue::setHinting}, + {"setAntiAlias","!(Z)V", (void*) PaintGlue::setAntiAlias}, + {"setSubpixelText","!(Z)V", (void*) PaintGlue::setSubpixelText}, + {"setLinearText","!(Z)V", (void*) PaintGlue::setLinearText}, + {"setUnderlineText","!(Z)V", (void*) PaintGlue::setUnderlineText}, + {"setStrikeThruText","!(Z)V", (void*) PaintGlue::setStrikeThruText}, + {"setFakeBoldText","!(Z)V", (void*) PaintGlue::setFakeBoldText}, + {"setFilterBitmap","!(Z)V", (void*) PaintGlue::setFilterBitmap}, + {"setDither","!(Z)V", (void*) PaintGlue::setDither}, + {"native_getStyle","!(J)I", (void*) PaintGlue::getStyle}, + {"native_setStyle","!(JI)V", (void*) PaintGlue::setStyle}, + {"getColor","!()I", (void*) PaintGlue::getColor}, + {"setColor","!(I)V", (void*) PaintGlue::setColor}, + {"getAlpha","!()I", (void*) PaintGlue::getAlpha}, + {"setAlpha","!(I)V", (void*) PaintGlue::setAlpha}, + {"getStrokeWidth","!()F", (void*) PaintGlue::getStrokeWidth}, + {"setStrokeWidth","!(F)V", (void*) PaintGlue::setStrokeWidth}, + {"getStrokeMiter","!()F", (void*) PaintGlue::getStrokeMiter}, + {"setStrokeMiter","!(F)V", (void*) PaintGlue::setStrokeMiter}, + {"native_getStrokeCap","!(J)I", (void*) PaintGlue::getStrokeCap}, + {"native_setStrokeCap","!(JI)V", (void*) PaintGlue::setStrokeCap}, + {"native_getStrokeJoin","!(J)I", (void*) PaintGlue::getStrokeJoin}, + {"native_setStrokeJoin","!(JI)V", (void*) PaintGlue::setStrokeJoin}, + {"native_getFillPath","!(JJJ)Z", (void*) PaintGlue::getFillPath}, + {"native_setShader","!(JJ)J", (void*) PaintGlue::setShader}, + {"native_setColorFilter","!(JJ)J", (void*) PaintGlue::setColorFilter}, + {"native_setXfermode","!(JJ)J", (void*) PaintGlue::setXfermode}, + {"native_setPathEffect","!(JJ)J", (void*) PaintGlue::setPathEffect}, + {"native_setMaskFilter","!(JJ)J", (void*) PaintGlue::setMaskFilter}, + {"native_setTypeface","!(JJ)J", (void*) PaintGlue::setTypeface}, + {"native_setRasterizer","!(JJ)J", (void*) PaintGlue::setRasterizer}, + {"native_getTextAlign","!(J)I", (void*) PaintGlue::getTextAlign}, + {"native_setTextAlign","!(JI)V", (void*) PaintGlue::setTextAlign}, + {"native_setTextLocale","!(JLjava/lang/String;)V", (void*) PaintGlue::setTextLocale}, + {"isElegantTextHeight","!()Z", (void*) PaintGlue::isElegantTextHeight}, + {"setElegantTextHeight","!(Z)V", (void*) PaintGlue::setElegantTextHeight}, + {"getTextSize","!()F", (void*) PaintGlue::getTextSize}, + {"setTextSize","!(F)V", (void*) PaintGlue::setTextSize}, + {"getTextScaleX","!()F", (void*) PaintGlue::getTextScaleX}, + {"setTextScaleX","!(F)V", (void*) PaintGlue::setTextScaleX}, + {"getTextSkewX","!()F", (void*) PaintGlue::getTextSkewX}, + {"setTextSkewX","!(F)V", (void*) PaintGlue::setTextSkewX}, + {"native_getLetterSpacing","!(J)F", (void*) PaintGlue::getLetterSpacing}, + {"native_setLetterSpacing","!(JF)V", (void*) PaintGlue::setLetterSpacing}, {"native_setFontFeatureSettings","(JLjava/lang/String;)V", (void*) PaintGlue::setFontFeatureSettings}, - {"ascent","()F", (void*) PaintGlue::ascent}, - {"descent","()F", (void*) PaintGlue::descent}, + {"ascent","!()F", (void*) PaintGlue::ascent}, + {"descent","!()F", (void*) PaintGlue::descent}, + {"getFontMetrics", "(Landroid/graphics/Paint$FontMetrics;)F", (void*)PaintGlue::getFontMetrics}, {"getFontMetricsInt", "(Landroid/graphics/Paint$FontMetricsInt;)I", (void*)PaintGlue::getFontMetricsInt}, {"native_measureText","([CIII)F", (void*) PaintGlue::measureText_CIII}, @@ -1014,8 +1016,9 @@ static JNINativeMethod methods[] = { (void*) PaintGlue::getStringBounds }, {"nativeGetCharArrayBounds", "(JJ[CIIILandroid/graphics/Rect;)V", (void*) PaintGlue::getCharArrayBounds }, - {"native_setShadowLayer", "(JFFFI)V", (void*)PaintGlue::setShadowLayer}, - {"native_hasShadowLayer", "(J)Z", (void*)PaintGlue::hasShadowLayer} + + {"native_setShadowLayer", "!(JFFFI)V", (void*)PaintGlue::setShadowLayer}, + {"native_hasShadowLayer", "!(J)Z", (void*)PaintGlue::hasShadowLayer} }; static jfieldID req_fieldID(jfieldID id) { diff --git a/core/jni/android/graphics/pdf/PdfEditor.cpp b/core/jni/android/graphics/pdf/PdfEditor.cpp index 5f60c9e3bfc8..ed6f1d69fc18 100644 --- a/core/jni/android/graphics/pdf/PdfEditor.cpp +++ b/core/jni/android/graphics/pdf/PdfEditor.cpp @@ -19,6 +19,9 @@ #include "fpdfview.h" #include "fpdfedit.h" #include "fpdfsave.h" +#include "fsdk_rendercontext.h" +#include "fpdf_transformpage.h" +#include "SkMatrix.h" #include <android_runtime/AndroidRuntime.h> #include <vector> @@ -29,6 +32,20 @@ namespace android { +enum PageBox {PAGE_BOX_MEDIA, PAGE_BOX_CROP}; + +static struct { + jfieldID x; + jfieldID y; +} gPointClassInfo; + +static struct { + jfieldID left; + jfieldID top; + jfieldID right; + jfieldID bottom; +} gRectClassInfo; + static Mutex sLock; static int sUnmatchedInitRequestCount = 0; @@ -72,8 +89,17 @@ static jlong nativeOpen(JNIEnv* env, jclass thiz, jint fd, jlong size) { if (!document) { const long error = FPDF_GetLastError(); - jniThrowException(env, "java/io/IOException", - "cannot create document. Error:" + error); + switch (error) { + case FPDF_ERR_PASSWORD: + case FPDF_ERR_SECURITY: { + jniThrowException(env, "java/lang/SecurityException", + "cannot create document. Error:" + error); + } break; + default: { + jniThrowException(env, "java/io/IOException", + "cannot create document. Error:" + error); + } break; + } destroyLibraryIfNeeded(); return -1; } @@ -144,18 +170,201 @@ static void nativeWrite(JNIEnv* env, jclass thiz, jlong documentPtr, jint fd) { } } +static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, + jlong transformPtr, jint clipLeft, jint clipTop, jint clipRight, jint clipBottom) { + FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); + + CPDF_Page* page = (CPDF_Page*) FPDF_LoadPage(document, pageIndex); + if (!page) { + jniThrowException(env, "java/lang/IllegalStateException", + "cannot open page"); + return; + } + + double width = 0; + double height = 0; + + const int result = FPDF_GetPageSizeByIndex(document, pageIndex, &width, &height); + if (!result) { + jniThrowException(env, "java/lang/IllegalStateException", + "cannot get page size"); + return; + } + + CFX_AffineMatrix matrix; + + SkMatrix* skTransform = reinterpret_cast<SkMatrix*>(transformPtr); + + SkScalar transformValues[6]; + skTransform->asAffine(transformValues); + + // PDF's coordinate system origin is left-bottom while in graphics it + // is the top-left. So, translate the PDF coordinates to ours. + matrix.Set(1, 0, 0, -1, 0, page->GetPageHeight()); + + // Apply the transformation what was created in our coordinates. + matrix.Concat(transformValues[SkMatrix::kAScaleX], transformValues[SkMatrix::kASkewY], + transformValues[SkMatrix::kASkewX], transformValues[SkMatrix::kAScaleY], + transformValues[SkMatrix::kATransX], transformValues[SkMatrix::kATransY]); + + // Translate the result back to PDF coordinates. + matrix.Concat(1, 0, 0, -1, 0, page->GetPageHeight()); + + FS_MATRIX transform = {matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f}; + FS_RECTF clip = {(float) clipLeft, (float) clipTop, (float) clipRight, (float) clipBottom}; + + FPDFPage_TransFormWithClip(page, &transform, &clip); + + FPDF_ClosePage(page); +} + +static void nativeGetPageSize(JNIEnv* env, jclass thiz, jlong documentPtr, + jint pageIndex, jobject outSize) { + FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); + + FPDF_PAGE page = FPDF_LoadPage(document, pageIndex); + if (!page) { + jniThrowException(env, "java/lang/IllegalStateException", + "cannot open page"); + return; + } + + double width = 0; + double height = 0; + + const int result = FPDF_GetPageSizeByIndex(document, pageIndex, &width, &height); + if (!result) { + jniThrowException(env, "java/lang/IllegalStateException", + "cannot get page size"); + return; + } + + env->SetIntField(outSize, gPointClassInfo.x, width); + env->SetIntField(outSize, gPointClassInfo.y, height); + + FPDF_ClosePage(page); +} + +static jboolean nativeScaleForPrinting(JNIEnv* env, jclass thiz, jlong documentPtr) { + FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); + FPDF_BOOL success = FPDF_VIEWERREF_GetPrintScaling(document); + return success ? JNI_TRUE : JNI_FALSE; +} + +static bool nativeGetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, + PageBox pageBox, jobject outBox) { + FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); + + FPDF_PAGE page = FPDF_LoadPage(document, pageIndex); + if (!page) { + jniThrowException(env, "java/lang/IllegalStateException", + "cannot open page"); + return false; + } + + float left; + float top; + float right; + float bottom; + + const FPDF_BOOL success = (pageBox == PAGE_BOX_MEDIA) + ? FPDFPage_GetMediaBox(page, &left, &top, &right, &bottom) + : FPDFPage_GetCropBox(page, &left, &top, &right, &bottom); + + FPDF_ClosePage(page); + + if (!success) { + return false; + } + + env->SetIntField(outBox, gRectClassInfo.left, (int) left); + env->SetIntField(outBox, gRectClassInfo.top, (int) top); + env->SetIntField(outBox, gRectClassInfo.right, (int) right); + env->SetIntField(outBox, gRectClassInfo.bottom, (int) bottom); + + return true; +} + +static jboolean nativeGetPageMediaBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, + jobject outMediaBox) { + const bool success = nativeGetPageBox(env, thiz, documentPtr, pageIndex, PAGE_BOX_MEDIA, + outMediaBox); + return success ? JNI_TRUE : JNI_FALSE; +} + +static jboolean nativeGetPageCropBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, + jobject outMediaBox) { + const bool success = nativeGetPageBox(env, thiz, documentPtr, pageIndex, PAGE_BOX_CROP, + outMediaBox); + return success ? JNI_TRUE : JNI_FALSE; +} + +static void nativeSetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, + PageBox pageBox, jobject box) { + FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); + + FPDF_PAGE page = FPDF_LoadPage(document, pageIndex); + if (!page) { + jniThrowException(env, "java/lang/IllegalStateException", + "cannot open page"); + return; + } + + const int left = env->GetIntField(box, gRectClassInfo.left); + const int top = env->GetIntField(box, gRectClassInfo.top); + const int right = env->GetIntField(box, gRectClassInfo.right); + const int bottom = env->GetIntField(box, gRectClassInfo.bottom); + + if (pageBox == PAGE_BOX_MEDIA) { + FPDFPage_SetMediaBox(page, left, top, right, bottom); + } else { + FPDFPage_SetCropBox(page, left, top, right, bottom); + } + + FPDF_ClosePage(page); +} + +static void nativeSetPageMediaBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, + jobject mediaBox) { + nativeSetPageBox(env, thiz, documentPtr, pageIndex, PAGE_BOX_MEDIA, mediaBox); +} + +static void nativeSetPageCropBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, + jobject mediaBox) { + nativeSetPageBox(env, thiz, documentPtr, pageIndex, PAGE_BOX_CROP, mediaBox); +} + static JNINativeMethod gPdfEditor_Methods[] = { {"nativeOpen", "(IJ)J", (void*) nativeOpen}, {"nativeClose", "(J)V", (void*) nativeClose}, {"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount}, {"nativeRemovePage", "(JI)I", (void*) nativeRemovePage}, - {"nativeWrite", "(JI)V", (void*) nativeWrite} + {"nativeWrite", "(JI)V", (void*) nativeWrite}, + {"nativeSetTransformAndClip", "(JIJIIII)V", (void*) nativeSetTransformAndClip}, + {"nativeGetPageSize", "(JILandroid/graphics/Point;)V", (void*) nativeGetPageSize}, + {"nativeScaleForPrinting", "(J)Z", (void*) nativeScaleForPrinting}, + {"nativeGetPageMediaBox", "(JILandroid/graphics/Rect;)Z", (void*) nativeGetPageMediaBox}, + {"nativeSetPageMediaBox", "(JILandroid/graphics/Rect;)V", (void*) nativeSetPageMediaBox}, + {"nativeGetPageCropBox", "(JILandroid/graphics/Rect;)Z", (void*) nativeGetPageCropBox}, + {"nativeSetPageCropBox", "(JILandroid/graphics/Rect;)V", (void*) nativeSetPageCropBox} }; int register_android_graphics_pdf_PdfEditor(JNIEnv* env) { - return android::AndroidRuntime::registerNativeMethods( + const int result = android::AndroidRuntime::registerNativeMethods( env, "android/graphics/pdf/PdfEditor", gPdfEditor_Methods, NELEM(gPdfEditor_Methods)); + + jclass pointClass = env->FindClass("android/graphics/Point"); + gPointClassInfo.x = env->GetFieldID(pointClass, "x", "I"); + gPointClassInfo.y = env->GetFieldID(pointClass, "y", "I"); + + jclass rectClass = env->FindClass("android/graphics/Rect"); + gRectClassInfo.left = env->GetFieldID(rectClass, "left", "I"); + gRectClassInfo.top = env->GetFieldID(rectClass, "top", "I"); + gRectClassInfo.right = env->GetFieldID(rectClass, "right", "I"); + gRectClassInfo.bottom = env->GetFieldID(rectClass, "bottom", "I"); + + return result; }; }; diff --git a/core/jni/android/graphics/pdf/PdfRenderer.cpp b/core/jni/android/graphics/pdf/PdfRenderer.cpp index 303ddea9d1ab..357d3c00ae84 100644 --- a/core/jni/android/graphics/pdf/PdfRenderer.cpp +++ b/core/jni/android/graphics/pdf/PdfRenderer.cpp @@ -82,8 +82,17 @@ static jlong nativeCreate(JNIEnv* env, jclass thiz, jint fd, jlong size) { if (!document) { const long error = FPDF_GetLastError(); - jniThrowException(env, "java/io/IOException", - "cannot create document. Error:" + error); + switch (error) { + case FPDF_ERR_PASSWORD: + case FPDF_ERR_SECURITY: { + jniThrowException(env, "java/lang/SecurityException", + "cannot create document. Error:" + error); + } break; + default: { + jniThrowException(env, "java/io/IOException", + "cannot create document. Error:" + error); + } break; + } destroyLibraryIfNeeded(); return -1; } diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index f8bab242c23e..4cff56d10c49 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -48,13 +48,20 @@ struct fields_t { jfieldID canDisableShutterSound; jfieldID face_rect; jfieldID face_score; + jfieldID face_id; + jfieldID face_left_eye; + jfieldID face_right_eye; + jfieldID face_mouth; jfieldID rect_left; jfieldID rect_top; jfieldID rect_right; jfieldID rect_bottom; + jfieldID point_x; + jfieldID point_y; jmethodID post_event; jmethodID rect_constructor; jmethodID face_constructor; + jmethodID point_constructor; }; static fields_t fields; @@ -88,6 +95,7 @@ private: sp<Camera> mCamera; // strong reference to native object jclass mFaceClass; // strong reference to Face class jclass mRectClass; // strong reference to Rect class + jclass mPointClass; // strong reference to Point class Mutex mLock; /* @@ -144,6 +152,9 @@ JNICameraContext::JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, jclass rectClazz = env->FindClass("android/graphics/Rect"); mRectClass = (jclass) env->NewGlobalRef(rectClazz); + jclass pointClazz = env->FindClass("android/graphics/Point"); + mPointClass = (jclass) env->NewGlobalRef(pointClazz); + mManualBufferMode = false; mManualCameraCallbackSet = false; } @@ -170,6 +181,10 @@ void JNICameraContext::release() env->DeleteGlobalRef(mRectClass); mRectClass = NULL; } + if (mPointClass != NULL) { + env->DeleteGlobalRef(mPointClass); + mPointClass = NULL; + } clearCallbackBuffers_l(env); mCamera.clear(); } @@ -356,6 +371,33 @@ void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_m env->SetObjectField(face, fields.face_rect, rect); env->SetIntField(face, fields.face_score, metadata->faces[i].score); + bool optionalFields = metadata->faces[i].id != 0 + && metadata->faces[i].left_eye[0] != -2000 && metadata->faces[i].left_eye[1] != -2000 + && metadata->faces[i].right_eye[0] != -2000 && metadata->faces[i].right_eye[1] != -2000 + && metadata->faces[i].mouth[0] != -2000 && metadata->faces[i].mouth[1] != -2000; + if (optionalFields) { + int32_t id = metadata->faces[i].id; + env->SetIntField(face, fields.face_id, id); + + jobject leftEye = env->NewObject(mPointClass, fields.point_constructor); + env->SetIntField(leftEye, fields.point_x, metadata->faces[i].left_eye[0]); + env->SetIntField(leftEye, fields.point_y, metadata->faces[i].left_eye[1]); + env->SetObjectField(face, fields.face_left_eye, leftEye); + env->DeleteLocalRef(leftEye); + + jobject rightEye = env->NewObject(mPointClass, fields.point_constructor); + env->SetIntField(rightEye, fields.point_x, metadata->faces[i].right_eye[0]); + env->SetIntField(rightEye, fields.point_y, metadata->faces[i].right_eye[1]); + env->SetObjectField(face, fields.face_right_eye, rightEye); + env->DeleteLocalRef(rightEye); + + jobject mouth = env->NewObject(mPointClass, fields.point_constructor); + env->SetIntField(mouth, fields.point_x, metadata->faces[i].mouth[0]); + env->SetIntField(mouth, fields.point_y, metadata->faces[i].mouth[1]); + env->SetObjectField(face, fields.face_mouth, mouth); + env->DeleteLocalRef(mouth); + } + env->DeleteLocalRef(face); env->DeleteLocalRef(rect); } @@ -1020,11 +1062,17 @@ int register_android_hardware_Camera(JNIEnv *env) { "android/hardware/Camera$CameraInfo", "canDisableShutterSound", "Z", &fields.canDisableShutterSound }, { "android/hardware/Camera$Face", "rect", "Landroid/graphics/Rect;", &fields.face_rect }, + { "android/hardware/Camera$Face", "leftEye", "Landroid/graphics/Point;", &fields.face_left_eye}, + { "android/hardware/Camera$Face", "rightEye", "Landroid/graphics/Point;", &fields.face_right_eye}, + { "android/hardware/Camera$Face", "mouth", "Landroid/graphics/Point;", &fields.face_mouth}, { "android/hardware/Camera$Face", "score", "I", &fields.face_score }, + { "android/hardware/Camera$Face", "id", "I", &fields.face_id}, { "android/graphics/Rect", "left", "I", &fields.rect_left }, { "android/graphics/Rect", "top", "I", &fields.rect_top }, { "android/graphics/Rect", "right", "I", &fields.rect_right }, { "android/graphics/Rect", "bottom", "I", &fields.rect_bottom }, + { "android/graphics/Point", "x", "I", &fields.point_x}, + { "android/graphics/Point", "y", "I", &fields.point_y}, }; if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0) @@ -1052,6 +1100,13 @@ int register_android_hardware_Camera(JNIEnv *env) return -1; } + clazz = env->FindClass("android/graphics/Point"); + fields.point_constructor = env->GetMethodID(clazz, "<init>", "()V"); + if (fields.point_constructor == NULL) { + ALOGE("Can't find android/graphics/Point()"); + return -1; + } + // Register native functions return AndroidRuntime::registerNativeMethods(env, "android/hardware/Camera", camMethods, NELEM(camMethods)); diff --git a/core/jni/android_hardware_SoundTrigger.cpp b/core/jni/android_hardware_SoundTrigger.cpp index 7b33bc28d24e..2a8e6d6b5b3d 100644 --- a/core/jni/android_hardware_SoundTrigger.cpp +++ b/core/jni/android_hardware_SoundTrigger.cpp @@ -265,19 +265,22 @@ void JNISoundTriggerCallback::onRecognitionEvent(struct sound_trigger_recognitio event->capture_session, event->capture_delay_ms, event->capture_preamble_ms, event->trigger_in_data, jAudioFormat, jData, jExtras); - env->DeleteLocalRef(jAudioFormat); - env->DeleteLocalRef(jData); + env->DeleteLocalRef(jExtras); } else { jEvent = env->NewObject(gRecognitionEventClass, gRecognitionEventCstor, event->status, event->model, event->capture_available, event->capture_session, event->capture_delay_ms, event->capture_preamble_ms, event->trigger_in_data, jAudioFormat, jData); + } + + if (jAudioFormat != NULL) { env->DeleteLocalRef(jAudioFormat); + } + if (jData != NULL) { env->DeleteLocalRef(jData); } - env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject, SOUNDTRIGGER_EVENT_RECOGNITION, 0, 0, jEvent); diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 33bb90bcdb70..f09928979be4 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -390,7 +390,7 @@ android_media_AudioSystem_setMasterMute(JNIEnv *env, jobject thiz, jboolean mute return (jint) check_AudioSystem_Command(AudioSystem::setMasterMute(mute)); } -static jfloat +static jboolean android_media_AudioSystem_getMasterMute(JNIEnv *env, jobject thiz) { bool mute; diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp index 7b3528b23823..9ec9993a248c 100644 --- a/core/jni/android_os_Debug.cpp +++ b/core/jni/android_os_Debug.cpp @@ -552,6 +552,10 @@ enum { MEMINFO_SWAP_TOTAL, MEMINFO_SWAP_FREE, MEMINFO_ZRAM_TOTAL, + MEMINFO_MAPPED, + MEMINFO_VMALLOC_USED, + MEMINFO_PAGE_TABLES, + MEMINFO_KERNEL_STACK, MEMINFO_COUNT }; @@ -590,6 +594,11 @@ static void android_os_Debug_getMemInfo(JNIEnv *env, jobject clazz, jlongArray o "Slab:", "SwapTotal:", "SwapFree:", + "ZRam:", + "Mapped:", + "VmallocUsed:", + "PageTables:", + "KernelStack:", NULL }; static const int tagsLen[] = { @@ -601,12 +610,17 @@ static void android_os_Debug_getMemInfo(JNIEnv *env, jobject clazz, jlongArray o 5, 10, 9, + 5, + 7, + 12, + 11, + 12, 0 }; - long mem[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + long mem[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; char* p = buffer; - while (*p && numFound < 8) { + while (*p && numFound < 13) { int i = 0; while (tags[i]) { if (strncmp(p, tags[i], tagsLen[i]) == 0) { diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp index 4859ee6fb796..94098c91880c 100644 --- a/core/jni/android_util_AssetManager.cpp +++ b/core/jni/android_util_AssetManager.cpp @@ -1095,7 +1095,7 @@ static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject c // coming from, first XML attributes, then XML style, then default // style, and finally the theme. value.dataType = Res_value::TYPE_NULL; - value.data = 0; + value.data = Res_value::DATA_NULL_UNDEFINED; typeSetFlags = 0; config.density = 0; @@ -1157,6 +1157,7 @@ static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject c if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) { DEBUG_STYLES(ALOGI("-> Setting to @null!")); value.dataType = Res_value::TYPE_NULL; + value.data = Res_value::DATA_NULL_UNDEFINED; block = -1; } @@ -1319,7 +1320,7 @@ static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject cla // coming from, first XML attributes, then XML style, then default // style, and finally the theme. value.dataType = Res_value::TYPE_NULL; - value.data = 0; + value.data = Res_value::DATA_NULL_UNDEFINED; typeSetFlags = 0; config.density = 0; @@ -1403,6 +1404,7 @@ static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject cla if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) { DEBUG_STYLES(ALOGI("-> Setting to @null!")); value.dataType = Res_value::TYPE_NULL; + value.data = Res_value::DATA_NULL_UNDEFINED; block = kXmlBlock; } @@ -1512,7 +1514,7 @@ static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, job // Try to find a value for this attribute... value.dataType = Res_value::TYPE_NULL; - value.data = 0; + value.data = Res_value::DATA_NULL_UNDEFINED; typeSetFlags = 0; config.density = 0; @@ -1548,6 +1550,7 @@ static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, job // Deal with the special @null value -- it turns back to TYPE_NULL. if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) { value.dataType = Res_value::TYPE_NULL; + value.data = Res_value::DATA_NULL_UNDEFINED; } //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data); @@ -1661,6 +1664,7 @@ static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject claz // Deal with the special @null value -- it turns back to TYPE_NULL. if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) { value.dataType = Res_value::TYPE_NULL; + value.data = Res_value::DATA_NULL_UNDEFINED; } //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data); diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 2e2b23f25d3d..9bdc6b5c99c9 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -43,6 +43,7 @@ #include <RenderNode.h> #include <CanvasProperty.h> #include <Paint.h> +#include <renderthread/RenderProxy.h> #include "MinikinUtils.h" @@ -861,7 +862,7 @@ static void android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) { #ifdef USE_OPENGL_RENDERER int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor); - android::uirenderer::RenderNode::outputLogBuffer(fd); + android::uirenderer::renderthread::RenderProxy::outputLogBuffer(fd); #endif // USE_OPENGL_RENDERER } diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp index 050037ebada5..621df72a7747 100644 --- a/core/jni/android_view_RenderNode.cpp +++ b/core/jni/android_view_RenderNode.cpp @@ -483,68 +483,68 @@ static JNINativeMethod gMethods[] = { { "nOutput", "(J)V", (void*) android_view_RenderNode_output }, { "nGetDebugSize", "(J)I", (void*) android_view_RenderNode_getDebugSize }, - { "nSetLayerType", "(JI)Z", (void*) android_view_RenderNode_setLayerType }, - { "nSetLayerPaint", "(JJ)Z", (void*) android_view_RenderNode_setLayerPaint }, - { "nSetStaticMatrix", "(JJ)Z", (void*) android_view_RenderNode_setStaticMatrix }, - { "nSetAnimationMatrix", "(JJ)Z", (void*) android_view_RenderNode_setAnimationMatrix }, - { "nSetClipToBounds", "(JZ)Z", (void*) android_view_RenderNode_setClipToBounds }, - { "nSetClipBounds", "(JIIII)Z", (void*) android_view_RenderNode_setClipBounds }, - { "nSetClipBoundsEmpty", "(J)Z", (void*) android_view_RenderNode_setClipBoundsEmpty }, - { "nSetProjectBackwards", "(JZ)Z", (void*) android_view_RenderNode_setProjectBackwards }, - { "nSetProjectionReceiver","(JZ)Z", (void*) android_view_RenderNode_setProjectionReceiver }, + { "nSetLayerType", "!(JI)Z", (void*) android_view_RenderNode_setLayerType }, + { "nSetLayerPaint", "!(JJ)Z", (void*) android_view_RenderNode_setLayerPaint }, + { "nSetStaticMatrix", "!(JJ)Z", (void*) android_view_RenderNode_setStaticMatrix }, + { "nSetAnimationMatrix", "!(JJ)Z", (void*) android_view_RenderNode_setAnimationMatrix }, + { "nSetClipToBounds", "!(JZ)Z", (void*) android_view_RenderNode_setClipToBounds }, + { "nSetClipBounds", "!(JIIII)Z", (void*) android_view_RenderNode_setClipBounds }, + { "nSetClipBoundsEmpty", "!(J)Z", (void*) android_view_RenderNode_setClipBoundsEmpty }, + { "nSetProjectBackwards", "!(JZ)Z", (void*) android_view_RenderNode_setProjectBackwards }, + { "nSetProjectionReceiver","!(JZ)Z", (void*) android_view_RenderNode_setProjectionReceiver }, { "nSetOutlineRoundRect", "(JIIIIFF)Z", (void*) android_view_RenderNode_setOutlineRoundRect }, { "nSetOutlineConvexPath", "(JJF)Z", (void*) android_view_RenderNode_setOutlineConvexPath }, { "nSetOutlineEmpty", "(J)Z", (void*) android_view_RenderNode_setOutlineEmpty }, { "nSetOutlineNone", "(J)Z", (void*) android_view_RenderNode_setOutlineNone }, - { "nHasShadow", "(J)Z", (void*) android_view_RenderNode_hasShadow }, - { "nSetClipToOutline", "(JZ)Z", (void*) android_view_RenderNode_setClipToOutline }, + { "nHasShadow", "!(J)Z", (void*) android_view_RenderNode_hasShadow }, + { "nSetClipToOutline", "!(JZ)Z", (void*) android_view_RenderNode_setClipToOutline }, { "nSetRevealClip", "(JZFFF)Z", (void*) android_view_RenderNode_setRevealClip }, - { "nSetAlpha", "(JF)Z", (void*) android_view_RenderNode_setAlpha }, - { "nSetHasOverlappingRendering", "(JZ)Z", + { "nSetAlpha", "!(JF)Z", (void*) android_view_RenderNode_setAlpha }, + { "nSetHasOverlappingRendering", "!(JZ)Z", (void*) android_view_RenderNode_setHasOverlappingRendering }, - { "nSetElevation", "(JF)Z", (void*) android_view_RenderNode_setElevation }, - { "nSetTranslationX", "(JF)Z", (void*) android_view_RenderNode_setTranslationX }, - { "nSetTranslationY", "(JF)Z", (void*) android_view_RenderNode_setTranslationY }, - { "nSetTranslationZ", "(JF)Z", (void*) android_view_RenderNode_setTranslationZ }, - { "nSetRotation", "(JF)Z", (void*) android_view_RenderNode_setRotation }, - { "nSetRotationX", "(JF)Z", (void*) android_view_RenderNode_setRotationX }, - { "nSetRotationY", "(JF)Z", (void*) android_view_RenderNode_setRotationY }, - { "nSetScaleX", "(JF)Z", (void*) android_view_RenderNode_setScaleX }, - { "nSetScaleY", "(JF)Z", (void*) android_view_RenderNode_setScaleY }, - { "nSetPivotX", "(JF)Z", (void*) android_view_RenderNode_setPivotX }, - { "nSetPivotY", "(JF)Z", (void*) android_view_RenderNode_setPivotY }, - { "nSetCameraDistance", "(JF)Z", (void*) android_view_RenderNode_setCameraDistance }, - { "nSetLeft", "(JI)Z", (void*) android_view_RenderNode_setLeft }, - { "nSetTop", "(JI)Z", (void*) android_view_RenderNode_setTop }, - { "nSetRight", "(JI)Z", (void*) android_view_RenderNode_setRight }, - { "nSetBottom", "(JI)Z", (void*) android_view_RenderNode_setBottom }, - { "nSetLeftTopRightBottom","(JIIII)Z", (void*) android_view_RenderNode_setLeftTopRightBottom }, - { "nOffsetLeftAndRight", "(JI)Z", (void*) android_view_RenderNode_offsetLeftAndRight }, - { "nOffsetTopAndBottom", "(JI)Z", (void*) android_view_RenderNode_offsetTopAndBottom }, - - { "nHasOverlappingRendering", "(J)Z", (void*) android_view_RenderNode_hasOverlappingRendering }, - { "nGetClipToOutline", "(J)Z", (void*) android_view_RenderNode_getClipToOutline }, - { "nGetAlpha", "(J)F", (void*) android_view_RenderNode_getAlpha }, - { "nGetCameraDistance", "(J)F", (void*) android_view_RenderNode_getCameraDistance }, - { "nGetScaleX", "(J)F", (void*) android_view_RenderNode_getScaleX }, - { "nGetScaleY", "(J)F", (void*) android_view_RenderNode_getScaleY }, - { "nGetElevation", "(J)F", (void*) android_view_RenderNode_getElevation }, - { "nGetTranslationX", "(J)F", (void*) android_view_RenderNode_getTranslationX }, - { "nGetTranslationY", "(J)F", (void*) android_view_RenderNode_getTranslationY }, - { "nGetTranslationZ", "(J)F", (void*) android_view_RenderNode_getTranslationZ }, - { "nGetRotation", "(J)F", (void*) android_view_RenderNode_getRotation }, - { "nGetRotationX", "(J)F", (void*) android_view_RenderNode_getRotationX }, - { "nGetRotationY", "(J)F", (void*) android_view_RenderNode_getRotationY }, - { "nIsPivotExplicitlySet", "(J)Z", (void*) android_view_RenderNode_isPivotExplicitlySet }, - { "nHasIdentityMatrix", "(J)Z", (void*) android_view_RenderNode_hasIdentityMatrix }, - - { "nGetTransformMatrix", "(JJ)V", (void*) android_view_RenderNode_getTransformMatrix }, - { "nGetInverseTransformMatrix","(JJ)V", (void*) android_view_RenderNode_getInverseTransformMatrix }, - - { "nGetPivotX", "(J)F", (void*) android_view_RenderNode_getPivotX }, - { "nGetPivotY", "(J)F", (void*) android_view_RenderNode_getPivotY }, + { "nSetElevation", "!(JF)Z", (void*) android_view_RenderNode_setElevation }, + { "nSetTranslationX", "!(JF)Z", (void*) android_view_RenderNode_setTranslationX }, + { "nSetTranslationY", "!(JF)Z", (void*) android_view_RenderNode_setTranslationY }, + { "nSetTranslationZ", "!(JF)Z", (void*) android_view_RenderNode_setTranslationZ }, + { "nSetRotation", "!(JF)Z", (void*) android_view_RenderNode_setRotation }, + { "nSetRotationX", "!(JF)Z", (void*) android_view_RenderNode_setRotationX }, + { "nSetRotationY", "!(JF)Z", (void*) android_view_RenderNode_setRotationY }, + { "nSetScaleX", "!(JF)Z", (void*) android_view_RenderNode_setScaleX }, + { "nSetScaleY", "!(JF)Z", (void*) android_view_RenderNode_setScaleY }, + { "nSetPivotX", "!(JF)Z", (void*) android_view_RenderNode_setPivotX }, + { "nSetPivotY", "!(JF)Z", (void*) android_view_RenderNode_setPivotY }, + { "nSetCameraDistance", "!(JF)Z", (void*) android_view_RenderNode_setCameraDistance }, + { "nSetLeft", "!(JI)Z", (void*) android_view_RenderNode_setLeft }, + { "nSetTop", "!(JI)Z", (void*) android_view_RenderNode_setTop }, + { "nSetRight", "!(JI)Z", (void*) android_view_RenderNode_setRight }, + { "nSetBottom", "!(JI)Z", (void*) android_view_RenderNode_setBottom }, + { "nSetLeftTopRightBottom","!(JIIII)Z", (void*) android_view_RenderNode_setLeftTopRightBottom }, + { "nOffsetLeftAndRight", "!(JI)Z", (void*) android_view_RenderNode_offsetLeftAndRight }, + { "nOffsetTopAndBottom", "!(JI)Z", (void*) android_view_RenderNode_offsetTopAndBottom }, + + { "nHasOverlappingRendering", "!(J)Z", (void*) android_view_RenderNode_hasOverlappingRendering }, + { "nGetClipToOutline", "!(J)Z", (void*) android_view_RenderNode_getClipToOutline }, + { "nGetAlpha", "!(J)F", (void*) android_view_RenderNode_getAlpha }, + { "nGetCameraDistance", "!(J)F", (void*) android_view_RenderNode_getCameraDistance }, + { "nGetScaleX", "!(J)F", (void*) android_view_RenderNode_getScaleX }, + { "nGetScaleY", "!(J)F", (void*) android_view_RenderNode_getScaleY }, + { "nGetElevation", "!(J)F", (void*) android_view_RenderNode_getElevation }, + { "nGetTranslationX", "!(J)F", (void*) android_view_RenderNode_getTranslationX }, + { "nGetTranslationY", "!(J)F", (void*) android_view_RenderNode_getTranslationY }, + { "nGetTranslationZ", "!(J)F", (void*) android_view_RenderNode_getTranslationZ }, + { "nGetRotation", "!(J)F", (void*) android_view_RenderNode_getRotation }, + { "nGetRotationX", "!(J)F", (void*) android_view_RenderNode_getRotationX }, + { "nGetRotationY", "!(J)F", (void*) android_view_RenderNode_getRotationY }, + { "nIsPivotExplicitlySet", "!(J)Z", (void*) android_view_RenderNode_isPivotExplicitlySet }, + { "nHasIdentityMatrix", "!(J)Z", (void*) android_view_RenderNode_hasIdentityMatrix }, + + { "nGetTransformMatrix", "!(JJ)V", (void*) android_view_RenderNode_getTransformMatrix }, + { "nGetInverseTransformMatrix","!(JJ)V", (void*) android_view_RenderNode_getInverseTransformMatrix }, + + { "nGetPivotX", "!(J)F", (void*) android_view_RenderNode_getPivotX }, + { "nGetPivotY", "!(J)F", (void*) android_view_RenderNode_getPivotY }, { "nAddAnimator", "(JJ)V", (void*) android_view_RenderNode_addAnimator }, { "nEndAllAnimators", "(J)V", (void*) android_view_RenderNode_endAllAnimators }, diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index b3d9890a2199..a0b2ca830b65 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -374,6 +374,7 @@ static jlong create(JNIEnv* env, jclass clazz, jlong rootNodePtr, jlong surfaceP ContextFactory factory; RenderProxy* proxy = new RenderProxy(false, rootNode, &factory); proxy->loadSystemProperties(); + proxy->setSwapBehavior(kSwap_discardBuffer); proxy->initialize(surface); // Shadows can't be used via this interface, so just set the light source // to all 0s. (and width & height are unused, TODO remove them) diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index 7ca9374631ae..4f5e08b6efa2 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -452,14 +452,23 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra DropCapabilitiesBoundingSet(env); - bool need_native_bridge = false; - if (instructionSet != NULL) { + bool use_native_bridge = !is_system_server && (instructionSet != NULL) + && android::NativeBridgeAvailable(); + if (use_native_bridge) { ScopedUtfChars isa_string(env, instructionSet); - need_native_bridge = android::NeedsNativeBridge(isa_string.c_str()); + use_native_bridge = android::NeedsNativeBridge(isa_string.c_str()); + } + if (use_native_bridge && dataDir == NULL) { + // dataDir should never be null if we need to use a native bridge. + // In general, dataDir will never be null for normal applications. It can only happen in + // special cases (for isolated processes which are not associated with any app). These are + // launched by the framework and should not be emulated anyway. + use_native_bridge = false; + ALOGW("Native bridge will not be used because dataDir == NULL."); } - if (!MountEmulatedStorage(uid, mount_external, need_native_bridge)) { - ALOGW("Failed to mount emulated storage: %d", errno); + if (!MountEmulatedStorage(uid, mount_external, use_native_bridge)) { + ALOGW("Failed to mount emulated storage: %s", strerror(errno)); if (errno == ENOTCONN || errno == EROFS) { // When device is actively encrypting, we get ENOTCONN here // since FUSE was mounted before the framework restarted. @@ -487,15 +496,10 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra SetRLimits(env, javaRlimits); - if (!is_system_server && need_native_bridge) { - // Set the environment for the apps running with native bridge. - ScopedUtfChars isa_string(env, instructionSet); // Known non-null because of need_native_... - if (dataDir == NULL) { - android::PreInitializeNativeBridge(NULL, isa_string.c_str()); - } else { - ScopedUtfChars data_dir(env, dataDir); - android::PreInitializeNativeBridge(data_dir.c_str(), isa_string.c_str()); - } + if (use_native_bridge) { + ScopedUtfChars isa_string(env, instructionSet); + ScopedUtfChars data_dir(env, dataDir); + android::PreInitializeNativeBridge(data_dir.c_str(), isa_string.c_str()); } int rc = setresgid(gid, gid, gid); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 15b56c3ae209..8e0cd5266090 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1269,6 +1269,18 @@ android:description="@string/permdesc_use_sip" android:label="@string/permlab_use_sip" /> + <!-- Protects the ability to register any PhoneAccount with a capability flags of either + PhoneAccount#CAPABILITY_CALL_PROVIDER or PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION. --> + <permission android:name="android.permission.REGISTER_PROVIDER_OR_SUBSCRIPTION" + android:permissionGroup="android.permission-group.PHONE_CALLS" + android:description="@string/permdesc_register_provider" + android:label="@string/permlab_register_provider" /> + + <permission android:name="android.permission.REGISTER_CONNECTION_MANAGER" + android:permissionGroup="android.permission-group.PHONE_CALLS" + android:description="@string/permdesc_connection_manager" + android:label="@string/permlab_connection_manager" /> + <!-- @SystemApi Allows an application to bind to InCallService implementations. @hide --> <permission android:name="android.permission.BIND_INCALL_SERVICE" diff --git a/core/res/res/anim/activity_close_exit.xml b/core/res/res/anim/activity_close_exit.xml index 52c3adf10b4e..d8c42ed808f1 100644 --- a/core/res/res/anim/activity_close_exit.xml +++ b/core/res/res/anim/activity_close_exit.xml @@ -20,13 +20,13 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false" android:zAdjustment="top"> <alpha android:fromAlpha="1.0" android:toAlpha="0.0" - android:interpolator="@interpolator/accelerate_quart" + android:interpolator="@interpolator/linear" android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true" android:startOffset="100" android:duration="150"/> - <translate android:fromYDelta="0%" android:toYDelta="5%" + <translate android:fromYDelta="0%" android:toYDelta="8%" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/accelerate_quint" + android:interpolator="@interpolator/accelerate_quart" android:duration="250"/> </set>
\ No newline at end of file diff --git a/core/res/res/animator/fragment_close_enter.xml b/core/res/res/animator/fragment_close_enter.xml index 0b2e2cfa57bf..dccf372a3389 100644 --- a/core/res/res/animator/fragment_close_enter.xml +++ b/core/res/res/animator/fragment_close_enter.xml @@ -13,13 +13,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. */ --> -<set xmlns:android="http://schemas.android.com/apk/res/android" android:zAdjustment="normal"> - <objectAnimator - android:interpolator="@interpolator/decelerate_quad" - android:valueFrom="0.0" android:valueTo="1.0" +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <objectAnimator + android:interpolator="@interpolator/decelerate_cubic" + android:valueFrom="0" + android:valueTo="1" android:valueType="floatType" android:propertyName="alpha" android:duration="300"/> diff --git a/core/res/res/animator/fragment_close_exit.xml b/core/res/res/animator/fragment_close_exit.xml index e0ab6077a53b..ddede70799d6 100644 --- a/core/res/res/animator/fragment_close_exit.xml +++ b/core/res/res/animator/fragment_close_exit.xml @@ -13,25 +13,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. */ --> -<set xmlns:android="http://schemas.android.com/apk/res/android" android:zAdjustment="top"> - <objectAnimator - android:interpolator="@interpolator/decelerate_quad" - android:valueFrom="1.0" android:valueTo="0.8" - android:valueType="floatType" - android:propertyName="scaleY" - android:duration="300"/> - <objectAnimator - android:interpolator="@interpolator/decelerate_quad" - android:valueFrom="1.0" android:valueTo="0.8" - android:valueType="floatType" - android:propertyName="scaleX" - android:duration="300"/> +<set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator - android:interpolator="@interpolator/decelerate_quad" - android:valueFrom="1.0" android:valueTo="0.0" + android:interpolator="@interpolator/decelerate_cubic" + android:valueFrom="1" + android:valueTo="0" android:valueType="floatType" android:propertyName="alpha" android:duration="300"/> diff --git a/core/res/res/animator/fragment_fade_enter.xml b/core/res/res/animator/fragment_fade_enter.xml index 13b15f318e46..ce8913efd86c 100644 --- a/core/res/res/animator/fragment_fade_enter.xml +++ b/core/res/res/animator/fragment_fade_enter.xml @@ -16,8 +16,7 @@ ** limitations under the License. */ --> -<set xmlns:android="http://schemas.android.com/apk/res/android" - android:zAdjustment="top"> +<set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:interpolator="@interpolator/decelerate_cubic" android:valueFrom="0" diff --git a/core/res/res/animator/fragment_fade_exit.xml b/core/res/res/animator/fragment_fade_exit.xml index 503b7ad2338a..f0fbd15ee5a1 100644 --- a/core/res/res/animator/fragment_fade_exit.xml +++ b/core/res/res/animator/fragment_fade_exit.xml @@ -16,8 +16,7 @@ ** limitations under the License. */ --> -<set xmlns:android="http://schemas.android.com/apk/res/android" - android:zAdjustment="normal"> +<set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:interpolator="@interpolator/decelerate_cubic" android:valueFrom="1" diff --git a/core/res/res/animator/fragment_open_enter.xml b/core/res/res/animator/fragment_open_enter.xml index 4ae24b9e07dd..dccf372a3389 100644 --- a/core/res/res/animator/fragment_open_enter.xml +++ b/core/res/res/animator/fragment_open_enter.xml @@ -13,25 +13,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. */ --> <set xmlns:android="http://schemas.android.com/apk/res/android"> - <objectAnimator - android:interpolator="@interpolator/decelerate_cubic" - android:valueFrom="0.95" android:valueTo="1.0" - android:valueType="floatType" - android:propertyName="scaleY" - android:duration="300"/> - <objectAnimator - android:interpolator="@interpolator/decelerate_cubic" - android:valueFrom="0.95" android:valueTo="1.0" - android:valueType="floatType" - android:propertyName="scaleX" - android:duration="300"/> <objectAnimator android:interpolator="@interpolator/decelerate_cubic" - android:valueFrom="0.0" android:valueTo="1.0" + android:valueFrom="0" + android:valueTo="1" android:valueType="floatType" android:propertyName="alpha" android:duration="300"/> diff --git a/core/res/res/animator/fragment_open_exit.xml b/core/res/res/animator/fragment_open_exit.xml index 1b505fe2366a..ddede70799d6 100644 --- a/core/res/res/animator/fragment_open_exit.xml +++ b/core/res/res/animator/fragment_open_exit.xml @@ -13,13 +13,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. */ --> <set xmlns:android="http://schemas.android.com/apk/res/android"> - <objectAnimator + <objectAnimator android:interpolator="@interpolator/decelerate_cubic" - android:valueFrom="1.0" android:valueTo="0.0" + android:valueFrom="1" + android:valueTo="0" android:valueType="floatType" android:propertyName="alpha" android:duration="300"/> diff --git a/core/res/res/drawable-hdpi/ic_text_dot.png b/core/res/res/drawable-hdpi/ic_text_dot.png Binary files differdeleted file mode 100644 index fa69c69adbb8..000000000000 --- a/core/res/res/drawable-hdpi/ic_text_dot.png +++ /dev/null diff --git a/core/res/res/drawable-ldpi/ic_text_dot.png b/core/res/res/drawable-ldpi/ic_text_dot.png Binary files differdeleted file mode 100644 index 4aff20ce9763..000000000000 --- a/core/res/res/drawable-ldpi/ic_text_dot.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/ic_text_dot.png b/core/res/res/drawable-mdpi/ic_text_dot.png Binary files differdeleted file mode 100644 index 2225bd581425..000000000000 --- a/core/res/res/drawable-mdpi/ic_text_dot.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/ic_text_dot.png b/core/res/res/drawable-xhdpi/ic_text_dot.png Binary files differdeleted file mode 100644 index 869dd95beace..000000000000 --- a/core/res/res/drawable-xhdpi/ic_text_dot.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/ic_text_dot.png b/core/res/res/drawable-xxhdpi/ic_text_dot.png Binary files differdeleted file mode 100644 index a74c2862bb9d..000000000000 --- a/core/res/res/drawable-xxhdpi/ic_text_dot.png +++ /dev/null diff --git a/core/res/res/drawable/ic_text_dot.xml b/core/res/res/drawable/ic_text_dot.xml new file mode 100644 index 000000000000..f8f39645378e --- /dev/null +++ b/core/res/res/drawable/ic_text_dot.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> +<inset xmlns:android="http://schemas.android.com/apk/res/android" + android:inset="10dp"> + <shape android:shape="oval"> + <solid android:color="?android:attr/textColorSecondary" /> + <size android:width="4dp" android:height="4dp" /> + </shape> +</inset> diff --git a/core/res/res/drawable/vector_drawable_progress_bar_large.xml b/core/res/res/drawable/vector_drawable_progress_bar_large.xml index 023f5cc9db44..cd678f1c9d81 100644 --- a/core/res/res/drawable/vector_drawable_progress_bar_large.xml +++ b/core/res/res/drawable/vector_drawable_progress_bar_large.xml @@ -17,7 +17,8 @@ android:height="76dp" android:width="76dp" android:viewportHeight="48" - android:viewportWidth="48" > + android:viewportWidth="48" + android:tint="?attr/colorControlActivated"> <group android:name="root" @@ -27,7 +28,7 @@ android:name="progressBar" android:fillColor="#00000000" android:pathData="M0, 0 m 0, -19 a 19,19 0 1,1 0,38 a 19,19 0 1,1 0,-38" - android:strokeColor="?attr/colorControlActivated" + android:strokeColor="@color/white" android:strokeLineCap="square" android:strokeLineJoin="miter" android:strokeWidth="4" diff --git a/core/res/res/drawable/vector_drawable_progress_bar_medium.xml b/core/res/res/drawable/vector_drawable_progress_bar_medium.xml index e72097ebbf68..7f038f44b197 100644 --- a/core/res/res/drawable/vector_drawable_progress_bar_medium.xml +++ b/core/res/res/drawable/vector_drawable_progress_bar_medium.xml @@ -17,7 +17,8 @@ android:height="48dp" android:width="48dp" android:viewportHeight="48" - android:viewportWidth="48" > + android:viewportWidth="48" + android:tint="?attr/colorControlActivated"> <group android:name="root" @@ -27,7 +28,7 @@ android:name="progressBar" android:fillColor="#00000000" android:pathData="M0, 0 m 0, -19 a 19,19 0 1,1 0,38 a 19,19 0 1,1 0,-38" - android:strokeColor="?attr/colorControlActivated" + android:strokeColor="@color/white" android:strokeLineCap="square" android:strokeLineJoin="miter" android:strokeWidth="4" diff --git a/core/res/res/drawable/vector_drawable_progress_bar_small.xml b/core/res/res/drawable/vector_drawable_progress_bar_small.xml index 875e7a333ece..562578859be4 100644 --- a/core/res/res/drawable/vector_drawable_progress_bar_small.xml +++ b/core/res/res/drawable/vector_drawable_progress_bar_small.xml @@ -17,7 +17,8 @@ android:height="16dp" android:width="16dp" android:viewportHeight="48" - android:viewportWidth="48" > + android:viewportWidth="48" + android:tint="?attr/colorControlActivated"> <group android:name="root" @@ -27,7 +28,7 @@ android:name="progressBar" android:fillColor="#00000000" android:pathData="M0, 0 m 0, -19 a 19,19 0 1,1 0,38 a 19,19 0 1,1 0,-38" - android:strokeColor="?attr/colorControlActivated" + android:strokeColor="@color/white" android:strokeLineCap="square" android:strokeLineJoin="miter" android:strokeWidth="4" diff --git a/core/res/res/drawable/view_accessibility_focused.xml b/core/res/res/drawable/view_accessibility_focused.xml index 68e3f1ecb97f..025916b35f40 100644 --- a/core/res/res/drawable/view_accessibility_focused.xml +++ b/core/res/res/drawable/view_accessibility_focused.xml @@ -18,9 +18,7 @@ <stroke android:width="4dp" - android:color="@color/accessibility_focus_highlight" - android:dashWidth="4dp" - android:dashGap="2dp" /> + android:color="@color/accessibility_focus_highlight" /> <corners android:radius="2dp" /> diff --git a/core/res/res/layout/alert_dialog_material.xml b/core/res/res/layout/alert_dialog_material.xml index c96182853a16..5627a2c9c0a3 100644 --- a/core/res/res/layout/alert_dialog_material.xml +++ b/core/res/res/layout/alert_dialog_material.xml @@ -51,12 +51,17 @@ <!-- If the client uses a customTitle, it will be added here. --> </LinearLayout> - <LinearLayout android:id="@+id/contentPanel" + <FrameLayout android:id="@+id/contentPanel" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" - android:orientation="vertical" android:minHeight="48dp"> + <View android:id="@+id/scrollIndicatorUp" + android:visibility="gone" + android:layout_width="match_parent" + android:layout_height="1dp" + android:layout_gravity="top" + android:background="@drawable/list_divider_material"/> <ScrollView android:id="@+id/scrollView" android:layout_width="match_parent" android:layout_height="wrap_content" @@ -78,7 +83,13 @@ android:layout_height="@dimen/alert_dialog_padding_top_material" /> </LinearLayout> </ScrollView> - </LinearLayout> + <View android:id="@+id/scrollIndicatorDown" + android:visibility="gone" + android:layout_width="match_parent" + android:layout_height="1dp" + android:layout_gravity="bottom" + android:background="@drawable/list_divider_material"/> + </FrameLayout> <FrameLayout android:id="@+id/customPanel" android:layout_width="match_parent" @@ -99,7 +110,8 @@ android:paddingStart="12dp" android:paddingEnd="12dp" android:paddingTop="8dp" - android:paddingBottom="8dp"> + android:paddingBottom="8dp" + android:gravity="bottom"> <Button android:id="@+id/button3" style="?attr/buttonBarNeutralButtonStyle" android:layout_width="wrap_content" diff --git a/core/res/res/layout/select_dialog_item_material.xml b/core/res/res/layout/select_dialog_item_material.xml index fe326f35554a..b45edc6218ec 100644 --- a/core/res/res/layout/select_dialog_item_material.xml +++ b/core/res/res/layout/select_dialog_item_material.xml @@ -28,6 +28,6 @@ android:textAppearance="?android:attr/textAppearanceListItemSmall" android:textColor="?android:attr/textColorAlertDialogListItem" android:gravity="center_vertical" - android:paddingStart="@dimen/alert_dialog_padding_material" - android:paddingEnd="@dimen/alert_dialog_padding_material" + android:paddingStart="?attr/listPreferredItemPaddingStart" + android:paddingEnd="?attr/listPreferredItemPaddingEnd" android:ellipsize="marquee" /> diff --git a/core/res/res/layout/time_header_label.xml b/core/res/res/layout/time_header_label.xml index 5c970402cc12..efb362847df4 100644 --- a/core/res/res/layout/time_header_label.xml +++ b/core/res/res/layout/time_header_label.xml @@ -20,14 +20,13 @@ android:layout_height="match_parent"> <RelativeLayout android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_gravity="center"> + android:layout_height="match_parent"> <TextView android:id="@+id/hours" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toLeftOf="@+id/separator" - android:layout_alignBaseline="@+id/separator" /> + android:layout_centerVertical="true" /> <TextView android:id="@+id/separator" android:layout_width="wrap_content" @@ -41,14 +40,35 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@+id/separator" - android:layout_alignBaseline="@+id/separator" /> - <TextView - android:id="@+id/ampm_label" + android:layout_centerVertical="true" /> + <LinearLayout + android:id="@+id/ampm_layout" + android:layout_alignBaseline="@+id/minutes" + android:layout_toEndOf="@+id/separator" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:paddingLeft="@dimen/timepicker_ampm_left_padding" - android:paddingRight="@dimen/timepicker_ampm_left_padding" - android:layout_toRightOf="@+id/separator" - android:layout_alignBaseline="@+id/separator" /> + android:baselineAlignedChildIndex="1" + android:orientation="vertical"> + <CheckedTextView + android:id="@+id/am_label" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingStart="@dimen/timepicker_ampm_horizontal_padding" + android:paddingTop="@dimen/timepicker_ampm_vertical_padding" + android:paddingEnd="@dimen/timepicker_ampm_horizontal_padding" + android:paddingBottom="@dimen/timepicker_am_bottom_padding" + android:lines="1" + android:ellipsize="none" /> + <CheckedTextView + android:id="@+id/pm_label" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingStart="@dimen/timepicker_ampm_horizontal_padding" + android:paddingTop="@dimen/timepicker_pm_top_padding" + android:paddingEnd="@dimen/timepicker_ampm_horizontal_padding" + android:paddingBottom="@dimen/timepicker_ampm_vertical_padding" + android:lines="1" + android:ellipsize="none" /> + </LinearLayout> </RelativeLayout> </FrameLayout> diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index 2a1be0335b89..ec4bd5027b3e 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"verander jou eie kontakkaart"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Laat die program toe om persoonlike profielinligting, soos jou naam en kontakinligting, wat op jou toestel gestoor is, te verander of daarby te voeg. Dit beteken dat die program jou kan identifiseer en moontlik jou profielinligting na ander mense kan stuur."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"liggaamsensors (soos hartklopmonitors)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Laat die program toe om toegang tot data te verkry vanaf sensors wat jy gebruik om te meet wat binne jou liggaam aangaan, soos hartklop."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Laat die program toe om toegang te verkry tot data van sensors af wat jou fisieke toestand, soos jou polsslag, monitor."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"lees jou sosiale stroom"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Laat die program toe om toegang tot sosiale opdaterings van jou en jou vriende te verkry en dit te sinkroniseer. Wees versigtig wanneer jy inligting deel -- dit laat die program toe om kommunikasie tussen jou en jou vriende op sosiale netwerke te lees, ongeag vertroulikheid. Let wel: hierdie toestemming mag dalk nie op alle sosiale netwerke afgedwing word nie."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"skryf aan jou sosiale stroom"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Laat die program toe om die kaslêerstelsel te lees en skryf."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"maak en/of ontvang SIP-oproepe"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Laat die program toe om SIP-oproepe te maak en te ontvang."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"registreer nuwe telekom-verbinding"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Laat die program toe om nuwe telekom-verbindings te registreer."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"bestuur telekom-verbindings"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Laat die program toe om telekom-verbindings te bestuur."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"beleef interaksie met inoproep-skerm"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Laat die program beheer wanneer en hoe die gebruiker die inoproep-skerm sien."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"werk met telefoniedienste saam"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Probeer weer"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Probeer weer"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Maksimum gesigontsluit-pogings oorskry"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Laai, (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Gelaai"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Koppel jou herlaaier."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Geen SIM-kaart nie"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Geen SIM-kaart in tablet nie."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Geen SIM-kaart in foon nie."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Vra wagwoord voordat jy ontspeld"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Om batteryleeftyd te help verbeter, verminder batterybespaarder jou toestel se werkverrigting en beperk vibrasie en die meeste agtergronddata. E-pos, boodskappe en ander programme wat op sinkronisering staatmaak, sal dalk nie opdateer nie tensy jy hulle oopmaak.\n\nBatterybespaarder skakel outomaties af wanneer jou toestel laai."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Totdat jou ontspantyd om <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> eindig"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Een minuut lank"</item> <item quantity="other" msgid="6924190729213550991">"%d minute lank"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Een uur lank"</item> <item quantity="other" msgid="5408537517529822157">"%d uur lank"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Onbepaalde tyd"</string> </resources> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 2425de1bccb6..2ba358dfb784 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"የራስዎን የዕውቂያ ካርድ ያስተካክሉ"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"መተግበሪያው ልክ እንደ ስምዎ እና የእውቂያ መረጃዎ ያሉ በመሳሪያዎ ላይ የተከማቹ የግል መገለጫ መረጃዎችን እንዲቀይር ወይም እንዲያክልባቸው ይፈቅድለታል። ይህም ማለት መተግበሪያው ለይቶ ሊያውቅዎ እና የመገለጫ መረጃዎን ለሌሎች ሊልክ ይችላል።"</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"የሰውነት መመርመሪያዎች (እንደ የልብ ምት መቆጣጠሪያዎች)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"መተግበሪያው እርስዎ በሰውነትዎ ውስጥ እየተካሄዱ ያሉ እንደ የልብ ምት የመሳሰሉ ነገሮችን ለመለካት የሚጠቀሙበትን ውሂብ ከመመርመሪያዎቹ ላይ እንዲደርስ ይፈቅድለታል።"</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"እንደ የእርስዎ የልብ ምት የመሳሰሉ ያሉበትን አካላዊ ሁኔታ ከሚቆጣጠሩ ሰውነት ዳሳሾች ውሂብ ላይ እንዲደርስ ለመተግበሪያው ይፈቅደለታል።"</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"የእርስዎን ማህበራዊ የውይይት ክፍሎች ያንብቡ"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"መተግበሪያው የአንተንና የጓኞችህን ማህበራዊ ዝማኔዎችን እንዲደርስባቸው እና እንዲያመሳስላቸው ይፈቅድለታል። መረጃ ስታጋራ ተጠንቀቅ -- ይህ መተግበሪያው ሚስጥራዊነትን ከግምት ሳያስገባ በማህበራዊ አውታረ መረቦች በአንተ እና በጓደኞችህ መካከል የሚደረጉ ግንኙነቶችን እንዲያነብ ይፈቅድለታል። ማስታወሻ፦ ይህ ፈቃድ ለሁሉም ማህበራዊ አውታር መረቦች ላይ ላይፈጸም ይችላል።"</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"ወደ የእርስዎ ማህበራዊ የውይይት ክፍሎች ይጻፉ"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"መሸጎጫ ስርዓተ ፋይል ለማንበብ እና ለመፃፍ ለመተግበሪያው ይፈቅዳሉ።"</string> <string name="permlab_use_sip" msgid="2052499390128979920">"የSIP ጥሪዎችን ያድርጉ/ይቀበሉ"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"መተግበሪያው የSIP ጥሪዎችን እንዲያደር እና እንዲቀበል ያስችላል።"</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"አዲስ የቴሌኮም ግንኙነት ይመዘግባል"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"መተግበሪያው አዲስ የቴሌክኮም ግንኙነቶችን እንዲመዘግብ ያስችለዋል"</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"የቴሌኮም ግንኙነቶችን ያቀናብራል"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"መተግበሪያው የቴሌኮም ግንኙነቶችን እንዲያቀናብር ያስችለዋል።"</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"ከውስጠ-ጥሪ ማያ ገጽ ጋር መስተጋብር ይፈጥራል"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"መተግበሪያው ተጠቃሚው በጥሪ ውስጥ ያለውን ማያ ገጽ መቼ እና እንዴት ማየት እንደሚችል እንዲቆጣጠር ይፈቅድለታል።"</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"ከስልክ አገልግሎቶች ጋር መስተጋብር ይፈጥራል"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"እንደገና ሞክር"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"እንደገና ሞክር"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"የመጨረሻውን የገጽ ክፈት ሙከራዎችን አልፏል"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"ኃይል በመሙላት ላይ፣ <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"ባትሪ ሞልቷል።"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"ኃይል መሙያዎን ያያይዙ"</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"ምንም ሲም ካርድ የለም"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"በጡባዊ ውስጥ ምንም SIM ካርድ የለም።"</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"በስልክ ውስጥ ምንም SIM ካርድ የለም።"</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ከመንቀል በፊት የይለፍ ቃል ጠይቅ"</string> <string name="battery_saver_description" msgid="2510530476513605742">"የባትሪ ህይወትን ለማሻሻል ሲባል ባትሪ ቆጣቢ የመሣሪያዎ የስራ አፈጻጸምን እና ንዝረትንና አብዛኛውን የጀርባ ውሂብ ይቀንሳል። ኢሜይል፣ መልዕክት መላላኪያ እና ሌሎች በማመሳሰል ላይ የሚወሰኑ መተግበሪያዎች እስኪከፍቷቸው ድረስ ላይዘምኑ ይችላሉ።\n\nመሣሪያዎ ባትሪ እየሞላ ሲሆን ባትሪ ቆጣቢ በራስ-ሰር ይጠፋል።"</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"የጥገና ጊዜዎ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> ላይ እስኪያበቃ ድረስ"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"ለአንድ ደቂቃ"</item> <item quantity="other" msgid="6924190729213550991">"ለ%d ደቂቃዎች"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"ለአንድ ሰዓት"</item> <item quantity="other" msgid="5408537517529822157">"ለ%d ሰዓቶች"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"ያለገደብ"</string> </resources> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index 85c67bec25b4..d1320d86d545 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"تعديل بطاقة جهة الاتصال الخاصة"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"للسماح للتطبيق بتغيير المعلومات الشخصية في الملف الشخصي المخزنة على الجهاز أو الإضافة إليها، مثل اسمك ومعلومات جهات الاتصال. ويعني ذلك أنه يمكن للتطبيق التعرف عليك كما يمكنه إرسال معلومات ملفك الشخصي إلى الآخرين."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"أجهزة استشعار الجسم (مثل شاشات معدل ضربات القلب)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"للسماح للتطبيق بالدخول إلى البيانات من أجهزة الاستشعار التي تستخدمها لقياس ما يجري داخل جسمك، مثل معدل ضربات القلب."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"للسماح للتطبيق بالدخول إلى البيانات من المستشعرات التي تراقب الحالة البدنية، مثل معدل نبضات القلب."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"قراءة المشاركات الاجتماعية"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"للسماح للتطبيق بالدخول إلى التحديثات الاجتماعية منك ومن أصدقائك ومزامنتها. توخ الحذر عند مشاركة المعلومات، حيث يتيح هذا للتطبيق قراءة عمليات التواصل بينك وبين أصدقائك على الشبكات الاجتماعية، بغض النظر عن مدى السرية. ملاحظة: لا يجوز فرض هذا الإذن على جميع الشبكات الاجتماعية."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"كتابة إلى المشاركات الاجتماعية"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"للسماح للتطبيق بقراءة نظام ملفات ذاكرة التخزين المؤقت والكتابة به."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"إجراء/تلقي مكالمات SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"للسماح للتطبيق بإجراء مكالمات SIP وتلقيها."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"تسجيل الاتصال اللاسلكي الجديد"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"للسماح للتطبيق بتسجيل الاتصالات اللاسلكية الجديدة."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"إدارة الاتصالات اللاسلكية"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"للسماح للتطبيق بإدارة الاتصالات اللاسلكية."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"التفاعل مع الشاشة أثناء الاتصال"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"للسماح للتطبيق بالتحكم في وقت وكيفية مشاهدة المستخدم للشاشة أثناء الاتصال."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"التفاعل مع الخدمات الهاتفية"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"أعد المحاولة"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"أعد المحاولة"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"تم تجاوز الحد الأقصى لعدد محاولات تأمين الجهاز بالوجه"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"جارٍ الشحن، <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"تم الشحن"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"توصيل جهاز الشحن."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"ليست هناك بطاقة SIM"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ليس هناك بطاقة SIM في الجهاز اللوحي."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ليس هناك بطاقة SIM في الهاتف."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"المطالبة بكلمة المرور قبل إزالة التثبيت"</string> <string name="battery_saver_description" msgid="2510530476513605742">"للمساعدة في تحسين مدة تشغيل البطارية، يقلل وضع توفير طاقة البطارية أداء جهازك ويقلل من الاهتزاز ومعظم بيانات الخلفية. وقد لا يتم تحديث البريد الإلكتروني والمراسلة والتطبيقات الأخرى التي تعتمد على المزامنة ما لم تفتحها.\n\nيتم إيقاف وضع توفير طاقة البطارية تلقائيًا عندما يكون الجهاز قيد الشحن."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"إلى أن ينتهي وقت التوقف عن العمل في <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"لمدة دقيقة واحدة"</item> <item quantity="other" msgid="6924190729213550991">"لمدة %d من الدقائق"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"لمدة ساعة واحدة"</item> <item quantity="other" msgid="5408537517529822157">"لمدة %d من الساعات"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"إلى أجل غير مسمى"</string> </resources> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index 0aa18b1be3ec..e202127d35a4 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"промяна на собств. ви карт. с данни за контакт"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Разрешава на приложението да променя или добавя към личния потребителски профил информация, съхранена на устройството ви, като например вашето име и данни за връзка. Това означава, че приложението може да ви идентифицира и да изпраща данните за потребителския ви профил на други хора."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"телесни сензори (като монитори за сърдечния ритъм)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Разрешава на приложението да осъществява достъп до данни от използваните от вас сензори, за да измери какво се случва в тялото ви, като например сърдечен ритъм."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Разрешава на приложението да осъществява достъп до данните от сензорите, които следят физическото ви състояние, като например сърдечния ви ритъм."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"четене на социалния ви поток"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Разрешава на приложението да осъществява достъп и да синхронизира социални актуализации от вас и приятелите ви. Бъдете внимателни при споделянето на информация – това позволява на приложението да чете съобщения помежду ви в социалните мрежи независимо от поверителността. Забележка: Възможно е ограниченията на това разрешение да не могат да бъдат наложени във всички социални мрежи."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"писане в социалния ви поток"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Разрешава на приложението да чете и записва във файловата система на кеша."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"извършване/получаване на обаждания чрез SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Разрешава на приложението да извършва и получава обаждания чрез SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"регистриране на новите телекомуникационни връзки"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Разрешава на приложението да регистрира новите телекомуникационни връзки."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"управление на телекомуникационните връзки"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Разрешава на приложението да управлява телекомуникационните връзки."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"взаимодействие с екрана за обаждане"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Разрешава на приложението да контролира кога и как потребителят вижда екрана за обаждане."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"взаимодействие с телефонни услуги"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Опитайте отново"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Опитайте отново"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Максималният брой опити за отключване с лице е надвишен"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Зарежда се, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Заредена"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Свържете зарядното си устройство."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Няма SIM карта"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"В таблета няма SIM карта."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"В телефона няма SIM карта."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Запитване за парола преди освобождаване"</string> <string name="battery_saver_description" msgid="2510530476513605742">"С цел удължаване на живота на батерията режимът за запазването й намалява ефективността на устройството ви и ограничава вибрирането и повечето данни на заден план. Имейл, Съобщения и другите приложения, които разчитат на синхронизиране, може да не се актуализират, освен ако не ги отворите.\n\nТози режим автоматично се изключва, когато устройството ви се зарежда."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"До приключване на неактивността в <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"За една минута"</item> <item quantity="other" msgid="6924190729213550991">"За %d минути"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"За един час"</item> <item quantity="other" msgid="5408537517529822157">"За %d часа"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"За неопределено време"</string> </resources> diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml index 0c97f2427854..43a758d26312 100644 --- a/core/res/res/values-bn-rBD/strings.xml +++ b/core/res/res/values-bn-rBD/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"আপনার নিজস্ব পরিচিতি কার্ড সংশোধন করুন"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"অ্যাপ্লিকেশানটিকে আপনার ডিভাইসে সংরক্ষিত ব্যক্তিগত প্রোফাইলের তথ্য যেমন আপনার নাম এবং পরিচিতি তথ্য পড়ার অনুমতি দেয়৷ এর মানে হল এই অ্যাপ্লিকেশানটি আপনাকে শনাক্ত করতে পারে এবং আপনার প্রোফাইলের তথ্য অন্যদের পাঠাতে পারে৷"</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"শরীরের সেন্সর (হার্ট রেট মনিটারের মত)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"অ্যাপ্লিকেশানকে, হৃদস্পন্দনের মতো, আপনার শরীরের ভেতর কি ঘটছে তা পরিমাপ করার জন্য ব্যবহৃত সেন্সর থেকে তথ্য অ্যাক্সেস করার অনুমতি দেয়৷"</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"অ্যাপ্লিকেশানটিকে আপনার শারীরিক অবস্থা যেমন, আপনার হৃৎস্পন্দন পর্যবেক্ষণ করে এমন সেন্সরগুলি অ্যাক্সেস করতে মঞ্জুরি দেয়।"</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"আপনার সামাজিক স্ট্রীম পড়ে"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"অ্যাপ্লিকেশানটিকে আপনার এবং আপনার বন্ধুদের থেকে সামাজিক আপডেটগুলিতে অ্যাক্সেস এবং সিঙ্ক করতে দেয়৷ তথ্য ভাগ করার সময় সতর্ক থাকুন -- এই অ্যাপ্লিকেশানটিকে গোপনীয়তা নির্বিশেষে সামাজিক নেটওয়ার্কগুলিতে আপনি এবং আপনার বন্ধুদের মধ্যে যোগাযোগগুলি পড়তে দেয়৷ দ্রষ্টব্য: এই অনুমতি সমস্ত সামাজিক নেটওয়ার্কে বলবৎ নাও হতে পারে৷"</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"আপনার সামাজিক স্ট্রীমে লেখে"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"ক্যাশে ফাইল সিস্টেম পড়তে ও লিখতে অ্যাপ্লিকেশানকে অনুমতি দেয়৷"</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP কল করুন/গ্রহণ করুন"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"অ্যাপ্লিকেশানকে SIP কল করতে ও গ্রহণ করতে অনুমতি দেয়।"</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"নতুন টেলিকম সংযোগ নিবন্ধিত করুন"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"নতুন টেলিকম সংযোগ নিবন্ধিত করতে অ্যাপ্লিকেশানটিকে অনুমোদিত করে৷"</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"টেলিকম সংযোগগুলি পরিচালনা করুন"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"টেলিকম সংযোগগুলি পরিচালনা করতে অ্যাপ্লিকেশানটিকে অনুমোদিত করে৷"</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"কলে-থাকা স্ক্রীণের সাথে ইন্টারঅ্যাক্ট করে"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ব্যবহারকারী কখন এবং কীভাবে কলে-থাকা স্ক্রীণটিকে দেখতে পাবেন, অ্যাপ্লিকেশানটিকে তা নিয়ন্ত্রণ করতে দেয়৷"</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"টেলিফোন পরিষেবার সাথে ইন্টারঅ্যাক্ট করুন"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"আবার চেষ্টা করুন"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"আবার চেষ্টা করুন"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"মুখের সাহায্যে আনলক করার প্রচেষ্টা যতবার করা যায় তার সীমা পেরিয়ে গেছে"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"চার্জ হচ্ছে, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"চার্জ হয়েছে"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"আপনার চার্জার সংযুক্ত করুন৷"</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"কোনো সিম কার্ড নেই"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ট্যাবলেটের মধ্যে কোনো সিম কার্ড নেই৷"</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ফোনের মধ্যে কোনো সিম কার্ড নেই৷"</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"আনপিন করার আগে পাসওয়ার্ড চান"</string> <string name="battery_saver_description" msgid="2510530476513605742">"ব্যাটারির আয়ু বাড়াতে সহায়তার জন্য, ব্যাটারি সঞ্চয়কারী আপনার ডিভাইসের কার্য-সম্পাদনা কমিয়ে আনবে এবং কম্পন ও পশ্চাদভূমি ডেটাকে সীমিত করবে। ইমেল, বার্তাপ্রেরণ ও অন্যান্য অ্যাপ্লিকেশান, যেগুলি সিঙ্ক হওয়ার উপর নির্ভরশীল সেগুলিকে আপনি না খোলা পর্যন্ত সেগুলি আপডেট নাও হতে পারে।\n\nআপনার ডিভাইস চার্জ হওয়ার সময় ব্যাটারি সঞ্চয়কারী স্বয়ংক্রিয়ভাবে বন্ধ হয়ে যাবে।"</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>টার সময়ে আপনার ডাউনটাইম শেষ হওয়া পর্যন্ত"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"এক মিনিটের জন্য"</item> <item quantity="other" msgid="6924190729213550991">"%d মিনিটের জন্য"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"এক ঘন্টার জন্য"</item> <item quantity="other" msgid="5408537517529822157">"%d ঘন্টার জন্য"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"অনির্দিষ্টভাবে"</string> </resources> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index fc9c470660a8..5aeb5d9bb9bb 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"modificació targeta contacte"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permet que l\'aplicació pugui canviar o afegir informació del perfil personal emmagatzemada al dispositiu, com ara el teu nom i la teva informació de contacte. Això significa que l\'aplicació et pot identificar i enviar la informació del teu perfil a altres persones."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"sensors corp. (monitors freq. cardíaca)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Permet que l\'aplicació accedeixi a les dades dels sensors que utilitzes per mesurar els signes vitals del teu cos, com ara la freqüència cardíaca."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Permet que l\'aplicació accedeixi a les dades dels sensors que supervisen el teu estat físic, com ara la freqüència cardíaca."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"llegeix el teu tauler d\'activitat social"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permet que l\'aplicació accedeixi i sincronitzi actualitzacions socials teves i dels teus amics. Vés amb compte en compartir informació: això permet que l\'aplicació llegeixi comunicacions entre tu i els teus amics a les xarxes socials, independentment de la confidencialitat. Nota: És possible que aquest permís no s\'apliqui a totes les xarxes socials."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"escriu al tauler d\'activitat social"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permet que l\'aplicació llegeixi el sistema de fitxers de la memòria cau i que hi escrigui."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"Fer i rebre trucades de SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Permet que l\'aplicació pugui fer i rebre trucades de SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"registrar connexions de telecomunicacions noves"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Permet que l\'aplicació registri connexions de telecomunicacions noves."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"gestionar les connexions de telecomunicacions"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Permet que l\'aplicació gestioni les connexions de telecomunicacions."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interaccionar amb la pantalla de la trucada"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Permet que l\'aplicació controli quan i com l\'usuari veu la pantalla de la trucada."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"interacciona amb els serveis de telefonia"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Torna-ho a provar"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Torna-ho a provar"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"S\'ha superat el nombre màxim d\'intents de desbloqueig facial"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"S\'està carregant, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Carregada"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Connecteu el carregador."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"No hi ha cap targeta SIM."</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No hi ha cap targeta SIM a la tauleta."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"No hi ha cap targeta SIM al telèfon."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Demana la contrasenya abans d\'anul·lar la fixació"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Per tal d\'augmentar la durada de la bateria, la funció d\'estalvi de bateria redueix el rendiment del dispositiu i en limita la vibració i la majoria de dades en segon pla. És possible que el correu electrònic, la missatgeria i la resta d\'aplicacions que se sincronitzen amb freqüència no s\'actualitzin llevat que les obris.\n\nL\'estalvi de bateria es desactiva automàticament mentre el dispositiu s\'està carregant."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Fins que no finalitzi la inactivitat a les <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>."</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Durant un minut"</item> <item quantity="other" msgid="6924190729213550991">"Durant %d minuts"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Durant una hora"</item> <item quantity="other" msgid="5408537517529822157">"Durant %d hores"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidament"</string> </resources> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 2b3f873bd033..ffb80dac46a5 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"úprava vaší vlastní vizitky"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Umožňuje aplikaci změnit nebo přidat údaje osobního profilu uložené v zařízení, například jméno nebo kontaktní údaje. Znamená to, že vás aplikace může identifikovat a odeslat údaje z profilu dalším aplikacím."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"tělesné senzory (například snímače tepu)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Umožňuje aplikaci přistupovat k datům ze senzorů, pomocí kterých měříte činnost svého těla, například tep."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Umožňuje aplikaci používat data ze senzorů, které sledují vaši fyzickou kondici, například tepovou frekvenci."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"čtení vašeho sociálního streamu"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Umožňuje aplikaci získat přístup k sociálním aktualizacím od vašich přátel a synchronizaci těchto aktualizací. Při sdílení informací buďte opatrní – toto oprávnění umožňuje aplikaci číst komunikaci mezi vámi a vašimi přáteli v sociálních sítích bez ohledu na její důvěrnost. Poznámka: Toto oprávnění nemusí platit pro všechny sociální sítě."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"zápis do sociálního streamu"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Umožňuje aplikaci číst a zapisovat do souborového systému mezipaměti."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"uskutečňování/příjem volání SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Povolí aplikaci uskutečňovat a přijímat volání SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"registrace nového telekomunikačního připojení"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Umožňuje aplikaci registrovat nová telekomunikační připojení."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"správa telekomunikačních připojení"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Umožňuje aplikaci spravovat telekomunikační připojení."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interakce s obrazovkou příchozího hovoru"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Umožňuje aplikaci řídit, kdy a jak se uživateli zobrazí obrazovka příchozího hovoru."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"komunikace s telefonními službami"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Zkusit znovu"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Zkusit znovu"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Překročili jste maximální povolený počet pokusů o odemknutí obličejem."</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Nabíjení - <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Nabito"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Připojte dobíjecí zařízení."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Není vložena SIM karta"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"V tabletu není SIM karta."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"V telefonu není žádná SIM karta."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Před uvolněním požádat o heslo"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Za účelem zvýšení životnosti baterie spořič baterie sníží výkon vašeho zařízení a omezí vibrace a většinu dat na pozadí. E-mail, zprávy a další aplikace, které používají synchronizaci, nemusejí být aktualizovány, dokud je nespustíte.\n\nPři nabíjení zařízení se spořič baterie automaticky vypne."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Dokud v <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> neskončí pozastavení"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Na jednu minutu"</item> <item quantity="other" msgid="6924190729213550991">"Na %d min"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Na 1 h"</item> <item quantity="other" msgid="5408537517529822157">"Na %d h"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Na dobu neurčitou"</string> </resources> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 677b9733da1d..0a81979b61c4 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"ændre dit eget kontaktkort"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Tillader, at appen kan ændre eller tilføje oplysninger i din personlige profil, der er gemt på din enhed, f.eks. dit navn eller dine kontaktoplysninger. Dette betyder, at andre apps kan identificere dig og sende profiloplysninger til andre."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"kropssensorer (f.eks. pulsmålere)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Tillader, at appen får adgang til data fra sensorer, du bruger til at måle, hvad der sker inde i din krop, f.eks. din puls."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Giver appen adgang til data fra sensorer, der overvåger din fysiske tilstand, f.eks. din puls."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"læse din sociale strøm"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Tillader, at appen kan få adgang til og synkronisere sociale opdateringer fra dig og dine venner. Vær forsigtig, når du deler oplysninger – med denne tilladelse kan appen læse kommunikation mellem dig og dine venner på sociale netværk, uanset fortrolighed. Bemærk! Denne tilladelse håndhæves muligvis ikke på alle sociale netværk."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"skrive i din sociale strøm"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Tillader, at appen kan læse og skrive i cachefilsystemet."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"foretage/modtage SIP-opkald"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Tillader, at appen foretager og modtager SIP-opkald."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"registrere nye telefonforbindelser"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Tillader, at appen registrerer nye telefonforbindelser."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"administrere telefonforbindelser"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Tillader, at appen administrerer telefonforbindelser."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interager med skærmen under opkald"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Tillader, at appen styrer, hvornår og hvordan brugeren ser skærmen for indgående opkald."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"interagere med telefonitjenester"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Prøv igen"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Prøv igen"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Det maksimale antal forsøg på at bruge Ansigtslås er overskredet"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Oplader, <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Opladet"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Tilslut din oplader."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Intet SIM-kort"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Der er ikke noget SIM-kort i tabletcomputeren."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Der er ikke noget SIM-kort i telefonen."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Bed om adgangskode inden frigørelse"</string> <string name="battery_saver_description" msgid="2510530476513605742">"For at forbedre batteriets levetid reducerer batterisparefunktionen enhedens ydeevne og begrænser vibrationer og de fleste baggrundsdata. E-mail, beskeder og andre apps, der benytter synkronisering, opdateres ikke, medmindre du åbner dem.\n\nBatterisparefunktionen deaktiveres automatisk, når enheden oplades."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Indtil din nedetid slutter kl. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"I ét minut"</item> <item quantity="other" msgid="6924190729213550991">"I %d minutter"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"I én time"</item> <item quantity="other" msgid="5408537517529822157">"I %d timer"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Uendeligt"</string> </resources> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 8924f9a631f5..74bd5f93fa02 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"Ihre Kontaktkarten ändern"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Ermöglicht der App, auf Ihrem Gerät gespeicherte personenbezogene Profildaten zu ändern, einschließlich Ihres Namens und Ihrer Kontaktdaten, sowie Daten hinzuzufügen. Die App kann Sie so identifizieren und Ihre Profildaten an andere senden."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"Körpersensoren (wie Herzfrequenzmesser)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Ermöglicht der App den Zugriff auf Daten von Sensoren, mit denen Ihre Vitalfunktionen, etwa die Herzfrequenz, gemessen werden."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Ermöglicht der App, auf Daten von Sensoren zuzugreifen, die Ihre körperliche Verfassung überwachen, beispielsweise Ihre Herzfrequenz"</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"In sozialem Stream lesen"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Ermöglicht der App, auf Updates aus sozialen Netzwerken von Ihnen und Ihren Freunden zuzugreifen und diese zu synchronisieren. Seien Sie vorsichtig, wenn Sie Informationen teilen: Der App wird erlaubt, die Kommunikation zwischen Ihnen und Ihren Freunden in sozialen Netzwerken zu lesen, unabhängig von der Vertraulichkeit der kommunizierten Informationen. Hinweis: Diese Berechtigung kann möglicherweise nicht in allen sozialen Netzwerken erzwungen werden."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"In sozialem Stream schreiben"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Ermöglicht der App Lese- und Schreibzugriff auf das Cache-Dateisystem"</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP-Anrufe tätigen/empfangen"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Ermöglicht der App das Tätigen und Empfangen von SIP-Anrufen"</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"Neue Telekommunikationsverbindungen registrieren"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Gestattet der App die Registrierung neuer Telekommunikationsverbindungen"</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"Telekommunikationsverbindungen verwalten"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Gestattet der App die Verwaltung der Telekommunikationsverbindungen"</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"Mit Anrufbildschirm interagieren"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Die App kann steuern, wann und wie der Nutzer den Anrufbildschirm sieht."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"Mit Telefondiensten interagieren"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Erneut versuchen"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Erneut versuchen"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Die maximal zulässige Anzahl an Face Unlock-Versuchen wurde überschritten."</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Wird aufgeladen... (<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Aufgeladen"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Ladegerät anschließen"</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Keine SIM-Karte"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Keine SIM-Karte im Tablet"</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Keine SIM-Karte im Telefon"</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Vor dem Beenden nach Passwort fragen"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Der Energiesparmodus hilft, den Akku zu schonen, indem er die Leistung des Geräts reduziert und die Vibrationsfunktion und die meisten Hintergrunddatenaktivitäten einschränkt. E-Mail-, SMS/MMS- und andere Apps, die die Synchronisierungsfunktion benötigen, werden möglicherweise nicht aktualisiert, bis Sie sie öffnen.\n\nDer Energiesparmodus endet automatisch, wenn Ihr Gerät aufgeladen wird."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Bis zum Ende der Downtime um <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Für eine Minute"</item> <item quantity="other" msgid="6924190729213550991">"Für %d Minuten"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Für eine Stunde"</item> <item quantity="other" msgid="5408537517529822157">"Für %d Stunden"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Unbegrenzt"</string> </resources> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 9b8f0da54265..edffefc5ff6a 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"τροποποίηση κάρτας επαφής"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Επιτρέπει στην εφαρμογή την αλλαγή ή την προσθήκη προσωπικών πληροφοριών προφίλ οι οποίες είναι αποθηκευμένες στη συσκευή σας, όπως το όνομα και τα στοιχεία επικοινωνίας σας. Αυτό σημαίνει ότι η εφαρμογή μπορεί να σας αναγνωρίσει και να στείλει τις πληροφορίες του προφίλ σας σε άλλα άτομα."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"αισθητήρες λειτουργιών (π.χ. καρδιακό ρυθμό)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Επιτρέπει στην εφαρμογή την πρόσβαση στα δεδομένα από τους αισθητήρες που χρησιμοποιείτε για να παρακολουθείτε τις εσωτερικές λειτουργίες σας, όπως τον καρδιακό ρυθμό."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Επιτρέπει στην εφαρμογή να αποκτήσει πρόσβαση στα δεδομένα των αισθητήρων που παρακολουθούν τη φυσική σας κατάσταση, όπως τον καρδιακό ρυθμό σας."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"διαβάστε τη ροή σας κοινωνικών δικτύων"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Επιτρέπει στην εφαρμογή την πρόσβαση και το συγχρονισμό κοινωνικών ενημερώσεων από εσάς και τους φίλους σας. Θα πρέπει να είστε προσεκτικοί όταν μοιράζεστε πληροφορίες -- αυτό δίνει τη δυνατότητα στην εφαρμογή να διαβάζει τις επικοινωνίες ανάμεσα σε εσάς και τους φίλους σας σε κοινωνικά δίκτυα, ανεξάρτητα από το επίπεδο εμπιστευτικότητας. Σημείωση: αυτή η άδεια ίσως να μην μπορεί να εφαρμοστεί σε όλα τα κοινωνικά δίκτυα."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"γράψτε στη ροή σας κοινωνικών δικτύων"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Επιτρέπει στην εφαρμογή την ανάγνωση και την εγγραφή του συστήματος αρχείων προσωρινής μνήμης."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"πραγματοποίηση/λήψη κλήσεων SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Επιτρέπει στην εφαρμογή να πραγματοποιεί και να λαμβάνει κλήσεις SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"εγγραφή νέας σύνδεσης τηλεπικοινωνιών"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Επιτρέπει στην εφαρμογή να εγγράφει νέες συνδέσεις τηλεπικοινωνιών."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"διαχείριση των συνδέσεων τηλεπικοινωνιών"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Επιτρέπει στην εφαρμογή να διαχειρίζεται τις συνδέσεις τηλεπικοινωνιών."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"αλληλεπίδραση με την οθόνη κατά τη διάρκεια κλήσης"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Επιτρέπει στην εφαρμογή να ελέγχει πότε και πώς βλέπει ο χρήστης την οθόνη κατά τη διάρκεια κλήσης."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"αλληλεπίδραση με υπηρεσίες τηλεφωνίας"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Προσπαθήστε ξανά"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Προσπαθήστε ξανά"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Έγινε υπέρβαση του μέγιστου αριθμού προσπαθειών Face Unlock"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Φόρτιση, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Μπαταρία πλήρης"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Συνδέστε τον φορτιστή."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Δεν υπάρχει κάρτα SIM"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Δεν υπάρχει κάρτα SIM στο tablet."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Δεν υπάρχει κάρτα SIM στο τηλέφωνο."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Να γίνεται ερώτηση για τον κωδικό πρόσβασης, πριν από το ξεκαρφίτσωμα"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Για τη βελτίωση της διάρκειας ζωής της μπαταρίας, η λειτουργία εξοικονόμησης μπαταρίας μειώνει την απόδοση της συσκευής σας και περιορίζει τη δόνηση και την πλειονότητα των δεδομένων παρασκηνίου. Το ηλεκτρονικό ταχυδρομείου, η ανταλλαγή μηνυμάτων και άλλες εφαρμογές που βασίζονται στο συγχρονισμό ενδέχεται να μην ενημερώνονται, παρά μόνο εάν τις ανοίξετε.\n\nΗ λειτουργία εξοικονόμησης μπαταρίας απενεργοποιείται αυτόματα κατά τη φόρτιση της συσκευής σας."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Έως τη λήξη του νεκρού χρόνου σας στις <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Για ένα λεπτό"</item> <item quantity="other" msgid="6924190729213550991">"Για %d λεπτά"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Για μία ώρα"</item> <item quantity="other" msgid="5408537517529822157">"Για %d ώρες"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Επ\' αόριστον"</string> </resources> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index ac974a614219..e3569034302c 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"modify your own contact card"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Allows the app to change or add to personal profile information stored on your device, such as your name and contact information. This means that the app can identify you and may send your profile information to others."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"body sensors (like heart rate monitors)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Allows the app to access data from sensors that you use to measure what’s happening inside your body, such as heart rate."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Allows the app to access data from sensors that monitor your physical condition, such as your heart rate."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"read your social stream"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Allows the app to access and sync social updates from you and your friends. Be careful when sharing information - this allows the app to read communications between you and your friends on social networks, regardless of confidentiality. Note: this permission may not be enforced on all social networks."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"write to your social stream"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Allows the app to read and write the cache file system."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"make/receive SIP calls"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Allows the app to make and receive SIP calls."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"register new telecom connection"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Allows the app to register new telecom connections."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"manage telecom connections"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Allows the app to manage telecom connections."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interact with in-call screen"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Allows the app to control when and how the user sees the in-call screen."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"interact with telephony services"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Try again"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Try again"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Maximum Face Unlock attempts exceeded"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Charging, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Charged"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Connect your charger."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"No SIM card"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No SIM card in tablet."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"No SIM card in phone."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ask for password before unpinning"</string> <string name="battery_saver_description" msgid="2510530476513605742">"To help improve battery life, battery saver reduces your device’s performance and limits vibration and most background data. Email, messaging and other apps that rely on syncing may not update unless you open them.\n\nBattery saver turns off automatically when your device is charging."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Until your downtime ends at <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"For one minute"</item> <item quantity="other" msgid="6924190729213550991">"For %d minutes"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"For one hour"</item> <item quantity="other" msgid="5408537517529822157">"For %d hours"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Indefinitely"</string> </resources> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index ac974a614219..e3569034302c 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"modify your own contact card"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Allows the app to change or add to personal profile information stored on your device, such as your name and contact information. This means that the app can identify you and may send your profile information to others."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"body sensors (like heart rate monitors)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Allows the app to access data from sensors that you use to measure what’s happening inside your body, such as heart rate."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Allows the app to access data from sensors that monitor your physical condition, such as your heart rate."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"read your social stream"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Allows the app to access and sync social updates from you and your friends. Be careful when sharing information - this allows the app to read communications between you and your friends on social networks, regardless of confidentiality. Note: this permission may not be enforced on all social networks."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"write to your social stream"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Allows the app to read and write the cache file system."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"make/receive SIP calls"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Allows the app to make and receive SIP calls."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"register new telecom connection"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Allows the app to register new telecom connections."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"manage telecom connections"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Allows the app to manage telecom connections."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interact with in-call screen"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Allows the app to control when and how the user sees the in-call screen."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"interact with telephony services"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Try again"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Try again"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Maximum Face Unlock attempts exceeded"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Charging, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Charged"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Connect your charger."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"No SIM card"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No SIM card in tablet."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"No SIM card in phone."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ask for password before unpinning"</string> <string name="battery_saver_description" msgid="2510530476513605742">"To help improve battery life, battery saver reduces your device’s performance and limits vibration and most background data. Email, messaging and other apps that rely on syncing may not update unless you open them.\n\nBattery saver turns off automatically when your device is charging."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Until your downtime ends at <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"For one minute"</item> <item quantity="other" msgid="6924190729213550991">"For %d minutes"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"For one hour"</item> <item quantity="other" msgid="5408537517529822157">"For %d hours"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Indefinitely"</string> </resources> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index ed573e9cc6ec..816436b2aea7 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"modif. tarjeta contacto propia"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permite que la aplicación modifique la información del perfil personal almacenada en el dispositivo, como el nombre o la información de contacto, o que agregue contenido a esa información. Esto significa que puede identificarte y enviar la información de tu perfil a otros usuarios."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"sensores corporales (frec. card)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Permite que la aplicación acceda a datos de sensores que utilizas para medir lo que sucede en tu cuerpo, como la frecuencia cardíaca."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Permite que la aplicación acceda a datos de sensores que controlan tu condición física, como el ritmo cardíaco."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"Lectura de tu muro social"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permite que la aplicación acceda a las actualizaciones de tus redes sociales y las de tus amigos, y que las sincronice. Ten cuidado al compartir información, ya que la aplicación puede utilizar este permiso para leer las conversaciones que tengas con tus amigos en las redes sociales sin tener en cuenta si son confidenciales. Nota: Este permiso no se puede utilizar en todas las redes sociales."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"Escritura en tu muro social"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permite que la aplicación lea y escriba el sistema de archivos almacenado en caché."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"realizar/recibir llamadas SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Permite que la aplicación realice y reciba llamadas SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"registrar conexiones de telecomunicaciones nuevas"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Permite que la aplicación registre las conexiones de telecomunicaciones nuevas."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"administrar conexiones de telecomunicaciones"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Permite que la aplicación administre las conexiones de telecomunicaciones."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interactuar con la pantalla de llamada"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Permite que la aplicación controle cuándo y cómo el usuario ve la pantalla de llamada."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"interaccionar con servicios de telefonía"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Vuelve a intentarlo."</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Volver a intentarlo"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Se superó el máximo de intentos permitido para el desbloqueo facial del dispositivo."</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Cargando <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Cargada"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Conecta tu cargador."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Sin tarjeta SIM"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No hay tarjeta SIM en el tablet."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"No hay tarjeta SIM en el dispositivo."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar contraseña para quitar fijación"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Para ayudar a mejorar la duración de la batería, la función de ahorro de batería reduce el rendimiento del dispositivo y limita la vibración y la mayor parte de la transmisión de datos en segundo plano. Es posible que las aplicaciones que se sincronizan, como las de correo electrónico y mensajería, no se actualicen a menos que las abras.\n\nEl ahorro de batería se desactiva automáticamente cuando el dispositivo se está cargando."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Hasta que termine el tiempo de inactividad a la(s) <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Durante un minuto"</item> <item quantity="other" msgid="6924190729213550991">"Durante %d minutos"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Durante una hora"</item> <item quantity="other" msgid="5408537517529822157">"Durante %d horas"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidamente"</string> </resources> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index b585e96a7e48..10c8716661a5 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"modificar tu propia tarjeta de contacto"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permite que la aplicación modifique la información del perfil personal almacenada en el dispositivo (como el nombre o la información de contacto) o que añada contenido a esa información, lo que significa que puede identificar al usuario y enviar la información de su perfil a otros usuarios."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"sens. corp. (mon. frec. card.)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Permite que la aplicación acceda a datos de sensores que utilizas para medir lo que sucede en tu cuerpo, como la frecuencia cardíaca."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Permite que la aplicación acceda a datos de sensores que controlan tu condición física, como la frecuencia cardíaca."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"consulta tu actividad social"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permite que la aplicación acceda a novedades de redes sociales tuyas y de tus amigos y las sincronice. Ten cuidado al compartir información, ya que la aplicación puede utilizar este permiso para leer conversaciones privadas con tus amigos en las redes sociales sin tener en cuenta si son confidenciales. Nota: este permiso no se puede utilizar en todas las redes sociales."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"escribir en tu actividad social"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permite que la aplicación lea y escriba el sistema de archivos almacenado en caché."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"hacer/recibir llamadas SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Permite que la aplicación haga y reciba llamadas SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"registrar conexiones de telecomunicaciones nuevas"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Permite que la aplicación registre conexiones de telecomunicaciones nuevas."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"administrar conexiones de telecomunicaciones"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Permite que la aplicación administre las conexiones de telecomunicaciones."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interactuar con la pantalla de llamada"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Permite que la aplicación controle cómo y cuándo aparece la pantalla de llamada."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"interactuar con servicios de telefonía"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Vuelve a intentarlo"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Vuelve a intentarlo"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Se ha superado el número máximo de intentos de desbloqueo facial."</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Cargando (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Cargada"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Conecta el cargador"</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Falta la tarjeta SIM."</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No se ha insertado ninguna tarjeta SIM en el tablet."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"No se ha insertado ninguna tarjeta SIM en el teléfono."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar contraseña para desactivar"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Para ayudar a mejorar la duración de la batería, la función de ahorro de energía reduce el rendimiento del dispositivo y limita la vibración y la mayor parte de la transmisión de datos en segundo plano. Es posible que las aplicaciones que se sincronizan, como las de correo y mensajes, no se actualicen a menos que las abras.\n\nLa función de ahorro de energía se desactiva automáticamente cuando el dispositivo se carga."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Hasta que el tiempo de inactividad finalice el <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Durante un minuto"</item> <item quantity="other" msgid="6924190729213550991">"Durante %d minutos"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Durante 1 hora"</item> <item quantity="other" msgid="5408537517529822157">"Durante %d horas"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidamente"</string> </resources> diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml index f2b543b7eb6b..379aef5bd143 100644 --- a/core/res/res/values-et-rEE/strings.xml +++ b/core/res/res/values-et-rEE/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"muutke oma kontaktikaarti"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Võimaldab rakendusel muuta või lisada seadmesse salvestatud isiklikku profiiliteavet, näiteks teie nime ja kontaktteavet. See tähendab, et rakendus saab teid tuvastada ja saata teie profiiliteavet teistele."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"kehaandurid (nt pulsilugeja)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Lubab rakendusel saada juurdepääsu selliste andurite andmetele, mida kasutate kehas toimuva (nt pulsi) mõõtmiseks."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Lubab rakendusel hankida juurdepääsu andmetele anduritest, mis jälgivad teie füüsilist seisundit, nt südame löögisagedust."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"Sotsiaalvoo lugemine"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Annab rakendusele juurdepääsu ja võimaldab sünkroonida teie ja teie sõprade sotsiaalseid värskendusi. Olge teabe jagamisel ettevaatlik – see võimaldab rakendusel lugeda teie suhtlusi sõpradega suhtlusvõrgustikes konfidentsiaalsusest hoolimata. Märkus: see luba ei pruugi jõustuda kõigis suhtlusvõrgustikes."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"Sotsiaalvoogu kirjutamine"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Võimaldab rakendusel vahemälu failisüsteemi lugeda ja kirjutada."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP-kõnede tegemine/vastuvõtmine"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Lubab rakendusel teha ja vastu võtta SIP-kõnesid."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"uute telekommunikatsiooni ühenduste registreerimine"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Lubab rakendusel registreerida uusi telekommunikatsiooni ühendusi."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"telekommunikatsiooni ühenduste haldamine"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Lubab rakendusel hallata telekommunikatsiooni ühendusi."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"ekraani Kõne pooleli kasutamine"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Lubab rakendusel juhtida, millal ja kuidas kasutajale kuvatakse ekraan Kõne pooleli."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"telefoniteenustega suhtlemine"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Proovige uuesti"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Proovige uuesti"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Maksimaalne teenusega Face Unlock avamise katsete arv on ületatud"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Laadimine, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Laetud"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Ühendage laadija."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM-kaarti pole"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tahvelarvutis pole SIM-kaarti."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Telefonis pole SIM-kaarti."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Enne vabastamist küsi parooli"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Aku kestuse parandamiseks vähendab akusäästja teie seadme jõudlust ja piirab vibratsiooni ning suuremat osa taustaandmetest. E-posti, sõnumsidet ja muid sünkroonimisele tuginevaid rakendusi võidakse värskendada ainult siis, kui te need avate.\n\nAkusäästja lülitatakse seadme laadimise ajal automaatselt välja."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Kuni seisakuaja lõppemiseni kell <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Üheks minutiks"</item> <item quantity="other" msgid="6924190729213550991">"%d minutiks"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Üheks tunniks"</item> <item quantity="other" msgid="5408537517529822157">"%d tunniks"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Määramata ajaks"</string> </resources> diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml index a67b3645658c..c19b209fcc37 100644 --- a/core/res/res/values-eu-rES/strings.xml +++ b/core/res/res/values-eu-rES/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"zeure kontaktu-txartela aldatzea"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Gailuan gordetako profil pertsonalaren informazioa aldatzeko baimena ematen dio; esaterako, zure izena eta harremanetan jartzeko informazioa. Horrek esan nahi du aplikazioak identifikatu egin zaitzakeela eta zure profil-informazioa besteei bidal diezaiekeela."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"Gorputzaren sentsoreak (adibidez, bihotz-erritmoaren monitoreak)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Zure gorputzaren barnean gertatzen ari dena (adibidez, bihotz-erritmoa) neurtzeko sentsoreen datuak atzitzea baimentzen die aplikazioei."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Zure egoera fisikoa kontrolatzen duten sentsoreetako datuak (adibidez, bihotz-maiztasuna) atzitzea baimentzen die aplikazioei."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"irakurri sare sozialetako korronteak"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Zure eta zure lagunen sare sozialetako eguneratzeak atzitzeko baimena ematen die aplikazioei. Kontuz partekatu informazioa; baimen honekin aplikazioak zure eta zure lagunen arteko sare sozialetako komunikazioak irakur ditzake, isilpekotasuna kontuan izan gabe. Oharra: baliteke baimen hori sare sozial guztiek ez aplikatzea."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"idatzi sare sozialetako korronteetan"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Cachearen fitxategi-sistema irakurtzea eta bertan idaztea baimentzen die aplikazioei."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"Egin/Jaso SIP deiak"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"SIP deiak egitea eta jasotzea baimentzen die aplikazioei."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"erregistratu telekomunikabideekiko konexioak"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Telekomunikabideekiko konexioak erregistratzea baimentzen die aplikazioei."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"kudeatu telekomunikabideekiko konexioak"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Telekomunikabideekiko konexioak kudeatzea baimentzen die aplikazioei."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"Deiak abian direnean pantaila erabiltzea"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Erabiltzaileak deiaren pantaila noiz eta nola ikusten duen kontrolatzea baimentzen die aplikazioei."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"Elkarreragin telefono-zerbitzuekin"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Saiatu berriro"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Saiatu berriro"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Aurpegiaren bidez desblokeatzeko saiakera muga gainditu da"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Kargatzen, <xliff:g id="PERCENT">%%</xliff:g> <xliff:g id="NUMBER">%d</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Kargatuta"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="PERCENT">%%</xliff:g> <xliff:g id="NUMBER">%d</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Konektatu kargagailua."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Ez dago SIM txartelik"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Ez dago SIM txartelik tabletan."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Ez dago SIM txartelik telefonoan."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Eskatu pasahitza aingura kendu aurretik"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Bateriak gehiago iraun dezan, bateria aurrezteko aukerak gailuaren errendimendua murrizten du, eta dardara eta atzeko planoko datu gehienak mugatzen ditu. Baliteke posta elektronikoa, mezuak eta sinkronizatzen diren beste aplikazio batzuk ez eguneratzea, ireki ezean.\n\nBateria aurrezteko aukera automatikoki desaktibatzen da gailua kargatzen ari denean."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> arte iraungo du jarduerarik gabeko aldiak"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Minutu batez"</item> <item quantity="other" msgid="6924190729213550991">"%d minutuz"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Ordubetez"</item> <item quantity="other" msgid="5408537517529822157">"%d orduz"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Mugagabea"</string> </resources> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 5b8d4665c1dd..543171661d1e 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"اصلاح کارت تماس شما"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"به برنامه اجازه میدهد تا اطلاعات نمایه شخصی ذخیره شده در دستگاه شما، مانند نام و اطلاعات تماس شما را تغییر دهد یا اضافه کند. یعنی برنامه میتواند شما را شناسایی کند و ممکن است اطلاعات نمایهٔ شما را برای دیگران ارسال کند."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"حسگرهای بدن (مانند پایشگرهای ضربان قلب)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"به برنامه امکان میدهد به اطلاعات حسگرهایی که استفاده میکنید، دسترسی پیدا کند تا اندازهگیریهای مربوط به آنچه که درون بدنتان رخ میدهد، مانند ضربان قلب، را انجام دهد."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"به برنامه امکان میدهد به اطلاعات حسگرهایی که بر شرایط فیزیکی شما مانند ضربان قلبتان، نظارت دارند، دسترسی داشته باشد."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"خواندن جریان اجتماعی شما"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"به برنامه اجازه میدهد به بهروزرسانیهای اجتماعی از طرف شما و دوستان شما دسترسی پیدا کرده و آنها را همگامسازی کند. دقت کنید که هنگام اشتراکگذاری -- این ویژگی به برنامه اجازه میدهد ارتباطات بین شما و دوستان شما را در شبکههای اجتماعی، صرفنظر از محرمانه بودن آنها بخواند. توجه: این مجوز ممکن است در همه شبکههای اجتماعی اجرا نشود."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"نوشتن در جریان اجتماعی شما"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"به برنامه اجازه میدهد تا سیستم فایل حافظهٔ پنهان را بخواند و بنویسد."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"تماس گرفتن/دریافت تماس از طریق SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"به برنامه اجازه میدهد تماسهای SIP بگیرد یا دریافت کند."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"ثبت ارتباط مخابراتی جدید"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"به برنامه امکان میدهد ارتباط مخابراتی جدید ثبت کند."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"مدیریت ارتباطات مخابراتی"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"به برنامه امکان میدهد ارتباطات مخابراتی را مدیریت کند."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"تعامل با صفحهنمایش هنگام تماس"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"به برنامه امکان میدهد کنترل کند که کاربر چه زمانی و چگونه صفحهنمایش هنگام تماس را مشاهده کند."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"تعامل با سرویسهای تلفنی"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"دوباره امتحان کنید"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"دوباره امتحان کنید"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"دفعات تلاش برای Face Unlock از حداکثر مجاز بیشتر شد"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"در حال شارژ، <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"شارژ شد"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"شارژر خود را متصل کنید."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"سیم کارت موجود نیست"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"سیم کارت درون رایانهٔ لوحی نیست."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"سیم کارت درون تلفن نیست."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"درخواست گذرواژه قبل از برداشتن پین"</string> <string name="battery_saver_description" msgid="2510530476513605742">"برای کمک به بهبود عمر باتری، ذخیرهکننده باتری عملکرد دستگاهتان را کاهش میدهد و اغلب اطلاعات پسزمینه و لرزش را محدود میکند. ایمیل، پیامرسانی و سایر برنامههایی که به همگامسازی وابسته هستند ممکن است بهروز نشوند مگر اینکه آنها را باز کنید.\n\nوقتی دستگاهتان شارژ میشود، ذخیرهکننده باتری به صورت خودکار خاموش میشود."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"تا زمانی که زمان استراحت در <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> به پایان برسد"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"برای یک دقیقه"</item> <item quantity="other" msgid="6924190729213550991">"برای %d دقیقه"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"برای یک ساعت"</item> <item quantity="other" msgid="5408537517529822157">"برای %d ساعت"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"نامحدود"</string> </resources> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 12363b17199f..fdec59ae3fc2 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"muokkaa omia yhteystietoja"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Antaa sovelluksen muuttaa laitteelle tallennettuja henkilökohtaisia tietoja, kuten nimeä ja yhteystietoja, tai lisätä niitä. Sovellus voi tunnistaa sinut ja lähettää profiilitietojasi muille."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"kehon anturit (kuten sykemittarit)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Antaa sovelluksen käyttää tietoja antureista, joita käytetään kehon toimintojen kuten sykkeen mittaamiseen."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Antaa sovelluksen käyttää kehosi tilaa seuraavien anturien tietoja, esimerkiksi sykettä."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"lue sosiaalista streamia"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Antaa sovelluksen käyttää ja synkronoida sinun tai kavereidesi päivityksiä sosiaalisista palveluista. Mieti tarkkaan ennen tietojen jakamista: tämän luvan saaneet sovellukset voivat lukea sinun ja kavereidesi välisiä viestejä sosiaalisissa verkkopalveluissa huolimatta viestien arkaluonteisuudesta. Huom: tätä lupaa ei saa ottaa käyttöön kaikissa sosiaalisissa verkkopalveluissa."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"kirjoita sosiaaliseen streamiin"</string> @@ -716,6 +716,14 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Antaa sovelluksen lukea välimuistin tiedostojärjestelmää ja kirjoittaa siihen."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"soita/vastaanota SIP-puheluja"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Sallii sovelluksen soittaa ja vastaanottaa SIP-puheluja."</string> + <!-- no translation found for permlab_register_provider (2654513709546459553) --> + <skip /> + <!-- no translation found for permdesc_register_provider (7571533832018681544) --> + <skip /> + <!-- no translation found for permlab_connection_manager (1116193254522105375) --> + <skip /> + <!-- no translation found for permdesc_connection_manager (5925480810356483565) --> + <skip /> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"Vuorovaikutteinen puhelunäyttö"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Antaa sovelluksen määrätä, milloin ja millaisena käyttäjä näkee puhelunäytön."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"Puhelinpalveluiden yhteyslupa"</string> @@ -905,10 +913,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Yritä uudelleen"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Yritä uudelleen"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Face Unlock -yrityksiä tehty suurin sallittu määrä."</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Ladataan (<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Täynnä"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Kytke laturi."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Ei SIM-korttia"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tablet-laitteessa ei ole SIM-korttia."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Puhelimessa ei ole SIM-korttia."</string> @@ -1776,6 +1780,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pyydä salasana ennen irrotusta"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Akunsäästötoiminto heikentää laitteen suorituskykyä ja rajoittaa värinää ja useimpia taustatietoja akun iän pidentämiseksi. Sähköposti, viestitys ja muut synkronointia edellyttävät sovellukset eivät ehkä päivity, ellet käynnistä niitä.\n\nAkunsäästö kytkeytyy automaattisesti pois laitteen akun latauksen ajaksi."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Käyttökatkos päättyy klo <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Minuutiksi"</item> <item quantity="other" msgid="6924190729213550991">"%d minuutiksi"</item> @@ -1784,5 +1792,7 @@ <item quantity="one" msgid="3480040795582254384">"Tunniksi"</item> <item quantity="other" msgid="5408537517529822157">"%d tunniksi"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Toistaiseksi"</string> </resources> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index 94df317e3995..ed7386c0c292 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"modifier votre fiche de contact"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permet à l\'application de modifier les données de profil enregistrées sur votre appareil, telles que votre nom et vos coordonnées, ou d\'en ajouter. Elle peut alors vous identifier et envoyer vos données de profil à des tiers."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"capteurs corporels (tels que les moniteurs de fréquence cardiaque)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Permet à l\'application d\'accéder aux données des capteurs utilisés pour mesurer des valeurs physiologiques, telles que votre fréquence cardiaque."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Permet à l\'application d\'accéder aux données des capteurs qui surveillent votre condition physique, comme votre rythme cardiaque."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"lire les flux de réseaux sociaux"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permet à l\'application d\'accéder à vos mises à jour sur les réseaux sociaux, ainsi qu\'à celles de vos amis, et de les synchroniser. Soyez prudent lorsque vous partagez de l\'information. Cette autorisation permet à l\'application de lire les communications entre vous et vos amis sur les réseaux sociaux, indépendamment de leur caractère confidentiel. Remarque : Il est possible que cette autorisation ne soit pas appliquée sur tous les réseaux sociaux."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"modifier vos flux de réseaux sociaux"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permet à l\'application d\'obtenir des droits en lecture et en écriture pour le système de fichiers du cache."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"faire et recevoir des appels SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Autorise l\'application à effectuer et à recevoir des appels SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"enregistrer des nouvelles connexions de télécommunication"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Permettre à l\'application d\'enregistrer de nouvelles connexions de télécommunication"</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"gérer les connexions de télécommunication"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Permettre à l\'application de gérer les connexions de télécommunication"</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interagir avec l\'écran d\'appel"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Permet à l\'application de contrôler quand et comment l\'écran d\'appel s\'affiche."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"interagir avec les services de téléphonie"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Réessayer"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Réessayer"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Nombre maximal autorisé de tentatives Face Unlock atteint."</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"En charge (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Chargé"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Branchez votre chargeur."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Aucune carte SIM"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Aucune carte SIM n\'est insérée dans la tablette."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Aucune carte SIM n\'est insérée dans le téléphone."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Demander le mot de passe avant d\'annuler l\'épinglage"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Pour optimiser l\'autonomie de la pile, l\'économiseur d\'énergie réduit les performances de votre appareil et limite les données en arrière-plan. Vous devrez peut-être ouvrir manuellement les applications de courriel, de messagerie et les autres applications synchronisées pour les mettre à jour.\n\nL\'économiseur d\'énergie se désactive automatiquement lorsque votre appareil est en charge."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Jusqu\'à ce que le temps d\'arrêt se termine à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Pendant une minute"</item> <item quantity="other" msgid="6924190729213550991">"Pendant %d minutes"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Pendant une heure"</item> <item quantity="other" msgid="5408537517529822157">"Pendant %d heures"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Indéfiniment"</string> </resources> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index d752b930aa0e..4f67038d9236 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"modifier votre fiche de contact"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permet à l\'application de modifier les informations de profil stockées sur votre appareil, telles que votre nom et vos coordonnées, ou d\'en ajouter. Elle peut alors vous identifier et envoyer vos informations de profil à des tiers."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"capteurs corporels (tels que les cardiofréquencemètres)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Permet à l\'application d\'accéder aux données des capteurs utilisés pour mesurer des valeurs physiologiques, telles que votre fréquence cardiaque."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Permet à l\'application d\'accéder aux données des capteurs qui contrôlent votre condition physique, comme votre rythme cardiaque."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"lire votre flux de réseau social"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permet à l\'application d\'accéder à vos mises à jour sur les réseaux sociaux, ainsi qu\'à celles de vos amis, et de les synchroniser. Soyez prudent lorsque vous partagez des informations. Cette autorisation permet à l\'application de lire les communications entre vous et vos amis sur les réseaux sociaux, indépendamment de leur caractère confidentiel. Remarque : il est possible que cette autorisation ne soit pas appliquée sur tous les réseaux sociaux."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"écrire sur votre flux social"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permet à l\'application d\'obtenir des droits en lecture/écriture concernant le système de fichiers du cache."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"effectuer/recevoir des appels SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Autorise l\'application à effectuer et à recevoir des appels SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"enregistrer des nouvelles connexions de télécommunication"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Permettre à l\'application d\'enregistrer de nouvelles connexions de télécommunication"</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"gérer les connexions de télécommunication"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Permettre à l\'application de gérer les connexions de télécommunication"</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"contrôler l\'écran d\'appel"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Permet à l\'application de contrôler quand et comment l\'écran d\'appel s\'affiche."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"interagir avec des services de téléphonie"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Veuillez réessayer."</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Veuillez réessayer."</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Nombre maximal autorisé de tentatives Face Unlock atteint."</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"En charge (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Chargé"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Branchez votre chargeur."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Aucune carte SIM"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Aucune carte SIM n\'est insérée dans la tablette."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Aucune carte SIM n\'est insérée dans le téléphone."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Demander le mot de passe avant d\'annuler l\'épinglage"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Pour optimiser l\'autonomie de la batterie, l\'économiseur de batterie réduit les performances de votre appareil et limite les données en arrière-plan. Vous devrez peut-être ouvrir manuellement vos applications d\'e-mail, de messagerie instantanée et autres applications synchronisées pour les mettre à jour.\n\nL\'économiseur de batterie s\'éteint automatiquement lorsque votre appareil est en charge."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Jusqu\'à ce que le temps d\'arrêt se termine à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Pendant une minute"</item> <item quantity="other" msgid="6924190729213550991">"Pendant %d minutes"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Pendant une heure"</item> <item quantity="other" msgid="5408537517529822157">"Pendant %d heures"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Indéfiniment"</string> </resources> diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml index bc152824da0a..08de833cd6ed 100644 --- a/core/res/res/values-gl-rES/strings.xml +++ b/core/res/res/values-gl-rES/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"modificar tarxeta de contacto"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permite á aplicación cambiar ou engadir á información do perfil persoal almacenada no teu dispositivo, como o teu nome e información de contacto. Isto significa que a aplicación pode identificarte e enviar a información do teu perfil a outros usuarios."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"sensores de corpo (como monitores de ritmo cardíaco)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Permite á aplicación acceder a datos de sensores que utilizas para medir o que está pasando dentro do teu corpo, como o ritmo cardíaco."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Permite que a aplicación acceda aos datos dos sensores que controlan o teu estado físico, como o ritmo cardíaco."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"ler a túa actividade social"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permite á aplicación acceder ás túas actualizacións nas redes sociais, e sincronizalas, e ás dos teus amigos. Ten coidado ao compartir información (esta acción permite á aplicación ler comunicacións entre ti e os teus amigos efectuadas a través das redes sociais, independentemente da súa confidencialidade). Nota: É posible que este permiso non se execute en todas as redes sociais."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"escribir na túa actividade social"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permite á aplicación ler e escribir no sistema de ficheiros da caché."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"facer/recibir chamadas SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Permite que a aplicación faga e reciba chamadas SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"rexistrar nova conexión de telecomunicacións"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Permite que a aplicación rexistre novas conexións de telecomunicacións."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"xestionar conexións de telecomunicacións"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Permite que a aplicación xestione conexións de telecomunicacións."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interactuar cunha pantalla de chamada"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Permite á aplicación controlar cando e como ve o usuario a pantalla de chamada."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"interactuar cos servizos de telefonía"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Téntao de novo"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Téntao de novo"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Superouse o número máximo de intentos de desbloqueo facial"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Cargando, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Cargado"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Conecta o cargador."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Non hai ningunha tarxeta SIM"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Non hai ningunha tarxeta SIM no tablet."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Non hai ningunha tarxeta SIM no teléfono."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar un contrasinal antes de soltar a pantalla"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Para axudar a mellorar a duración da batería, o aforro de batería reduce o rendemento do dispositivo e restrinxe a vibración e a maioría dos datos en segundo plano. É posible que o correo, as mensaxes e outras aplicacións que se sincronizan con frecuencia, non se actualicen a menos que as abras.\n\nO aforro de batería desactívase automaticamente durante a carga do dispositivo."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Ata que remate o tempo de inactividade ás <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Durante un minuto"</item> <item quantity="other" msgid="6924190729213550991">"Durante %d minutos"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Durante unha hora"</item> <item quantity="other" msgid="5408537517529822157">"Durante %d horas"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidamente"</string> </resources> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index a873cafddd46..51586ffb64a6 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"स्वयं का संपर्क कार्ड बदलें"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"ऐप्स को आपके डिवाइस में संग्रहीत निजी प्रोफ़ाइल जानकारी, जैसे आपका नाम और संपर्क जानकारी को बदलने या उसमें कुछ जोड़ने देता है. इसका अर्थ है कि ऐप्स आपको पहचान सकता है और आपकी प्रोफ़ाइल जानकारी अन्य लोगों को भेज सकता है."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"बॉडी सेंसर (जैसे हृदय गति मॉनीटर)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"ऐप्लिकेशन को ऐसे सेंसर का डेटा एक्सेस करने देती है जिनका उपयोग आप यह मापने के लिए करते हैं कि आपके शरीर के भीतर क्या चल रहा है, जैसे हृदय गति."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"ऐप को आपकी शारीरिक स्थिति, जैसे आपकी हृदय गति पर नज़र रखने वाले संवेदकों का डेटा एक्सेस करने देती है."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"अपनी सामाजिक स्ट्रीम पढ़ें"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"एप को आपके और आपके मित्रों की नई सामाजिक जानकारी तक पहुंचने और उन्हें समन्वयित करने देता है. जानकारी साझा करते समय सावधान रहें - इससे गोपनीयता पर ध्यान दिए बिना, एप सामाजिक नेटवर्क पर आपके और आपके मित्रों के बीच संचारों को पढ़ सकता है. ध्यान दें: यह अनुमति सभी सामाजिक नेटवर्क पर लागू नहीं की जा सकती."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"सामाजिक स्ट्रीम में लिखें"</string> @@ -716,6 +716,14 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"ऐप्स को संचय फ़ाइल सिस्टम पढ़ने और लिखने देता है."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP कॉल करें/प्राप्त करें"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"ऐप्स को SIP कॉल करने और प्राप्त करने देती है."</string> + <!-- no translation found for permlab_register_provider (2654513709546459553) --> + <skip /> + <!-- no translation found for permdesc_register_provider (7571533832018681544) --> + <skip /> + <!-- no translation found for permlab_connection_manager (1116193254522105375) --> + <skip /> + <!-- no translation found for permdesc_connection_manager (5925480810356483565) --> + <skip /> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"इन-कॉल स्क्रीन से सहभागिता करें"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ऐप्स को यह नियंत्रित करने देती है कि उपयोगकर्ता को इन-कॉल स्क्रीन कब और कैसी दिखाई देती है."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"टेलीफ़ोनी सेवाओं के साथ सहभागिता करें"</string> @@ -905,10 +913,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"फिर से प्रयास करें"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"फिर से प्रयास करें"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"फेस अनलॉक के अधिकतम प्रयासों की सीमा पार हो गई"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"चार्ज हो रही है, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"चार्ज हो गया"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"अपना चार्जर कनेक्ट करें."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"कोई सिम कार्ड नहीं है"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"टेबलेट में कोई सिम कार्ड नहीं है."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"फ़ोन में कोई सिम कार्ड नहीं है."</string> @@ -1776,6 +1780,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"अनपिन करने से पहले पासवर्ड के लिए पूछें"</string> <string name="battery_saver_description" msgid="2510530476513605742">"बैटरी के जीवन काल को बेहतर बनाने में सहायता के लिए, बैटरी सेवर आपके डिवाइस के प्रदर्शन को घटा देता है तथा कंपन और अधिकांश पृष्ठभूमि डेटा को सीमित कर देता है. ईमेल, संदेश सेवा और अन्य ऐप्स जो समन्वयन पर निर्भर करते हैं वे तब तक अपडेट नहीं हो सकते जब तक कि आप उन्हें नहीं खोलते.\n\nजब आपका डिवाइस चार्ज हो रहा होता है तो बैटरी सेवर अपने आप बंद हो जाता है."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"जब तक कि <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> बजे आपका डाउनटाइम समाप्त न हो"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"एक मिनट के लिए"</item> <item quantity="other" msgid="6924190729213550991">"%d मिनट के लिए"</item> @@ -1784,5 +1792,7 @@ <item quantity="one" msgid="3480040795582254384">"एक घंटे के लिए"</item> <item quantity="other" msgid="5408537517529822157">"%d घंटे के लिए"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"अनिश्चित समय तक"</string> </resources> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index 74b6a7a757fc..1a4af08e2355 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"izmjena vaše kontaktne kartice"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Aplikaciji omogućuje promjenu ili dodavanje osobnih podataka profila pohranjenih na uređaju, kao što su vaše ime i kontaktni podaci. To znači da vas aplikacija može identificirati i slati informacije s vašeg profila drugima."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"senzori tjelesnih funkcija (npr. monitori otkucaja srca)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Aplikaciji omogućuje pristup podacima iz senzora koje upotrebljavate za mjerenje onoga što se odvija u vašem tijelu, poput otkucaja srca."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Omogućuje aplikaciji pristup podacima sa senzora koji nadziru vaše fizičko stanje, na primjer, broj otkucaja srca."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"čitanje društvenog streama"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Aplikaciji omogućuje pristup vašim ažuriranjima na društvenim mrežama i ažuriranjima vaših prijatelja, kao i sinkronizaciju tih ažuriranja. Budite oprezni kad dijelite informacije – to aplikaciji omogućuje čitanje poruka između vas i vaših prijatelja na društvenim mrežama, neovisno o povjerljivosti. Napomena: ta se dozvola možda ne primjenjuje na svim društvenim mrežama."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"pisanje društvenog streama"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Aplikaciji omogućuje čitanje i pisanje u datotečnom sustavu privremene memorije."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"upućivanje/primanje SIP poziva"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Aplikacija može upućivati i primati SIP pozive."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"registriranje novih telekomunikacijskih veza"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Aplikaciji omogućuje registriranje novih telekomunikacijskih veza."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"upravljanje telekomunikacijskim vezama"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Aplikaciji omogućuje upravljanje telekomunikacijskim vezama."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interakcija sa zaslonom tijekom poziva"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Omogućuje aplikaciji upravljanje vremenom i načinom na koji se korisniku prikazuje zaslon tijekom poziva."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"interakcija s telefonskim uslugama"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Pokušajte ponovo"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Pokušajte ponovo"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Premašen je maksimalni broj Otključavanja licem"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Punjenje, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Napunjeno"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Priključite punjač."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Nema SIM kartice"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"U tabletnom uređaju nema SIM kartice."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"U telefonu nema SIM kartice."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Traži zaporku radi otkvačivanja"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Da bi se produljilo trajanje baterije, ušteda baterije smanjuje rad uređaja i ograničava vibraciju i većinu pozadinskih podataka. Aplikacije za e-poštu, slanje poruka i ostalo koje se oslanjaju na sinkronizaciju možda se neće ažurirati ako ih ne otvorite.\n\nUšteda baterije isključuje se automatski dok se uređaj puni."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Dok razdoblje zastoja ne završi u <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Jednu minutu"</item> <item quantity="other" msgid="6924190729213550991">"%d min"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Jedan sat"</item> <item quantity="other" msgid="5408537517529822157">"%d h"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Neodređeno"</string> </resources> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index 6e6758741aa1..87be17493a22 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"saját névjegykártya módosítása"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Lehetővé teszi az alkalmazás számára az eszközön tárolt személyes profiladatok, például a név és az elérhetőségek módosítását vagy hozzáadását. Ez azt jelenti, hogy az alkalmazás azonosíthatja Önt, és elküldheti másoknak profiladatait."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"testérzékelők (pl. pulzusmérő)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Lehetővé teszi, hogy az alkalmazás hozzáférjen az olyan érzékelők által észlelt adatokhoz, amelyek az Ön életfunkcióit – például a pulzusszámát – figyelik."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Engedélyezi az alkalmazásnak, hogy hozzáférjen az Ön fizikai állapotát – például a pulzusszámát – figyelő érzékelők adataihoz."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"közösségi adatfolyam olvasása"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Lehetővé teszi az alkalmazás számára, hogy hozzáférjen az Ön és ismerősei közösségi oldalakon szereplő frissítéseihez. Legyen elővigyázatos, amikor információt tesz közzé -- így az alkalmazás hozzáférhet az ismerőseivel a közösségi hálózatokon folytatott magánbeszélgetésekhez, a tartalom titkos jellegétől függetlenül. Megjegyzés: előfordulhat, hogy ez nincs minden közösségi hálózaton engedélyezve."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"írás a közösség adatfolyamra"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Lehetővé teszi az alkalmazás számára a gyorsítótár-fájlrendszer olvasását és írását."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP-hívások indítása/fogadása"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"SIP-hívások indításának és fogadásának engedélyezése az alkalmazás számára."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"új telekommunikációs kapcsolatok regisztrálása"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Engedélyezi az alkalmazásnak új telekommunikációs kapcsolatok regisztrálását."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"telekommunikációs kapcsolatok kezelése"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Engedélyezi az alkalmazásnak a telekommunikációs kapcsolatok kezelését."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interakció a hívás közbeni képernyővel"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Lehetővé teszi, hogy az alkalmazás felügyelje, a felhasználók mikor és hogyan láthatják a hívás közbeni képernyőt."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"együttműködés a telefonos szolgáltatásokkal"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Próbálja újra"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Újra"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Elérte az arcalapú feloldási kísérletek maximális számát"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Töltés (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Feltöltve"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Csatlakoztassa a töltőt."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Nincs SIM kártya."</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nincs SIM kártya a táblagépben."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Nincs SIM kártya a telefonban."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Jelszó kérése a rögzítés feloldásához"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Az akkumulátor üzemidejének növeléséhez az akkumulátorkímélő mód csökkenti az eszköz teljesítményét, valamint korlátozza a rezgést és a legtöbb háttéradatot. Előfordulhat, hogy az e-mailek, az üzenetküldő programok és más alkalmazások, amelyek a szinkronizálás funkciót használják, nem frissülnek addig, amíg meg nem nyitja őket.\n\nAz akkumulátorkímélő mód automatikusan kikapcsol, amikor az eszköz töltődik."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Amíg az állásidő véget nem ér ekkor: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Egy percen át"</item> <item quantity="other" msgid="6924190729213550991">"%d percen át"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Egy órán át"</item> <item quantity="other" msgid="5408537517529822157">"%d órán át"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Határozatlan ideig"</string> </resources> diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml index d4bf79fb858b..1ab805edcd2b 100644 --- a/core/res/res/values-hy-rAM/strings.xml +++ b/core/res/res/values-hy-rAM/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"փոփոխել ձեր սեփական կոնտակտային քարտը"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Թույլ է տալիս հավելվածին փոխել կամ ավելացնել ձեր սարքում պահված անհատական պրոֆիլի տվյալները, ինչպիսիք են ձեր անունը և կոնտակտային տվյալները: Սա նշանակում է, որ հավելվածը կարող է ձեզ ճանաչել և ուղարկել ձեր պրոֆիլի տվյալները ուրիշներին:"</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"մարմնի սենսորներ (օր.` սրտի)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Ծրագրին թույլ է տալիս մատչել ձեր կողմից օգտագործվող սենսորների տվյալները՝ չափելու, թե ինչ է տեղի ունենում ձեր մարմնի ներսում, ինչպես օրինակ՝ սրտի զարկերը:"</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Հավելվածին թույլ է տալիս մուտք ունենալ սենսորների տվյալներին, որոնք վերահսկում են ձեր ֆիզիկական վիճակը, օրինակ՝ ձեր սրտի զարկերը:"</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"կարդալ ձեր սոցիալական հոսքը"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Թույլ է տալիս հավելվածին մուտք գործել և համաժամեցնել ձեր և ձեր ընկերների սոցիալական թարմացումները: Զգույշ եղեք տեղեկություններ տարածելիս. այն թույլ է տալիս հավելվածին կարդալ ձեր և ձեր ընկերների միջև անձնական հաղորդագրությունները սոցիալական ցանցերում` անկախ գաղտնիությունից: Նշում. այս թույլտվությունը չի կարող գործածվել բոլոր սոցիալական ցանցերում:"</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"գրել ձեր սոցիալական հոսքում"</string> @@ -716,6 +716,14 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Թույլ է տալիս հավելվածին գրել և կարդալ քեշ ֆայլային համակարգը:"</string> <string name="permlab_use_sip" msgid="2052499390128979920">"կատարել կամ ստանալ SIP զանգեր"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Ծրագրին թույլ է տալիս կատարել և ստանալ SIP զանգեր:"</string> + <!-- no translation found for permlab_register_provider (2654513709546459553) --> + <skip /> + <!-- no translation found for permdesc_register_provider (7571533832018681544) --> + <skip /> + <!-- no translation found for permlab_connection_manager (1116193254522105375) --> + <skip /> + <!-- no translation found for permdesc_connection_manager (5925480810356483565) --> + <skip /> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"փոխազդել մուտքային զանգի էկրանին"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Թույլ է տալիս ծրագրին վերահսկել՝ երբ և ինչպես է օգտվողը տեսնում մուտքային զանգը էկրանին:"</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"համագործակցել հեռախոսակապի ծառայությունների հետ"</string> @@ -905,10 +913,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Կրկին փորձեք"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Կրկին փորձեք"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Առավելագույն Դեմքով ապակողպման փորձերը գերազանցված են"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Լիցքավորում, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Լիցքավորված է"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Միացրեք ձեր լիցքավորիչը:"</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM քարտ չկա"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Գրասալիկում SIM քարտ չկա:"</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Հեռախոսում SIM քարտ չկա:"</string> @@ -1776,6 +1780,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ապաամրացնելուց առաջ հարցնել գաղտնաբառը"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Մարտկոցի աշխատաժամանակը շատացնելու համար մարտկոցի տնտեսումը կնվազեցնի ձեր սարքի կատարողականը և կսահմանափակի թրթռոցն ու ֆոնային տվյալներից շատերը: Էլփոստը, հաղորդագրությունները և այլ ծրագրերը, որոնք օգտագործում են համաժամեցումը, կթարմանան միայն դրանք աշխատեցնելիս:\n\nՄարկտոցի տնտեսումը ավտոմատ կանջատվի, հենց սարքը միացվի լիցքավորման:"</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Մինչև ձեր ժամանակն ավարտվի ժամը <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Մեկ րոպե"</item> <item quantity="other" msgid="6924190729213550991">"%d րոպե"</item> @@ -1784,5 +1792,7 @@ <item quantity="one" msgid="3480040795582254384">"Մեկ ժամ"</item> <item quantity="other" msgid="5408537517529822157">"%d ժամ"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Անորոշ ժամանակով"</string> </resources> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index b58bcc6b44ce..d80c2bdf2e72 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"ubah kartu kontak Anda"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Memungkinkan aplikasi mengubah atau menambah informasi profil pribadi yang tersimpan di perangkat Anda, seperti nama dan informasi kontak. Ini berarti aplikasi tersebut dapat mengenali Anda dan mengirim informasi profil Anda ke orang lain."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"sensor tubuh (misal: monitor detak jantung)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Memungkinkan aplikasi mengakses data dari sensor yang Anda gunakan untuk mengukur yang terjadi di dalam tubuh, misalnya detak jantung."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Mengizinkan aplikasi untuk mengakses data dari sensor yang memantau kondisi fisik Anda, seperti denyut jantung."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"membaca aliran sosial Anda"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Memungkinkan aplikasi mengakses dan menyinkronkan pembaruan sosial dari Anda dan teman. Hati-hati ketika berbagi informasi -- izin ini memungkinkan aplikasi membaca komunikasi antara Anda dan teman di jejaring sosial, terlepas dari kerahasiaan. Catatan: izin ini tidak dapat diberlakukan di semua jejaring sosial."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"menulis ke aliran sosial Anda"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Mengizinkan apl membaca dan menulis pada sistem file cache."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"lakukan/terima panggilan SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Izinkan aplikasi melakukan dan menerima panggilan SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"daftarkan sambungan telekomunikasi baru"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Mengizinkan aplikasi untuk mendaftarkan sambungan telekomunikasi baru."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"kelola sambungan telekomunikasi"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Mengizinkan aplikasi untuk mengelola sambungan telekomunikasi."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"berinteraksi dengan layar dalam panggilan"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Memungkinkan aplikasi mengontrol kapan dan bagaimana pengguna melihat layar dalam panggilan."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"berinteraksi dengan layanan telepon"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Coba lagi"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Coba lagi"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Percobaan Face Unlock melebihi batas maksimum"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Mengisi daya, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Terisi"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Hubungkan pengisi daya."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Tidak ada kartu SIM"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tidak ada kartu SIM dalam tablet."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Tidak ada Kartu SIM di dalam ponsel."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Meminta sandi sebelum melepas sematan"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Guna membantu meningkatkan masa pakai baterai, penghemat baterai mengurangi kinerja perangkat dan membatasi getaran serta sebagian besar data latar belakang. Email, perpesanan, dan aplikasi lain yang bergantung pada sinkronisasi mungkin tidak akan diperbarui kecuali Anda membukanya.\n\nPenghemat baterai dinonaktifkan secara otomatis saat perangkat diisi daya."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Hingga waktu perbaikan Anda berakhir pukul <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Selama satu menit"</item> <item quantity="other" msgid="6924190729213550991">"Selama %d menit"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Selama satu jam"</item> <item quantity="other" msgid="5408537517529822157">"Selama %d jam"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Tidak ditentukan"</string> </resources> diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml index 64fd266acb42..2b2415446d7e 100644 --- a/core/res/res/values-is-rIS/strings.xml +++ b/core/res/res/values-is-rIS/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"breyta tengiliðaspjaldinu þínu"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Leyfir forriti að breyta eða bæta við persónulegum prófílupplýsingum sem vistaðar eru í tækinu, t.d. nafni og samskiptaupplýsingum. Þetta þýðir að forritið veit hver þú ert og getur sent prófílupplýsingarnar þínar til annarra."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"líkamsskynjarar (s.s. hjartsláttarmælar)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Leyfir forriti að fá aðgang að gögnum frá skynjurum sem þú notar til að mæla líkamsstarfsemi þína, svo sem hjartslátt."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Veitir forritinu aðgang að gögnum frá skynjurum sem fylgjast með líkamsstarfsemi þinni, svo sem hjartslætti."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"lesa samfélagsstrauminn þinn"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Leyfir forriti að fá aðgang að og samstilla samfélagsuppfærslur þínar og vina þinna. Sýndu aðgát þegar þú deilir upplýsingum; þetta gerir forritinu kleift að lesa samskipti þín og vina þinna í netsamfélögum. Athugaðu: Ekki er víst að þessi heimild sé virt í öllum netsamfélögum."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"skrifa í samfélagsstrauminn þinn"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Leyfir forriti að lesa og skrifa í skráakerfi skyndiminnis."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"hringja/svara SIP-símtölum"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Leyfir forritinu að hringja og svara SIP-símtölum."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"skrá nýjar símatengingar"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Leyfir forritinu að skrá nýjar símatengingar."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"stjórna símatengingum"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Leyfir forritinu að stjórna símatengingum."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"eiga samskipti við símtalsskjá"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Leyfir forriti að stjórna því hvenær og hvernig notandi sér símtalsskjá."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"hafa samskipti við símafyrirtæki"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Reyndu aftur"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Reyndu aftur"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Hámarksfjölda tilrauna til að opna með andliti náð"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Í hleðslu, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Fullhlaðið"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Tengdu hleðslutækið."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Ekkert SIM-kort"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Ekkert SIM-kort í spjaldtölvunni."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Ekkert SIM-kort í símanum."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Biðja um aðgangsorð til að losa"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Til að auka endingu rafhlöðunnar dregur rafhlöðusparnaður úr afköstum tækisins og takmarkar titring og flest bakgrunnsgögn. Ekki er víst að tölvupóstur, skilaboð og önnur forrit sem reiða sig á samstillingu verði uppfærð fyrr en þú opnar þau.\n\nSjálfkrafa er slökkt á rafhlöðusparnaði þegar tækið er í hleðslu."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Þangað til niðritíma lýkur, <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Í eina mínútu"</item> <item quantity="other" msgid="6924190729213550991">"Í %d mínútur"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Í eina klukkustund"</item> <item quantity="other" msgid="5408537517529822157">"Í %d klukkustundir"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Án tímatakmarkana"</string> </resources> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index d47f9edcc278..69b76048e605 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"modifica scheda contatti"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Consente all\'applicazione di modificare o aggiungere informazioni ai dati del profilo personale memorizzati sul dispositivo, come il tuo nome e le tue informazioni di contatto. Significa che l\'applicazione può identificarti e inviare le informazioni del tuo profilo ad altri."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"sensori per il corpo (come il cardiofrequenzimetro)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Consente all\'app di accedere a dati derivanti dai sensori utilizzati per rilevare cosa sta accadendo nel tuo corpo, ad esempio la frequenza cardiaca."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Consente all\'app di accedere ai dati relativi ai sensori che monitorano le tue condizioni fisiche, ad esempio la frequenza cardiaca."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"lettura del tuo stream sociale"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Consente all\'applicazione di accedere agli aggiornamenti dei social network tra te e i tuoi amici e di sincronizzarli. Fai attenzione quando condividi informazioni: questa autorizzazione consente all\'applicazione di leggere le comunicazioni tra te e i tuoi amici sui social network, indipendentemente dal livello di riservatezza. Nota. È possibile che questa autorizzazione non sia applicabile su tutti i social network."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"scrittura nel tuo stream sociale"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Consente all\'applicazione di leggere e scrivere il filesystem nella cache."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"fare/ricevere chiamate SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Consente all\'app di effettuare e ricevere chiamate SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"registra nuova connessione di telecomunicazione"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Consente all\'app di registrare nuove connessioni di telecomunicazione."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"gestisci connessioni di telecomunicazione"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Consente all\'app di gestire connessioni di telecomunicazione."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interazione con lo schermo durante una chiamata"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Consente all\'app di stabilire quando e come l\'utente vede lo schermo durante una chiamata."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"interagire con i servizi di telefonia"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Riprova"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Riprova"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Numero massimo di tentativi di Sblocco col sorriso superato"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"In carica (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Carica"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Collegare il caricabatterie."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Nessuna scheda SIM"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nessuna scheda SIM presente nel tablet."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Nessuna SIM presente nel telefono."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Richiedi password prima di sbloccare"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Per aumentare la durata della batteria, la funzione Risparmio energetico riduce le prestazioni del dispositivo e limita vibrazione e gran parte dei dati in background. App di email, messaggi e altre app basate sulla sincronizzazione potrebbero non essere aggiornate se non le apri.\n\nIl risparmio energetico si disattiva automaticamente quando il dispositivo è in carica."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Fino al termine del periodo di inattività previsto per le <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Per un minuto"</item> <item quantity="other" msgid="6924190729213550991">"Per %d minuti"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Per un\'ora"</item> <item quantity="other" msgid="5408537517529822157">"Per %d ore"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Sempre"</string> </resources> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 45f290fe27fc..6a41a47da87f 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"שינוי כרטיס איש הקשר שלך"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"מאפשר לאפליקציה לשנות או להוסיף נתונים לפרטי הפרופיל האישי המאוחסנים במכשיר, כגון שמך ופרטי הקשר שלך. משמעות הדבר שהאפליקציה יכולה לזהות אותך ועשוי לשלוח את פרטי הפרופיל שלך לאנשים אחרים."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"חיישני גוף (כמו מוניטורים עבור קצב לב)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"מאפשר לאפליקציה לגשת לנתוני חיישנים שבהם אתה משתמש כדי למדוד פעילות המתרחשת בתוך הגוף, כמו קצב לב."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"מאפשר לאפליקציה לגשת אל נתוני חיישנים העוקבים אחר מצבך הגופני, כמו קצב הלב."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"קריאת הזרם החברתי שלך"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"מאפשר לאפליקציה גישה ויכולת סנכרון של עדכונים חברתיים שאתה וחבריך מבצעים. היזהר בעת שיתוף מידע -- הדבר מתיר לאפליקציה לקרוא התכתבויות בינך ובין חבריך ברשתות חברתיות, ללא התחשבות בסודיות. שים לב: ייתכן שאישור זה לא נאכף בכל הרשתות החברתיות."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"כתיבה בזרם החברתי שלך"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"מאפשר לאפליקציה לקרוא ולכתוב במערכת הקבצים של הקבצים השמורים."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"ביצוע/קבלה של שיחות SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"אפשר לאפליקציה לבצע ולקבל שיחות SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"רישום של חיבור תקשורת חדש"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"מאפשר לאפליקציה לרשום חיבורי תקשורת חדשים."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"ניהול חיבורי תקשורת"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"מאפשר לאפליקציה לנהל חיבורי תקשורת."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"צור אינטראקציה עם מסך שיחה נכנסת"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"מאפשר לאפליקציה לקבוע מתי ואיך המשתמש יראה את מסך השיחה הנכנסת."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"צור אינטראקציה עם שירותי טלפוניה"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"נסה שוב"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"נסה שוב"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"חרגת ממספר הניסיונות המרבי של זיהוי פנים"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"טוען (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"טעון"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"חבר את המטען."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"אין כרטיס SIM"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"אין כרטיס SIM בטאבלט."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"אין כרטיס SIM בטלפון."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"בקש סיסמה לפני ביטול הצמדה"</string> <string name="battery_saver_description" msgid="2510530476513605742">"כדי לעזור בהארכת חיי הסוללה, תכונת \'חיסכון בסוללה\' מצמצמת את פעילות המכשיר ומגבילה את השימוש ברטט וברוב נתוני הרקע. ייתכן שאימייל, שליחת הודעות ואפליקציות אחרות המסתמכות על סנכרון לא יתעדכנו, אלא אם תפתח אותן.\n\nתכונת \'חיסכון בסוללה\' מופסקת אוטומטית כשהמכשיר מחובר לחשמל."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"עד לסיום ההשבתה בשעה <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"למשך דקה אחת"</item> <item quantity="other" msgid="6924190729213550991">"למשך %d דקות"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"למשך שעה אחת"</item> <item quantity="other" msgid="5408537517529822157">"למשך %d שעות"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"ללא הגבלה"</string> </resources> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index fec3dd29d031..254c7f357071 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"自分の連絡先カードの変更"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"端末に保存されている個人のプロフィール情報(名前、連絡先情報など)の変更と追加をアプリに許可します。これにより、アプリがユーザーの身元を特定できるようになり、プロフィール情報を第三者に転送する可能性があります。"</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"ボディーセンサー(心拍数モニターなど)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"心拍数など、体内の変化の測定に使用するセンサーからのデータにアクセスすることをアプリに許可します。"</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"心拍数など、身体状態を監視するセンサーからのデータにアクセスすることをアプリに許可します。"</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"ソーシャルストリームを読む"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"あなたや友だちのソーシャル更新情報へのアクセスと同期をアプリに許可します。情報の共有は慎重に行ってください。これを許可すると、あなたと友だちがソーシャルネットワークで行ったやり取りを、機密性に関係なくアプリから読み取ることができるようになります。注: この許可は、一部のソーシャルネットワークでは適用されない場合があります。"</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"ソーシャルストリームに書く"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"キャッシュファイルシステムの読み書きをアプリに許可します。"</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP通話の発着信"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"SIP通話の発着信をアプリに許可します。"</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"新しい通信接続の登録"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"新しい通信接続の登録をアプリに許可します。"</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"通信接続の管理"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"通信接続の管理をアプリに許可します。"</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"通話画面とのインタラクション"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"通話画面をユーザーに表示するタイミングと方法の制御をアプリに許可します。"</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"電話サービスとの通信"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"もう一度お試しください"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"もう一度お試しください"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"フェイスアンロックの最大試行回数を超えました"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"充電しています: <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"充電完了"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"充電してください"</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIMカードが挿入されていません"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"タブレット内にSIMカードがありません。"</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"SIMカードが挿入されていません"</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"オフライン再生を解除する前にパスワードの入力を求める"</string> <string name="battery_saver_description" msgid="2510530476513605742">"バッテリーを長持ちさせるため、バッテリーセーバーは端末のパフォーマンス、バイブレーション、ほとんどのバックグラウンドデータを制限します。同期を使用するメールやメッセージなどのアプリは起動しないと更新されない場合があります。\n\nバッテリーセーバーは、端末の充電中は自動的にOFFになります。"</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>にダウンロードが終わるまで"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"1分"</item> <item quantity="other" msgid="6924190729213550991">"%d分"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"1時間"</item> <item quantity="other" msgid="5408537517529822157">"%d時間"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"制限なし"</string> </resources> diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml index 754ccdf7b70b..d45fb04799a7 100644 --- a/core/res/res/values-ka-rGE/strings.xml +++ b/core/res/res/values-ka-rGE/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"თქვენი საკონტაქტო ინფორმაციის შეცვლა"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"აპს შეეძლება მოწყობილობაზე შენახული პირადი პროფილის ინფორმაციის შეცვლა ან დამატება, მაგალითად, თქვენი სახელისა და საკონტაქტო ინფორმაციის. ეს ნიშნავს, რომ აპს შეუძლია თქვენი იდენტიფიცირება და თქვენი პირადი ინფორმაციის სხვებისთვის გაგზავნა."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"სხეულის სენსორები (მაგ. გულისცემის მონიტორები)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"საშუალებას აძლევს აპს იქონიოს წვდომა თქვენ მიერ გამოყენებული სენსორებიდან, რათა გაზომოთ, რა ხდება თქვენ სხეულში, მაგ. გულის ცემის რითმი."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"აპისთვის ნების დართვა, რათა მას ჰქონდეს წვდომა თქვენი ფიზიკური მდგომარეობის მონიტორინგის სენსორების მონაცემებზე."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"სოციალური ნაკადის წაკითხვა"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"აპს შეეძლება თქვენი და თქვენი მეგობრების სოციალური განახლებებთან წვდომა და სინქრონიზაცია. ინფორმაციის გაზიარებისას იყავით ფრთხიად - აპს ექნება შესაძლებლობა, რომ წაიკითხოს სოციალურ ქსელებში კომუნიკაცია თქვენსა და თქვენს მეგობრებს შორის კონფიდენციალურობის მიუხედავად. შენიშვნა: ეს უფლება შესაძლოა ვერ იყოს გამოყენებული ყველა სოციალურ ქსელში."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"თქვენს სოციალურ მაუწყებლობაზე დაწერა"</string> @@ -716,6 +716,14 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"აპებს აძლევს ქეშირებული სისტემური ფაილების წაკითხვისა და მათში ჩანაწერების გაკეთების საშუალებას."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP ზარების წამოწყება/მიღება"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"ნებას რთავს აპს განახორციელოს და მიიღოს SIP ზარები."</string> + <!-- no translation found for permlab_register_provider (2654513709546459553) --> + <skip /> + <!-- no translation found for permdesc_register_provider (7571533832018681544) --> + <skip /> + <!-- no translation found for permlab_connection_manager (1116193254522105375) --> + <skip /> + <!-- no translation found for permdesc_connection_manager (5925480810356483565) --> + <skip /> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"ინტერაქცია საუბრის რეჟიმის ეკრანთან"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"აპს შეეძლება გაკონტროლება, როდის და როგორ დაინახავს მომხმარებელი საუბრის რეჟიმის ეკრანს."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"ტელეფონიის სერვისებთან ინტერაქცია"</string> @@ -905,10 +913,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"კიდევ სცადეთ"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"კიდევ სცადეთ"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"სახის ამოცნობით განბლოკვის მცდელობამ დაშვებულ რაოდენობას გადააჭარბა"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"დამუხტვა, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"დამუხტულია"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"შეაერთეთ დამტენი."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM ბარათი არ არის"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ტაბლეტში არ დევს SIM ბარათი."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"არ არის SIM ბარათი ტელეფონში."</string> @@ -1776,6 +1780,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ფიქსაციის მოხსნამდე პაროლის მოთხოვნა"</string> <string name="battery_saver_description" msgid="2510530476513605742">"ბატარეის გამძლეობის გასახანგრძლივებლად, ბატარეის დამზოგი ამცირებს თქვენი მოწყობილობის წარმადობას და ზღუდავს ვიბრაციასა და უმეტეს ფონურ მონაცემს. თუ არ განაახლებთ, შეიძლება არ გაიხსნას ელფოსტა, შეტყობინებები და სხვა აპები, რომლებიც სინქრონიზაციაზეა დამოკიდებული.\n\nბატარეის დამზოგი ავტომატურად გამოირთვება, როდესაც თქვენი მოწყობილობა იტენება."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"დანამ თქვენი კავშირგარეშე დრო დასრულდებოდეს <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-ზე"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"ერთი წუთით"</item> <item quantity="other" msgid="6924190729213550991">"%d წუთით"</item> @@ -1784,5 +1792,7 @@ <item quantity="one" msgid="3480040795582254384">"ერთი საათით"</item> <item quantity="other" msgid="5408537517529822157">"%d საათით"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"სამუდამოდ"</string> </resources> diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml index 2988201b4e23..7402cc1908d5 100644 --- a/core/res/res/values-kk-rKZ/strings.xml +++ b/core/res/res/values-kk-rKZ/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"өзіңіздің байланыс картаңызды өзгерту"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Қолданбаға құрылғыда сақталған сіздің аты-жөніңіз және байланыс ақпаратыңыз сияқты жеке ақпаратты өзгерту немесе қосу мүмкіндігін береді. Бұл - қолданба сізді анықтап, сіз туралы жеке ақпаратты басқаларға жібере алады дегенді білдіреді."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"дене сен-ры (жүрек соғу жиіл. мон-ры сияқты)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Қолданбаларға сіз жүрек соғу жиілігі сияқты дене ішінде болып жатқан нәрселерді өлшеу үшін пайдаланатын сенсорлардан алынған деректерге қатынасуға рұқсат береді."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Қолданбаға жүрек соғу жиілігіңіз сияқты дене күйіңізді бақылайтын сенсорлардың деректеріне қатынасуға рұқсат етеді."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"әлеуметтік ағымды оқу"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Қолданбаға сіз және достарыңыздың әлеуметтік жаңартуларына кіру және синхрондау мүмкіндігін береді. Ақпарат бөліскенде абай болыңыз -- бұл қолданбаға сіз және достарыңызды әлеуметтік желілердегі қарым-қатынасты, құпиялығына қарамастан, оқу мүмкіндігін берді. Есіңізде болсын: бұл рұқсатты барлық әлеуметтік желілер қолданбайды."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"әлеуметтік ағынға жазу"</string> @@ -716,6 +716,14 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Қолданбаға кэш файлдық жүйесін оқуға және оған жазуға рұқсат береді."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP қоңырауларын шалу/қабылдау"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Қолданбаға SIP қоңырауларын шалуға және қабылдауға рұқсат етеді."</string> + <!-- no translation found for permlab_register_provider (2654513709546459553) --> + <skip /> + <!-- no translation found for permdesc_register_provider (7571533832018681544) --> + <skip /> + <!-- no translation found for permlab_connection_manager (1116193254522105375) --> + <skip /> + <!-- no translation found for permdesc_connection_manager (5925480810356483565) --> + <skip /> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"қоңыраудағы экранмен өзара әрекеттесу"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Қолданбаға пайдаланушының қоңырау кезінде экранды қашан және қалай көретінін басқару мүмкіндігін береді."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"телефония қызметтерімен өзара әрекеттесу"</string> @@ -905,10 +913,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Әрекетті қайталау"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Әрекетті қайталау"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Бет-әлпет арқылы ашу әрекеттері анықталған шегінен асып кетті"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Зарядтауда, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Зарядталған"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Зарядтағышты қосыңыз."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM картасы жоқ"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Планшетте SIM картасы жоқ."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Телефонда SIM картасы жоқ."</string> @@ -1776,6 +1780,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Босату алдында құпия сөзді сұрау"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Батареяның қызмет мерзімін жақсарту үшін батарея үнемдегіш құрылғының өнімділігін азайтады және діріл мен фондық деректердің көпшілігін шектейді. Синхрондауды қажет ететін электрондық пошта, хабар алмасу және басқа қолданбалар ашқанша жаңартылмауы мүмкін.\n\nБатарея үнемдегіш құрылғы зарядталып жатқанда автоматты түрде өшеді."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> уақытында әрекетсіздік аяқталғанша"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Бір минут бойы"</item> <item quantity="other" msgid="6924190729213550991">"%d минут бойы"</item> @@ -1784,5 +1792,7 @@ <item quantity="one" msgid="3480040795582254384">"Бір сағат бойы"</item> <item quantity="other" msgid="5408537517529822157">"%d сағат бойы"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Белгісіз уақыт бойы"</string> </resources> diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml index a9482aa6941e..b6e5c287dce1 100644 --- a/core/res/res/values-km-rKH/strings.xml +++ b/core/res/res/values-km-rKH/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"កែកាតទំនាក់ទំនងផ្ទាល់ខ្លួនរបស់អ្នក"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"ឲ្យកម្មវិធីប្ដូរ ឬបន្ថែមព័ត៌មានប្រវត្តិរូបផ្ទាល់ខ្លួនដែលបានរក្សាទុកក្នុងឧបករណ៍របស់អ្នក ដូចជា ឈ្មោះ និងព័ត៌មានទំនាក់ទំនងរបស់អ្នក។ នេះមានន័យថាកម្មវិធីអាចកំណត់អ្នក និងផ្ញើព័ត៌មានប្រវត្តិរូបរបស់អ្នកទៅអ្នកផ្សេង។"</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"ឧបករណ៍ចាប់សញ្ញារាងកាយ(ដូចជាម៉ាស៊ីនវាស់ចង្វាក់បេះដូង)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"ឲ្យកម្មវិធីដើម្បីចូលដំណើរការទិន្នន័យពីឧបករណ៍ចាប់សញ្ញាដែលអ្នកប្រើ ដើម្បីវាស់ពីអ្វីដែលកំពុងកើតឡើងនៅខាងក្នុងខ្លួនរបស់អ្នកដូចជាចង្វាក់បេះដូង។"</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"ឲ្យកម្មវិធីចូលដំណើរការទិន្នន័យពីឧបករណ៍ចាប់សញ្ញាដែលតាមដានលក្ខខណ្ឌសុខភាពរបស់អ្នក ដូចជាចង្វាក់បេះដូង។"</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"អានចរន្តសង្គមរបស់អ្នក"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"ឲ្យកម្មវិធីចូលដំណើរការ និងធ្វើសមកាលកម្មបច្ចុប្បន្នភាពសង្គមពីអ្នក និងមិត្តភ័ក្ដិ។ ប្រយ័ត្នពេលចែករំលែកព័ត៌មាន វាអនុញ្ញាតឲ្យកម្មវិធីអានការទាក់ទងរវាងអ្នក និងមិត្តភ័ក្ដិលើបណ្ដាញសង្គម ទាក់ទងនឹងព័ត៌មានសម្ងាត់។ ចំណាំ៖ សិទ្ធិនេះមិនអាចត្រូវបានអនុវត្តលើបណ្ដាញសង្គមទាំងអស់បានទេ។"</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"សរសេរទៅចរន្តសង្គមរបស់អ្នក"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"ឲ្យកម្មវិធីអាន និងសរសេរប្រព័ន្ធឯកសារឃ្លាំងសម្ងាត់។"</string> <string name="permlab_use_sip" msgid="2052499390128979920">"បង្កើត/ទទួល ការហៅ SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"ឲ្យកម្មវិធី បង្កើត និងទទួលការហៅ SIP ។"</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"ចុះឈ្មោះភ្ជាប់ទូរគមនាគមន៍ថ្មី"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"ឲ្យកម្មវិធីចុះឈ្មោះការភ្ជាប់ទូរគមនាគមន៍ថ្មី។"</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"គ្រប់គ្រងការភ្ជាប់ទូរគមនាគមន៍"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"ឲ្យកម្មវិធីគ្រប់គ្រងការភ្ជាប់ទូរគមនាគមន៍។"</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"ទាក់ទងជាមួយអេក្រង់ហៅចូល"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ឲ្យកម្មវិធីពិនិត្យពេលវេលា និងវិធីដែលអ្នកប្រើមើលឃើញអេក្រង់ហៅចូល។"</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"ទាក់ទងជាមួយសេវាកម្មទូរស័ព្ទ"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"ព្យាយាមម្ដងទៀត"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"ព្យាយាមម្ដងទៀត"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"បានលើសការព្យាយាមដោះសោតាមទម្រង់មុខ"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"បញ្ចូលថ្ម <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"បានបញ្ចូលពេញ។"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"ភ្ជាប់ឧបករណ៍បញ្ចូលថ្ម។"</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"គ្មានស៊ីមកាត"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"គ្មានស៊ីមកាតក្នុងកុំព្យូទ័របន្ទះ។"</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"គ្មានស៊ីមកាតក្នុងទូរស័ព្ទ។"</string> @@ -1778,6 +1778,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"សួររកពាក្យសម្ងាត់មុនពេលផ្ដាច់"</string> <string name="battery_saver_description" msgid="2510530476513605742">"ដើម្បីបង្កើនអាយុថ្ម កម្មវិធីសន្សំថ្មកាត់បន្ថយការអនុវត្តឧបករណ៍របស់អ្នក ហើយកម្រិតការញ័រ និងទិន្នន័យផ្ទៃខាងក្រោយ។ អ៊ីមែល, ការផ្ញើសារ និងកម្មវិធីផ្សេងៗទៀតដែលផ្អែកលើការធ្វើសមកាលកម្មមិនអាចធ្វើបច្ចុប្បន្នភាពលុះត្រាតែអ្នកបើកពួកវា។\n\nកម្មវិធីសន្សំថ្មបិទដោយស្វ័យប្រវត្តិពេលឧបករណ៍របស់អ្នកកំពុងបញ្ចូលថ្ម។"</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"រហូតដល់ម៉ោងសម្រាក ឬរវល់របស់អ្នកបញ្ចប់នៅ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"សម្រាប់មួយនាទី"</item> <item quantity="other" msgid="6924190729213550991">"សម្រាប់ %d នាទី"</item> @@ -1786,5 +1790,7 @@ <item quantity="one" msgid="3480040795582254384">"សម្រាប់មួយម៉ោង"</item> <item quantity="other" msgid="5408537517529822157">"សម្រាប់ %d ម៉ោង"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"គ្មានកំណត់"</string> </resources> diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml index 65a50b0696f8..b23f82f2f61c 100644 --- a/core/res/res/values-kn-rIN/strings.xml +++ b/core/res/res/values-kn-rIN/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"ನಿಮ್ಮದೇ ಸಂಪರ್ಕದ ಕಾರ್ಡ್ ಮಾರ್ಪಡಿಸಿ"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗಿರುವ ನಿಮ್ಮ ಹೆಸರು ಹಾಗೂ ಸಂಪರ್ಕ ಮಾಹಿತಿಯಂತಹ, ವೈಯಕ್ತಿಕ ಪ್ರೊಫೈಲ್ ಮಾಹಿತಿಯನ್ನು ಬದಲಿಸಲು ಅಥವಾ ಸೇರಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಅಂದರೆ, ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮನ್ನು ಗುರುತಿಸಬಹುದು ಮತ್ತು ನಿಮ್ಮ ಪ್ರೊಫೈಲ್ ಮಾಹಿತಿಯನ್ನು ಇತರರಿಗೆ ಕಳುಹಿಸಬಹುದು ಎಂದರ್ಥ."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"ದೇಹದ ಸಂವೇದಗಳು (ಹೃದಯದ ರೇಟ್ ಮಾನಿಟರ್ಗಳಂತಹ)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"ಹೃದಯ ಬಡಿತದಂತಹ, ನಿಮ್ಮ ದೇಹದಲ್ಲಿ ಏನು ನಡೆಯುತ್ತಿದೆ ಎಂಬುದನ್ನು ಅಳತೆ ಮಾಡಲು ನೀವು ಬಳಸುವ ಸಂವೇದಕಗಳಿಂದ ಡೇಟಾ ಪ್ರವೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"ನಿಮ್ಮ ಹೃದಯ ಬಡಿತದಂತಹ ನಿಮ್ಮ ದೈಹಿಕ ಸ್ಥಿತಿಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡುವ ಸೆನ್ಸರ್ಗಳಿಂದ ಡೇಟಾ ಪ್ರವೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"ನಿಮ್ಮ ಸಾಮಾಜಿಕ ಸ್ಟ್ರೀಮ್ ಓದಿರಿ"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"ನೀವು ಮತ್ತು ನಿಮ್ಮ ಸ್ನೇಹಿತರ ಸಾಮಾಜಿಕ ನವೀಕರಣಗಳನ್ನು ಪ್ರವೇಶಿಸಲು ಮತ್ತು ಸಿಂಕ್ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಮಾಹಿತಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳುವಾಗ ಜಾಗರೂಕರಾಗಿರಿ -- ಇದು ಗೌಪ್ಯತೆಯನ್ನು ಲೆಕ್ಕಿಸದೆಯೇ, ಸಾಮಾಜಿಕ ನೆಟ್ವರ್ಕ್ಗಳಲ್ಲಿ ನೀವು ಮತ್ತು ನಿಮ್ಮ ಸ್ನೇಹಿತರ ನಡುವೆ ನಡೆದಿರುವ ಸಂವಹನವನ್ನು ಓದಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಗಮನಿಸಿ: ಈ ಅನುಮತಿಯನ್ನು ಎಲ್ಲಾ ಸಾಮಾಜಿಕ ನೆಟ್ವರ್ಕ್ಗಳಲ್ಲಿ ಜಾರಿಗೊಳಿಸದೇ ಇರಬಹುದು."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"ನಿಮ್ಮ ಸಾಮಾಜಿಕ ಸ್ಟ್ರೀಮ್ನಲ್ಲಿ ಬರೆಯಿರಿ"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"ಕ್ಯಾಷ್ ಫೈಲ್ ವ್ಯವಸ್ಥೆಯನ್ನು ಓದಲು ಮತ್ತು ಬರೆಯಲು ಅಪ್ಲಿಕೇಶನ್ ಅನುಮತಿಸುತ್ತದೆ."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP ಕರೆಗಳನ್ನು ಮಾಡಿ/ಸ್ವೀಕರಿಸಿ"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"SIP ಕರೆಗಳನ್ನು ಮಾಡಲು ಮತ್ತು ಸ್ವೀಕರಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"ಹೊಸ ಟೆಲಿಕಾಂ ಸಂಪರ್ಕವನ್ನು ನೋಂದಣಿ ಮಾಡಿ"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"ಹೊಸ ಟೆಲಿಕಾಂ ಸಂಪರ್ಕಗಳನ್ನು ನೋಂದಣಿ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"ಟೆಲಿಕಾಂ ಸಂಪರ್ಕಗಳನ್ನು ನಿರ್ವಹಿಸಿ"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"ಟೆಲಿಕಾಂ ಸಂಪರ್ಕಗಳನ್ನು ನಿರ್ವಹಿಸಲು ಅಪ್ಲಿಕೇಶನ್ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"ಒಳ-ಕರೆ ಪರದೆಯ ಮೂಲಕ ಸಂವಹನ ನಡೆಸಿ"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ಬಳಕೆದಾರರು ಒಳ-ಕರೆಯ ಪರದೆಯನ್ನು ಯಾವಾಗ ಮತ್ತು ಹೇಗೆ ನೋಡುತ್ತಾರೆ ಎಂಬುದನ್ನು ನಿಯಂತ್ರಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"ಟೆಲಿಫೋನಿ ಸೇವೆಗಳೊಂದಿಗೆ ಸಂವಾದ ನಡೆಸಿ"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸು"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸು"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"ಗರಿಷ್ಠ ಫೇಸ್ ಅನ್ಲಾಕ್ ಪ್ರಯತ್ನಗಳು ಮೀರಿವೆ"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"ನಿಮ್ಮ ಚಾರ್ಜರ್ಗೆ ಸಂಪರ್ಕಪಡಿಸಿ."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"ಯಾವುದೇ ಸಿಮ್ ಕಾರ್ಡ್ ಇಲ್ಲ"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ಟ್ಯಾಬ್ಲೆಟ್ನಲ್ಲಿ ಸಿಮ್ ಕಾರ್ಡ್ ಇಲ್ಲ."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ಫೋನ್ನಲ್ಲಿ ಸಿಮ್ ಕಾರ್ಡ್ ಇಲ್ಲ."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ಅನ್ಪಿನ್ ಮಾಡುವುದಕ್ಕೂ ಮೊದಲು ಪಾಸ್ವರ್ಡ್ ಕೇಳಿ"</string> <string name="battery_saver_description" msgid="2510530476513605742">"ಬ್ಯಾಟರಿ ಬಾಳಿಕೆಯನ್ನು ಹೆಚ್ಚಿಸುವ ನಿಟ್ಟಿನಲ್ಲಿ ಸಹಾಯ ಮಾಡಲು, ಬ್ಯಾಟರಿ ಉಳಿತಾಯವು ನಿಮ್ಮ ಸಾಧನದ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಕುಂಠಿತಗೊಳಿಸುತ್ತದೆ ಮತ್ತು ವೈಬ್ರೇಷನ್ ಹಾಗೂ ಹೆಚ್ಚಿನ ಹಿನ್ನೆಲೆ ಡೇಟಾವನ್ನು ಸೀಮಿತಗೊಳಿಸುತ್ತದೆ. ಇಮೇಲ್, ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆ, ಮತ್ತು ಸಿಂಕ್ ಮಾಡುವುದನ್ನು ಅವಲಂಬಿಸಿರುವ ಇತರ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ನೀವು ತೆರೆಯುವವರೆಗೆ ಅವುಗಳನ್ನು ನವೀಕರಿಸಲಾಗುವುದಿಲ್ಲ.\n\nನಿಮ್ಮ ಸಾಧನವು ಚಾರ್ಜ್ ಆಗುತ್ತಿರುವಾಗ ಬ್ಯಾಟರಿ ಉಳಿತಾಯವು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಆಫ್ ಆಗುತ್ತದೆ."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"ನಿಮ್ಮ ಅಲಭ್ಯತೆ ಕೊನೆಗೊಳ್ಳುವವರೆಗೆ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"ಒಂದು ನಿಮಿಷದವರೆಗೆ"</item> <item quantity="other" msgid="6924190729213550991">"%d ನಿಮಿಷಗಳವರೆಗೆ"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"ಒಂದು ಗಂಟೆಯವರೆಗೆ"</item> <item quantity="other" msgid="5408537517529822157">"%d ಗಂಟೆಗಳವರೆಗೆ"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"ಅನಿರ್ದಿಷ್ಟವಾಗಿ"</string> </resources> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 85c85b27adef..241159316dcf 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"나만의 연락처 카드 수정"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"앱이 기기에 저장된 개인 프로필 정보(예: 사용자 이름, 연락처 정보 등)를 변경 또는 추가할 수 있도록 허용합니다. 이는 앱이 사용자를 확인하고 다른 사용자에게 해당 프로필 정보를 전송할 수 있다는 것을 의미합니다."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"신체 센서(예: 심박수 모니터)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"앱이 신체 변화(예: 심박수) 측정을 위해 사용하는 센서의 데이터에 액세스하도록 허용합니다."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"앱이 심박수와 같은 신체 상태를 모니터링하는 센서의 데이터에 액세스하도록 허용합니다."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"소셜 스트림 읽기"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"앱이 사용자와 친구의 최신 소셜 소식에 액세스하고 동기화할 수 있도록 허용합니다. 이 경우 앱이 비밀유지와 관계 없이 소셜 네트워크에서 사용자와 친구가 주고받는 내용을 읽을 수 있으므로, 정보를 공유할 때 주의해야 합니다. 참고: 이 권한이 적용되지 않는 소셜 네트워크도 있습니다."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"소셜 스트림에 쓰기"</string> @@ -716,6 +716,14 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"앱이 캐시 파일 시스템을 읽고 쓸 수 있도록 허용합니다."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP 통화 발신/수신"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"앱에서 SIP 통화를 발신 및 수신하도록 허용"</string> + <!-- no translation found for permlab_register_provider (2654513709546459553) --> + <skip /> + <!-- no translation found for permdesc_register_provider (7571533832018681544) --> + <skip /> + <!-- no translation found for permlab_connection_manager (1116193254522105375) --> + <skip /> + <!-- no translation found for permdesc_connection_manager (5925480810356483565) --> + <skip /> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"통화 화면과 상호작용"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"앱에서 사용자가 통화 화면을 보는 시기와 방법을 제어하도록 허용합니다."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"전화 서비스와 상호 작용"</string> @@ -905,10 +913,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"다시 시도"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"다시 시도"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"얼굴 인식 잠금해제 최대 시도 횟수를 초과했습니다."</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"충전 중(<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"충전됨"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"충전기를 연결하세요."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM 카드가 없습니다."</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"태블릿에 SIM 카드가 없습니다."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"휴대전화에 SIM 카드가 없습니다."</string> @@ -1776,6 +1780,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"고정 해제 이전에 비밀번호 요청"</string> <string name="battery_saver_description" msgid="2510530476513605742">"배터리 수명을 개선하기 위해 배터리 세이버에서는 기기의 성능을 줄이고 진동과 대부분의 백그라운드 데이터를 제한합니다. 동기화가 필요한 이메일, 메시지, 기타 앱은 열어야 업데이트됩니다.\n\n기기를 충전하는 중에는 배터리 세이버가 자동으로 사용 중지됩니다."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>에 정지가 종료될 때까지"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"1분 동안"</item> <item quantity="other" msgid="6924190729213550991">"%d분 동안"</item> @@ -1784,5 +1792,7 @@ <item quantity="one" msgid="3480040795582254384">"1시간 동안"</item> <item quantity="other" msgid="5408537517529822157">"%d시간 동안"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"무제한"</string> </resources> diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml index b0a521b04ef9..5f34b9de0fb1 100644 --- a/core/res/res/values-ky-rKG/strings.xml +++ b/core/res/res/values-ky-rKG/strings.xml @@ -653,7 +653,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"сиздин байланыш картаңызды өзгөртүү"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Колдонмого түзмөгүңүздө сакталган, сиздин атыңыз жана байланыш маалыматтарыңыз сыяктуу жеке профайл маалыматтарын өзгөртүү же кошуу уруксатын берет. Бул колдонмо сизди аныктай алат жана сиздин профилдик маалыматтарыңызды башкаларга жөнөтүүгө жөндөм алат дегенди билдирет."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"дене-бой сенсорлору (жүрөктүн кагышын өлчөгүчтөр сыяктуу)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Колдонмого жүрөктүн кагышы сыяктуу дене-боюңуздагы нерселерди өлчөп турган сенсорлордун дайындарын алып туруу мүмкүнчүлүгүн берет."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Колдонмого жүрөгүңүздүн согушу сыяктуу дене-бой абалыңызды көзөмөлдөгөн сенсорлордогу дайындарды көрүп туруу мүмкүнчүлүгүн берет."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"сиздин социалдык агымыңызды окуу"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Колдонмого социалдык түйүндөргө жетүү жана сиздин жана досторуңуздун жаңыртуулары менен синхрондошуу уруксатын берет. Маалымат бөлүшкөндө абайлаңыз -- бул колдонмого сиздин социалдык түйүндөрдөгү досторуңуз менен баарлашууңузду, анын конфиденциалдуулугуна карабастан, окуганга уруксат берет. Эскертүү: бул уруксат айрым социалдык түйүндөрдө иштебеши мүмкүн."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"сиздин социалдык агымыңызга жазуу"</string> @@ -926,6 +926,14 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Колдонмого кэш файл тутумун окуу жана жазуу мүмкүнчүлүгүн берет."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP чалууларын жасоо/кабыл алуу"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Колдонмонун SIP чалууларын жасап жана кабыл алуусуна жол ачат."</string> + <!-- no translation found for permlab_register_provider (2654513709546459553) --> + <skip /> + <!-- no translation found for permdesc_register_provider (7571533832018681544) --> + <skip /> + <!-- no translation found for permlab_connection_manager (1116193254522105375) --> + <skip /> + <!-- no translation found for permdesc_connection_manager (5925480810356483565) --> + <skip /> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"чалуу экраны менен байланыштыруу"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Колдонмого чалуу экраны качан жана кандай көрүнө тургандыгын башкаруу мүмкүнчүлүгүн берет."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"телефония кызматтары"</string> @@ -1195,11 +1203,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Дагы аракет кылыңыз"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Дагы аракет кылыңыз"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Жүзүнөн таанып ачуу аракеттеринин чегинен аштыңыз"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Дүрмөттөлүүдө, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Дүрмөттөлдү"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <!-- no translation found for lockscreen_low_battery (1482873981919249740) --> - <skip /> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM-карта жок"</string> <!-- no translation found for lockscreen_missing_sim_message (151659196095791474) --> <skip /> @@ -2257,6 +2260,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Бошотуудан мурун сырсөз суралсын"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Батарея өмүрүн узартууга жардамдашуу үчүн, батарея үнөмдөгүч түзмөгүңүздүн өндүрүмдүүлүгүн азайтып, дирилдөөнү жана көпчүлүк фон дайындарын чектейт. Email, билдирүү жазуу жана башка шайкештирүүгө көз каранды колдонмолор, аларды ачмайыңызча жаңыртылбашы мүмкүн.\n\nТүзмөгүңүз кубатталып жатканда батарея үнөмдөгүч автоматтык түрдө өчөт."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Иштебей турган абал <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> аяктамайынча"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Бир мүнөткө"</item> <item quantity="other" msgid="6924190729213550991">"%d мүнөткө"</item> @@ -2265,5 +2272,7 @@ <item quantity="one" msgid="3480040795582254384">"Бир саатка"</item> <item quantity="other" msgid="5408537517529822157">"%d саатка"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Белгисиз"</string> </resources> diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml index 49da58bff412..719717bbfac4 100644 --- a/core/res/res/values-lo-rLA/strings.xml +++ b/core/res/res/values-lo-rLA/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"ແກ້ໄຂບັດລາຍຊື່ຜູ່ຕິດຕໍ່ຂອງທ່ານເອງ"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"ອະນຸຍາດໃຫ້ແອັບຯ ປ່ຽນແປງ ຫຼືເພີ່ມຂໍ້ມູນໃສ່ໂປຣໄຟລ໌ສ່ວນບຸກຄົນທີ່ເກັບໄວ້ໃນອຸປະກອນຂອງທ່ານ, ເຊັ່ນ: ຊື່ ແລະຂໍ້ມູນຕິດຕໍ່ທ່ານ. ນີ້ໝາຍຄວາມວ່າແອັບຯສາມາດບົ່ງບອກໂຕທ່ານ ແລະອາດສົ່ງຂໍ້ມູນໂປຣໄຟລ໌ຂອງທ່ານໃຫ້ຜູ່ອື່ນໄດ້."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"ເຊັນເຊີຮ່າງກາຍ (ເຊັ່ນ: ຕິດຕາມອັດຕາການເຕັ້ນຂອງຫົວໃຈ)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"ອະນຸຍາດໃຫ້ແອັບຯເຂົ້າເຖິງຂໍ້ມູນຈາກເຊັນເຊີທີ່ທ່ານໃຊ້ເພື່ອວັດແທກສິ່ງທີ່ເກີດຂຶ້ນໃນຮ່າງກາຍຂອງທ່ານ ເຊັ່ນ: ອັດຕາການເຕັ້ນຂອງຫົວໃຈ."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"ອະນຸຍາດໃຫ້ແອັບຯເຂົ້າເຖິງຂໍ້ມູນຈາກເຊັນເຊີທີ່ຕິດຕາມສະພາບຮ່າງການຂອງທ່ານ, ເຊັ່ນ: ອັດຕາການເຕັ້ນຂອງຫົວໃຈຂອງທ່ານ."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"ອ່ານການອັບເດດສັງຄົມອອນລາຍຂອງທ່ານ"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"ອະນຸຍາດໃຫ້ແອັບຯ ເຂົ້າເຖິງ ແລະຊິ້ງຂໍ້ມູນຂ່າວສານສັງຄົມຈາກທ່ານ ແລະໝູ່ຂອງທ່ານ. ຄວນລະມັດລະວັງໃນເວລາທີ່ແລກປ່ຽນຂໍ້ມູນ -- ນີ້ຈະເປັນການອະນຸຍາດໃຫ້ແອັບຯ ອ່ານການສື່ສານລະຫວ່າງທ່ານ ກັບໝູ່ຂອງທ່ານເທິງເຄືອຂ່າຍສັງຄົມ ໂດຍບໍ່ຄຳນຶງເຖິງຄວາມລັບ. ໝາຍເຫດ: ການກຳນົດສິດນີ້ອາດບໍ່ໄດ້ບັງຄັບໃຊ້ໃນທຸກເຄືອຂ່າຍສັງຄົມ."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"ຂຽນໃສ່ເຄືອຂ່າຍສັງຄົມຂອງທ່ານ"</string> @@ -716,6 +716,14 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"ອະນຸຍາດໃຫ້ແອັບຯ ອ່ານ ແລະຂຽນ ລະບົບໄຟລ໌ແຄດ."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"ຮັບສາຍ/ໂທອອກ ຜ່ານ SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"ອະນຸຍາດໃຫ້ແອັບຯສາມາດຮັບສາຍ ແລະໂທອອກຜ່ານ SIP ໄດ້"</string> + <!-- no translation found for permlab_register_provider (2654513709546459553) --> + <skip /> + <!-- no translation found for permdesc_register_provider (7571533832018681544) --> + <skip /> + <!-- no translation found for permlab_connection_manager (1116193254522105375) --> + <skip /> + <!-- no translation found for permdesc_connection_manager (5925480810356483565) --> + <skip /> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"ໂຕ້ຕອບກັບໜ້າຈໍການໂທ"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ອະນຸຍາດໃຫ້ແອັບຯຄວບຄຸມເວລາ ແລະວິທີການທີ່ຜູ່ໃຊ້ເຫັນໜ້າຈໍການໂທໄດ້."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"ສັ່ງບໍລິການໂທລະສັບ"</string> @@ -905,10 +913,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"ລອງໃໝ່ອີກຄັ້ງ"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"ທົດລອງອີກຄັ້ງ"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"ຄວາມພະຍາຍາມປົດລັອກດ້ວຍໜ້ານັ້ນ ເກີນຈຳນວນທີ່ກຳນົດແລ້ວ"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"ກຳລັງສາກ <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"ສາກເຕັມແລ້ວ."</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"ເຊື່ອມຕໍ່ສາຍສາກຂອງທ່ານ."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"ບໍ່ມີ SIM card."</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ບໍ່ມີຊິມກາດໃນແທັບເລັດ."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ບໍ່ມີ SIM card ໃນໂທລະສັບ."</string> @@ -1776,6 +1780,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ຖາມຫາລະຫັດຜ່ານກ່ອນຍົກເລີກການປັກໝຸດ"</string> <string name="battery_saver_description" msgid="2510530476513605742">"ເພື່ອຊ່ວຍປັບປຸງອາຍຸແບັດເຕີຣີ, ໂຕປະຢັດແບັດເຕີຣີຈະຫຼຸດປະສິດທິພາບຂອງອຸປະກອນທ່ານລົງ ແລະຈຳກັດການສັ່ນເຕືອນ ຮວມເຖິງຂໍ້ມູນພື້ນຫຼັງສ່ວນໃຫຍ່ນຳ. ອີເມວ, ການສົ່ງຂໍ້ຄວາມ ແລະແອັບຯອື່ນໆທີ່ອີງອາໃສການຊິ້ງຂໍ້ມູນອາດບໍ່ມີການອັບເດດຈົນກວ່າທ່ານຈະເປີດພວກມັນຂຶ້ນມາ.\n\nໂຕປະຢັດແບັດເຕີຣີຈະປິດໂດຍອັດຕະໂນມັດເມື່ອມີອຸປະກອນຖືກສາກໄຟ."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"ຈົນກວ່າດາວທາມຂອງທ່ານຈະສິ້ນສຸດທີ່ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"ເປັນເວລານຶ່ງນາທີ"</item> <item quantity="other" msgid="6924190729213550991">"ເປັນເວລາ %d ນາທີ"</item> @@ -1784,5 +1792,7 @@ <item quantity="one" msgid="3480040795582254384">"ເປັນເວລານຶ່ງຊົ່ວໂມງ"</item> <item quantity="other" msgid="5408537517529822157">"ເປັນເວລາ %d ຊົ່ວໂມງ"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"ຢ່າງບໍ່ມີກຳນົດ"</string> </resources> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index a631677417c2..f6e05dc2d94a 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"keisti jūsų kontaktinę kortelę"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Leidžiama programai keisti įrenginyje saugomą asmeninę profilio informaciją, pvz., vardą, pavardę ir kontaktinę informaciją, arba jos pridėti. Tai reiškia, kad programa gali nustatyti tapatybę ir siųsti profilio informaciją kitiems."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"kūno jut. (pvz., pulso d. t.)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Programai leidžiama pasiekti naudojamų jutiklių duomenis, siekiant įvertinti, kas vyksta jūsų kūne, pvz., pulso dažnį."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Programai leidžiama pasiekti duomenis, gautus iš jutiklių, stebinčių fizinę būseną, pvz., širdies ritmą."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"skaityti socialinį srautą"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Leidžiama programai pasiekti ir sinchronizuoti viešas naujienas iš jūsų ir jūsų draugų. Būkite atidūs bendrindami informaciją – programai leidžiama skaityti korespondenciją tarp jūsų ir draugų viešuosiuose tinkluose, neatsižvelgiant į konfidencialumą. Pastaba: šis leidimas negali būti taikomas visuose viešuosiuose tinkluose."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"rašyti į socialinį srautą"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Leidžiama programai skaityti talpyklos failų sistemą ir į ją rašyti."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"skambinti / priimti SIP skambučius"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Leidžiama programai skambinti ir priimti SIP skambučius."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"registruoti naujus telekomunikacijų ryšius"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Programai leidžiama registruoti naujus telekomunikacijų ryšius."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"tvarkyti telekomunikacijų ryšius"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Programai leidžiama tvarkyti telekomunikacijų ryšius."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"sąveika su gaunamojo skambučio ekranu"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Programai leidžiama valdyti, kada ir kaip naudotojai matys gaunamojo skambučio ekraną."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"sąveikauti su telefonijos paslaugomis"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Bandykite dar kartą"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Bandykite dar kartą"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Viršijote maksimalų atrakinimo pagal veidą bandymų skaičių"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Įkraunama, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Įkrauta"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Prijunkite kroviklį."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Nėra SIM kortelės"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Planšetiniame kompiuteryje nėra SIM kortelės."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Telefone nėra SIM kortelės."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Prašyti slaptažodžio prieš atsegant"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Siekiant pailginti akumuliatoriaus veikimo laiką, Akumuliatoriaus tausojimo priemonė sumažina įrenginio našumą ir apriboja vibravimą bei daugumą foninių duomenų. El. paštas, pranešimų siuntimas ir kitos programos, kurios veikia sinchronizavimo pagrindu, gali nebūti atnaujintos, nebent jas atidarysite.\n\nKraunant įrenginį Akumuliatoriaus tausojimo priemonė automatiškai išjungiama."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Kol jūsų prastova baigsis <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"1 min."</item> <item quantity="other" msgid="6924190729213550991">"%d min."</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"1 val."</item> <item quantity="other" msgid="5408537517529822157">"%d val."</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Neapibrėžta"</string> </resources> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 6cdf543185e0..72ecf591e033 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"mainīt manu vizītkarti"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Ļauj lietotnei mainīt ierīcē saglabāto personīgā profila informāciju, piemēram, jūsu vārdu un kontaktinformāciju, vai pievienot tai citu informāciju. Tas nozīmē, ka lietotne var jūs identificēt un var nosūtīt jūsu profila informāciju citām personām."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"ķermeņa sensori (piemēram, sirdsdarbības monitori)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Ļauj lietotnei piekļūt to sensoru datiem, kurus izmantojat, lai novērtētu ķermeņa procesus, piemēram, sirdsdarbību."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Ļauj lietotnei piekļūt to sensoru datiem, kuri pārrauga jūsu fizisko stāvokli (piemēram, sirdsdarbības ātrumu)."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"lasīt jūsu soc. tīklu straumi"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Ļauj lietotnei piekļūt sociālajiem atjauninājumiem no jums un jūsu draugiem un sinhronizēt tos. Esiet piesardzīgs, kad kopīgojat informāciju, — šādi lietotne var lasīt sociālajos tīklos ar draugiem veikto saziņu, neraugoties uz konfidencialitāti. Piezīme: šo atļauju nedrīkst piemērot visiem sociālajiem tīkliem."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"rakstīt sociālo tīklu straumē"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Ļauj lietotnei lasīt un rakstīt kešatmiņas failu sistēmā."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP zvanu veikšana/saņemšana"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Ļauj lietotnei veikt un saņemt SIP zvanus."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"jauna telekomunikācijas savienojuma reģistrēšana"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Ļauj lietotnei reģistrēt jaunus telekomunikācijas savienojumus."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"telekomunikācijas savienojumu pārvaldība"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Ļauj lietotnei pārvaldīt telekomunikācijas savienojumus."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"Mijiedarboties ar zvana laikā rādītu ekrānu"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Ļauj lietotnei kontrolēt, kad un kā lietotājam ir redzams zvana laikā redzamais ekrāns."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"mijiedarbība ar tālruņu komunikācijas pakalpojumiem"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Mēģināt vēlreiz"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Mēģināt vēlreiz"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Ir pārsniegts maksimālais Autorizācijas pēc sejas mēģinājumu skaits."</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Notiek uzlāde (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Uzlādēts"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Pievienojiet uzlādes ierīci."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Nav SIM kartes"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Planšetdatorā nav SIM kartes."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Tālrunī nav SIM kartes."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pirms atspraušanas pieprasīt paroli"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Lai paildzinātu akumulatora darbības laiku, akumulatora enerģijas taupīšanas režīmā tiks pazemināta ierīces veiktspēja, samazināta vibrācija un ierobežota liela daļa fona datu. E-pasta, ziņojumapmaiņas un citas lietotnes, kas regulāri tiek sinhronizētas, tiks atjauninātas tikai tad, ja tās atvērsiet.\n\nIerīces uzlādes laikā akumulatora jaudas taupīšana tiek izslēgta automātiski."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Līdz beigsies dīkstāve (<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>)"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Vienu minūti"</item> <item quantity="other" msgid="6924190729213550991">"%d min"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Vienu stundu"</item> <item quantity="other" msgid="5408537517529822157">"%d h"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Uz nenoteiktu laiku"</string> </resources> diff --git a/core/res/res/values-mcc204-mnc04/config.xml b/core/res/res/values-mcc204-mnc04/config.xml index 3c0381427b8a..d7484e164576 100644 --- a/core/res/res/values-mcc204-mnc04/config.xml +++ b/core/res/res/values-mcc204-mnc04/config.xml @@ -31,4 +31,11 @@ <item>"*611:+19085594899,BAE0000000000000"</item> <item>"*86:+1MDN,BAE0000000000000"</item> </string-array> + + <!-- Flag indicating whether strict threshold is used, or lenient threshold is used, + when evaluating RSRP for LTE antenna bar display + 0. Strict threshold + 1. Lenient threshold + --> + <integer name="config_LTE_RSRP_threshold_type">0</integer> </resources> diff --git a/core/res/res/values-mcc310-mnc160/config.xml b/core/res/res/values-mcc310-mnc160/config.xml new file mode 100644 index 000000000000..28cd69533197 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160/config.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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 my 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. +*/ +--> + +<!-- These resources are around just to allow their values to be customized + for different hardware and product builds. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Configure mobile network MTU. Carrier specific value is set here. + --> + <integer name="config_mobile_mtu">1440</integer> + + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + carrier provisioning. If false: hard disabled. If true: then depends on carrier + provisioning, availability etc --> + <bool name="config_carrier_volte_vt_available">true</bool> +</resources> diff --git a/core/res/res/values-mcc310-mnc200/config.xml b/core/res/res/values-mcc310-mnc200/config.xml new file mode 100644 index 000000000000..28cd69533197 --- /dev/null +++ b/core/res/res/values-mcc310-mnc200/config.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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 my 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. +*/ +--> + +<!-- These resources are around just to allow their values to be customized + for different hardware and product builds. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Configure mobile network MTU. Carrier specific value is set here. + --> + <integer name="config_mobile_mtu">1440</integer> + + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + carrier provisioning. If false: hard disabled. If true: then depends on carrier + provisioning, availability etc --> + <bool name="config_carrier_volte_vt_available">true</bool> +</resources> diff --git a/core/res/res/values-mcc310-mnc210/config.xml b/core/res/res/values-mcc310-mnc210/config.xml new file mode 100644 index 000000000000..28cd69533197 --- /dev/null +++ b/core/res/res/values-mcc310-mnc210/config.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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 my 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. +*/ +--> + +<!-- These resources are around just to allow their values to be customized + for different hardware and product builds. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Configure mobile network MTU. Carrier specific value is set here. + --> + <integer name="config_mobile_mtu">1440</integer> + + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + carrier provisioning. If false: hard disabled. If true: then depends on carrier + provisioning, availability etc --> + <bool name="config_carrier_volte_vt_available">true</bool> +</resources> diff --git a/core/res/res/values-mcc310-mnc220/config.xml b/core/res/res/values-mcc310-mnc220/config.xml new file mode 100644 index 000000000000..28cd69533197 --- /dev/null +++ b/core/res/res/values-mcc310-mnc220/config.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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 my 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. +*/ +--> + +<!-- These resources are around just to allow their values to be customized + for different hardware and product builds. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Configure mobile network MTU. Carrier specific value is set here. + --> + <integer name="config_mobile_mtu">1440</integer> + + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + carrier provisioning. If false: hard disabled. If true: then depends on carrier + provisioning, availability etc --> + <bool name="config_carrier_volte_vt_available">true</bool> +</resources> diff --git a/core/res/res/values-mcc310-mnc230/config.xml b/core/res/res/values-mcc310-mnc230/config.xml new file mode 100644 index 000000000000..28cd69533197 --- /dev/null +++ b/core/res/res/values-mcc310-mnc230/config.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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 my 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. +*/ +--> + +<!-- These resources are around just to allow their values to be customized + for different hardware and product builds. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Configure mobile network MTU. Carrier specific value is set here. + --> + <integer name="config_mobile_mtu">1440</integer> + + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + carrier provisioning. If false: hard disabled. If true: then depends on carrier + provisioning, availability etc --> + <bool name="config_carrier_volte_vt_available">true</bool> +</resources> diff --git a/core/res/res/values-mcc310-mnc240/config.xml b/core/res/res/values-mcc310-mnc240/config.xml new file mode 100644 index 000000000000..28cd69533197 --- /dev/null +++ b/core/res/res/values-mcc310-mnc240/config.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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 my 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. +*/ +--> + +<!-- These resources are around just to allow their values to be customized + for different hardware and product builds. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Configure mobile network MTU. Carrier specific value is set here. + --> + <integer name="config_mobile_mtu">1440</integer> + + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + carrier provisioning. If false: hard disabled. If true: then depends on carrier + provisioning, availability etc --> + <bool name="config_carrier_volte_vt_available">true</bool> +</resources> diff --git a/core/res/res/values-mcc310-mnc250/config.xml b/core/res/res/values-mcc310-mnc250/config.xml new file mode 100644 index 000000000000..28cd69533197 --- /dev/null +++ b/core/res/res/values-mcc310-mnc250/config.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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 my 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. +*/ +--> + +<!-- These resources are around just to allow their values to be customized + for different hardware and product builds. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Configure mobile network MTU. Carrier specific value is set here. + --> + <integer name="config_mobile_mtu">1440</integer> + + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + carrier provisioning. If false: hard disabled. If true: then depends on carrier + provisioning, availability etc --> + <bool name="config_carrier_volte_vt_available">true</bool> +</resources> diff --git a/core/res/res/values-mcc310-mnc260/config.xml b/core/res/res/values-mcc310-mnc260/config.xml index 28cd69533197..6bfc3d19ac64 100644 --- a/core/res/res/values-mcc310-mnc260/config.xml +++ b/core/res/res/values-mcc310-mnc260/config.xml @@ -25,8 +25,8 @@ --> <integer name="config_mobile_mtu">1440</integer> - <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + <!-- Flag specifying whether VoLTE should be available for carrier: independent of carrier provisioning. If false: hard disabled. If true: then depends on carrier provisioning, availability etc --> - <bool name="config_carrier_volte_vt_available">true</bool> + <bool name="config_carrier_volte_available">true</bool> </resources> diff --git a/core/res/res/values-mcc310-mnc270/config.xml b/core/res/res/values-mcc310-mnc270/config.xml new file mode 100644 index 000000000000..28cd69533197 --- /dev/null +++ b/core/res/res/values-mcc310-mnc270/config.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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 my 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. +*/ +--> + +<!-- These resources are around just to allow their values to be customized + for different hardware and product builds. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Configure mobile network MTU. Carrier specific value is set here. + --> + <integer name="config_mobile_mtu">1440</integer> + + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + carrier provisioning. If false: hard disabled. If true: then depends on carrier + provisioning, availability etc --> + <bool name="config_carrier_volte_vt_available">true</bool> +</resources> diff --git a/core/res/res/values-mcc310-mnc300/config.xml b/core/res/res/values-mcc310-mnc300/config.xml new file mode 100644 index 000000000000..28cd69533197 --- /dev/null +++ b/core/res/res/values-mcc310-mnc300/config.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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 my 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. +*/ +--> + +<!-- These resources are around just to allow their values to be customized + for different hardware and product builds. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Configure mobile network MTU. Carrier specific value is set here. + --> + <integer name="config_mobile_mtu">1440</integer> + + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + carrier provisioning. If false: hard disabled. If true: then depends on carrier + provisioning, availability etc --> + <bool name="config_carrier_volte_vt_available">true</bool> +</resources> diff --git a/core/res/res/values-mcc310-mnc310/config.xml b/core/res/res/values-mcc310-mnc310/config.xml new file mode 100644 index 000000000000..28cd69533197 --- /dev/null +++ b/core/res/res/values-mcc310-mnc310/config.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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 my 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. +*/ +--> + +<!-- These resources are around just to allow their values to be customized + for different hardware and product builds. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Configure mobile network MTU. Carrier specific value is set here. + --> + <integer name="config_mobile_mtu">1440</integer> + + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + carrier provisioning. If false: hard disabled. If true: then depends on carrier + provisioning, availability etc --> + <bool name="config_carrier_volte_vt_available">true</bool> +</resources> diff --git a/core/res/res/values-mcc310-mnc490/config.xml b/core/res/res/values-mcc310-mnc490/config.xml new file mode 100644 index 000000000000..28cd69533197 --- /dev/null +++ b/core/res/res/values-mcc310-mnc490/config.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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 my 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. +*/ +--> + +<!-- These resources are around just to allow their values to be customized + for different hardware and product builds. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Configure mobile network MTU. Carrier specific value is set here. + --> + <integer name="config_mobile_mtu">1440</integer> + + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + carrier provisioning. If false: hard disabled. If true: then depends on carrier + provisioning, availability etc --> + <bool name="config_carrier_volte_vt_available">true</bool> +</resources> diff --git a/core/res/res/values-mcc310-mnc530/config.xml b/core/res/res/values-mcc310-mnc530/config.xml new file mode 100644 index 000000000000..28cd69533197 --- /dev/null +++ b/core/res/res/values-mcc310-mnc530/config.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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 my 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. +*/ +--> + +<!-- These resources are around just to allow their values to be customized + for different hardware and product builds. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Configure mobile network MTU. Carrier specific value is set here. + --> + <integer name="config_mobile_mtu">1440</integer> + + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + carrier provisioning. If false: hard disabled. If true: then depends on carrier + provisioning, availability etc --> + <bool name="config_carrier_volte_vt_available">true</bool> +</resources> diff --git a/core/res/res/values-mcc310-mnc580/config.xml b/core/res/res/values-mcc310-mnc580/config.xml new file mode 100644 index 000000000000..28cd69533197 --- /dev/null +++ b/core/res/res/values-mcc310-mnc580/config.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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 my 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. +*/ +--> + +<!-- These resources are around just to allow their values to be customized + for different hardware and product builds. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Configure mobile network MTU. Carrier specific value is set here. + --> + <integer name="config_mobile_mtu">1440</integer> + + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + carrier provisioning. If false: hard disabled. If true: then depends on carrier + provisioning, availability etc --> + <bool name="config_carrier_volte_vt_available">true</bool> +</resources> diff --git a/core/res/res/values-mcc310-mnc590/config.xml b/core/res/res/values-mcc310-mnc590/config.xml new file mode 100644 index 000000000000..28cd69533197 --- /dev/null +++ b/core/res/res/values-mcc310-mnc590/config.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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 my 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. +*/ +--> + +<!-- These resources are around just to allow their values to be customized + for different hardware and product builds. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Configure mobile network MTU. Carrier specific value is set here. + --> + <integer name="config_mobile_mtu">1440</integer> + + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + carrier provisioning. If false: hard disabled. If true: then depends on carrier + provisioning, availability etc --> + <bool name="config_carrier_volte_vt_available">true</bool> +</resources> diff --git a/core/res/res/values-mcc310-mnc640/config.xml b/core/res/res/values-mcc310-mnc640/config.xml new file mode 100644 index 000000000000..28cd69533197 --- /dev/null +++ b/core/res/res/values-mcc310-mnc640/config.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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 my 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. +*/ +--> + +<!-- These resources are around just to allow their values to be customized + for different hardware and product builds. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Configure mobile network MTU. Carrier specific value is set here. + --> + <integer name="config_mobile_mtu">1440</integer> + + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + carrier provisioning. If false: hard disabled. If true: then depends on carrier + provisioning, availability etc --> + <bool name="config_carrier_volte_vt_available">true</bool> +</resources> diff --git a/core/res/res/values-mcc310-mnc660/config.xml b/core/res/res/values-mcc310-mnc660/config.xml new file mode 100644 index 000000000000..28cd69533197 --- /dev/null +++ b/core/res/res/values-mcc310-mnc660/config.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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 my 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. +*/ +--> + +<!-- These resources are around just to allow their values to be customized + for different hardware and product builds. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Configure mobile network MTU. Carrier specific value is set here. + --> + <integer name="config_mobile_mtu">1440</integer> + + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + carrier provisioning. If false: hard disabled. If true: then depends on carrier + provisioning, availability etc --> + <bool name="config_carrier_volte_vt_available">true</bool> +</resources> diff --git a/core/res/res/values-mcc310-mnc800/config.xml b/core/res/res/values-mcc310-mnc800/config.xml new file mode 100644 index 000000000000..28cd69533197 --- /dev/null +++ b/core/res/res/values-mcc310-mnc800/config.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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 my 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. +*/ +--> + +<!-- These resources are around just to allow their values to be customized + for different hardware and product builds. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Configure mobile network MTU. Carrier specific value is set here. + --> + <integer name="config_mobile_mtu">1440</integer> + + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + carrier provisioning. If false: hard disabled. If true: then depends on carrier + provisioning, availability etc --> + <bool name="config_carrier_volte_vt_available">true</bool> +</resources> diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml index c2be34094d74..8cb2928e83e2 100644 --- a/core/res/res/values-mcc311-mnc480/config.xml +++ b/core/res/res/values-mcc311-mnc480/config.xml @@ -38,10 +38,10 @@ be disabled) but individual Features can be disabled using ImsConfig.setFeatureValue() --> <bool name="imsServiceAllowTurnOff">false</bool> - <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + <!-- Flag specifying whether VoLTE should be available for carrier: independent of carrier provisioning. If false: hard disabled. If true: then depends on carrier provisioning, availability etc --> - <bool name="config_carrier_volte_vt_available">false</bool> + <bool name="config_carrier_volte_available">true</bool> <bool name="config_auto_attach_data_on_creation">false</bool> <!-- service number convert map in roaming network. --> @@ -49,4 +49,11 @@ <item>"*611:+19085594899,"</item> <item>"*86:+1MDN,"</item> </string-array> + + <!-- Flag indicating whether strict threshold is used, or lenient threshold is used, + when evaluating RSRP for LTE antenna bar display + 0. Strict threshold + 1. Lenient threshold + --> + <integer name="config_LTE_RSRP_threshold_type">0</integer> </resources> diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml index 444628a7f7eb..58ee5ec96d9c 100644 --- a/core/res/res/values-mk-rMK/strings.xml +++ b/core/res/res/values-mk-rMK/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"измени ја сопствената картичка за контакт"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Овозможува апликацијата да менува или да додава информации од личниот профил што се зачувани на вашиот уред, како што се вашето име и информации за контакт. Ова значи дека апликацијата може да ве идентификува и да ги испрати информациите од вашиот профил на други."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"телесни сензори (како монитори за срцев пулс)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Дозволува апликацијата да пристапи до податоци од сензори што ги користите за мерење на настани во вашето тело, како срцевиот ритам."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Дозволува апликацијата да пристапува до податоци од сензори кои ја следат вашата физичка состојба, како на пр. отчукувањата на срцето."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"читај социјални текови"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Овозможува апликацијата да пристапува и да синхронизира социјални ажурирања од вас и вашите пријатели. Бидете внимателни кога споделувате информации - ова овозможува апликацијата да ја чита комуникацијата меѓу вас и вашите пријатели на социјалните мрежи, без оглед на нејзината доверливост. Напомена: оваа дозвола не може да се наметне на сите социјални мрежи."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"пишувај на социјалните текови"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Дозволува апликацијата да чита и да пишува кеш систем на датотеки."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"остварувај/примај повици преку СИП"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Дозволува апликацијата да остварува и прима повици преку СИП."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"регистрира нови телекомуникациски врски"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Дозволува апликацијата да регистрира нови телекомуникациски врски."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"управува со телекомуникациски врски"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Дозволува апликацијата да управува со телекомуникациски врски."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"комуницирај со екран на дојдовен повик"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Овозможува апликацијата да контролира кога и како корисникот го гледа екранот на дојдовен повик."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"комуницира со телефонски услуги"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Обидете се повторно"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Обидете се повторно"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Максималниот број обиди на отклучување со лице е надминат"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Се полни, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Наполнета"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Поврзете го полначот."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Нема СИМ картичка"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Во таблетот нема СИМ картичка."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Во телефонот нема СИМ картичка."</string> @@ -1778,6 +1778,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Прашај за лозинка пред откачување"</string> <string name="battery_saver_description" msgid="2510530476513605742">"За да помогне во подобрување на трајноста на батеријата, штедачот на батерија го намалува учинокот на уредот и ги ограничува вибрациите и повеќето податоци во заднина. Е-поштата, испраќањето пораки и другите апликации кои се потпираат на синхронизирање може да не се ажурираат освен ако не ги отворите.\n\nШтедачот на батерија автоматски се исклучува кога уредот се полни."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Додека не заврши паузата во <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"За една минута"</item> <item quantity="other" msgid="6924190729213550991">"За %d минути"</item> @@ -1786,5 +1790,7 @@ <item quantity="one" msgid="3480040795582254384">"За еден час"</item> <item quantity="other" msgid="5408537517529822157">"За %d часа"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Неодредено време"</string> </resources> diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml index 2237d8c50884..c303fa23759b 100644 --- a/core/res/res/values-ml-rIN/strings.xml +++ b/core/res/res/values-ml-rIN/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"നിങ്ങളുടെ സ്വന്തം കോൺടാക്റ്റ് കാർഡ് പരിഷ്ക്കരിക്കുക"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"നിങ്ങളുടെ ഉപകരണത്തിൽ സംഭരിച്ചിരിക്കുന്ന നിങ്ങളുടെ പേരും ബന്ധപ്പെടാനുള്ള വിവരങ്ങളും പോലുള്ള വ്യക്തിഗത പ്രൊഫൈൽ വിവരം മാറ്റാനോ ചേർക്കാനോ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. നിങ്ങളെ തിരിച്ചറിയാനും നിങ്ങളുടെ പ്രൊഫൈൽ വിവരം മറ്റുള്ളവർക്ക് അയയ്ക്കാനും അപ്ലിക്കേഷന് കഴിഞ്ഞേക്കാമെന്നാണ് ഇതിനർത്ഥം."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"ശാരീര സെൻസറുകൾ (ഹൃദയമിടിപ്പ് നിരക്ക് മോണിറ്ററുകൾ പോലെ)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"ഹൃദയമിടിപ്പിന്റെ നിരക്കുപോലെ നിങ്ങളുടെ ശരീരത്തിനുള്ളിൽ സംഭവിക്കുന്ന കാര്യങ്ങൾ കണക്കാക്കാൻ ഉപയോഗിക്കുന്ന സെൻസറുകളിൽനിന്ന് ഡാറ്റ ആക്സസ്സുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"നിങ്ങളുടെ ഹൃദയമിടിപ്പ് പോലുള്ള ശാരീരികാവസ്ഥ നിരീക്ഷിക്കാൻ സെൻസറുകളിൽ നിന്ന് വിവരം ആക്സസ്സുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"നിങ്ങളുടെ സോഷ്യൽ സ്ട്രീം വായിക്കുക"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"നിങ്ങളിൽ നിന്നും സുഹൃത്തുക്കളിൽ നിന്നും സോഷ്യൽ അപ്ഡേറ്റുകൾ ആക്സസ്സുചെയ്യാനും സമന്വയിപ്പിക്കാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. വിവരം പങ്കിടുമ്പോൾ ജാഗ്രത പാലിക്കുക -- ഇത് സോഷ്യൽ നെറ്റ്വർക്കുകളിൽ നിങ്ങൾക്കും സുഹൃത്തുക്കൾക്കും ഇടയിലുള്ള ആശയവിനിമയങ്ങൾ രഹസ്യാത്മകത പരിഗണിക്കാതെ റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ശ്രദ്ധിക്കുക: ഈ അനുമതി എല്ലാ സോഷ്യൽ നെറ്റ്വർക്കുകളിലും നടപ്പിലാക്കാനിടയില്ല."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"നിങ്ങളുടെ സോഷ്യൽ സ്ട്രീമിലേക്ക് എഴുതുക"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"കാഷെ ഫയൽ സിസ്റ്റം റീഡുചെയ്യുന്നതിനും റൈറ്റുചെയ്യുന്നതിനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP കോളുകൾ വിളിക്കുക/സ്വീകരിക്കുക"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"SIP കോളുകൾ വിളിക്കാനും സ്വീകരിക്കാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"പുതിയ ടെലികോം കണക്ഷൻ രജിസ്റ്റർ ചെയ്യുക"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"പുതിയ ടെലികോം കണക്ഷനുകൾ രജിസ്റ്റർ ചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"ടെലികോം കണക്ഷനുകൾ നിയന്ത്രിക്കുക"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"ടെലികോം കണക്ഷനുകൾ നിയന്ത്രിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"ഇൻ-കോൾ സ്ക്രീനുമായി സംവദിക്കുക"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ഉപയോക്താവ് ഇൻ-കോൾ സ്ക്രീൻ എപ്പോൾ, എങ്ങനെ കാണുന്നുവെന്നത് നിയന്ത്രിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"ടെലിഫോണി സേവനങ്ങൾ ഉപയോഗിച്ച് സംവദിക്കുക"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"വീണ്ടും ശ്രമിക്കുക"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"വീണ്ടും ശ്രമിക്കുക"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"മുഖം തിരിച്ചറിഞ്ഞുള്ള അൺലോക്ക് ശ്രമങ്ങളുടെ പരമാവധി കഴിഞ്ഞു"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"ചാർജ്ജുചെയ്യുന്നു, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"ചാർജ്ജുചെയ്തു"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"നിങ്ങളുടെ ചാർജർ കണക്റ്റുചെയ്യുക."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"സിം കാർഡൊന്നുമില്ല"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ടാബ്ലെറ്റിൽ സിം കാർഡൊന്നുമില്ല."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ഫോണിൽ സിം കാർഡൊന്നുമില്ല."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"അൺപിൻ ചെയ്യുന്നതിനുമുമ്പ് പാസ്വേഡ് ആവശ്യപ്പെടുക"</string> <string name="battery_saver_description" msgid="2510530476513605742">"ബാറ്ററി ആയുസ്സ് മെച്ചപ്പെടുത്താൻ സഹായിക്കുന്നതിന്, ബാറ്ററി സേവർ നിങ്ങളുടെ ഉപകരണത്തിന്റെ പ്രകടനത്തെ കുറയ്ക്കുകയും വൈബ്രേഷനെയും മിക്ക പശ്ചാത്തല ഡാറ്റയെയും പരിമിതപ്പെടുത്തുകയും ചെയ്യുന്നു. ഇമെയിൽ, സന്ദേശമയയ്ക്കൽ, സമന്വയിപ്പിക്കലിനെ ആശ്രയിച്ചുള്ള മറ്റ് അപ്ലിക്കേഷനുകൾ എന്നിവ നിങ്ങൾ തുറക്കുന്നതുവരെ അപ്ഡേറ്റുചെയ്യാനിടയില്ല.\n\nനിങ്ങളുടെ ഉപകരണം ചാർജ്ജുചെയ്യുമ്പോൾ ബാറ്ററി സേവർ യാന്ത്രികമായി ഓഫാകും."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-ന് നിങ്ങളുടെ കാലാവധി അവസാനിക്കുന്നതുവരെ"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"ഒരു മിനിറ്റ് ദൈർഘ്യം"</item> <item quantity="other" msgid="6924190729213550991">"%d മിനിറ്റ് ദൈർഘ്യം"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"ഒരു മണിക്കൂർ ദൈർഘ്യം"</item> <item quantity="other" msgid="5408537517529822157">"%d മണിക്കൂർ ദൈർഘ്യം"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"അവ്യക്തം"</string> </resources> diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml index 9cb3e92e5a33..38e395ce39be 100644 --- a/core/res/res/values-mn-rMN/strings.xml +++ b/core/res/res/values-mn-rMN/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"та өөрийн харилцагчийн картыг өөрчлөх"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Апп нь таны нэр болон холбоо барих мэдээлэл зэрэг таны төхөөрөмж дээр хадгалагдсан хувийн профайл мэдээллийг солих эсвэл нэмэх боломжтой. Ингэснээр апп нь танийг таньж чадах ба таны профайл мэдээллийг бусдад илгээх боломжтой."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"биеийн сенсор (зүрхний цохилт хянагч гэх мэт)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Зүрхний цохилт гэх мэт биеийн үзүүлэлт хэмждэг сенсоруудын дата-д хандалт хийх боломжийг апп-д олгоно."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Апп-т таны зүрхний цохилт гэх мэт биеийн байдлыг хянадаг мэдрэгчдийн датанд хандалт хийх боломж олгоно."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"таны нийтийн урсгалаас унших"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Апп нь та болон таны найзуудын нийтийн шинэчлэлтэд хандах болон синк хийх боломжтой. Мэдээлэл хуваалцахдаа болгоомжтой байна уу - энэ нь апп-д нийтийн сүлжээндэх та болон таны найзууд хоорондын холбоог нууц эсэхээс үл хамааран унших боломжтой. Анхаар: энэ зөвшөөрөл нь бүх нийтийн сүлжээнд ашиглаж боломжгүй."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"Таны нийтийн урсгалруу бичих"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Апп нь кеш файлсистемийг унших бичих боломжтой."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP дуудлага хийх/хүлээн авах"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Апп-д SIP дуудлага хийх болон хүлээн авахыг зөвшөөрөх."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"шинэ телеком холболтуудыг бүртгэх"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Апп-д шинэ телеком холболтуудыг бүртгэхийг зөвшөөрнө."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"телеком холболтуудыг удирдах."</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Апп-д телеком холболтуудыг удирдахыг зөвшөөрнө."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"дуудлагын дэлгэцтэй харьцах"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Апп-д дуудлагын дэлгэцийг хэрэглэгчид хэзээ хэрхэн харуулахыг удирдахыг зөвшөөрнө."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"телефоны үйлчилгээтэй харилцах"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Дахин оролдох"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Дахин оролдох"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Нүүрээр түгжээ тайлах оролдлогын тоо дээд хэмжээнээс хэтэрсэн"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Цэнэглэж байна, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Цэнэглэгдэв"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Цэнэглэгчээ холбоно уу."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM карт байхгүй"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Таблет SIM картгүй."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Утсанд SIM карт байхгүй."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Тогтоосныг суллахаас өмнө нууц үг асуух"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Батерейны ашиглалтыг уртасгахын тулд батерей хэмнэгч нь таны төхөөрөмжийн ажиллагааг бууруулж, чичрэлт болон далд датаны ихэнх хувийг хязгаарлана. Имэйл, зурвас гэх мэт синк хийгддэг бусад апп-ууд таныг нээхээс нааш шинэчлэгдэхгүй байж болно.\n\nТаныг төхөөрөмжөө цэнэглэх үед батерей хэмнэгч автоматаар унтарна."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Таны уйтгартай байдал <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-д дуусах хүртэл"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Нэг минутын турш"</item> <item quantity="other" msgid="6924190729213550991">"%d минутын турш"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Нэг цагийн турш"</item> <item quantity="other" msgid="5408537517529822157">"%d цагийн турш"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Тодорхойгүй"</string> </resources> diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml index 93fe1628176f..b7401c774f62 100644 --- a/core/res/res/values-mr-rIN/strings.xml +++ b/core/res/res/values-mr-rIN/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"आपल्या स्वतःचे संपर्क कार्ड सुधारित करा"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"आपल्या डिव्हाइसवर संचयित केलेली वैयक्तिक माहिती बदलण्यासाठी किंवा जोडण्यासाठी अॅप ला अनुमती देते. म्हणजेच अॅप आपल्याला ओळखू शकतो आणि इतरांना आपली प्रोफाईल माहिती पाठवू शकतो."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"(हृदय गती मॉनिटरसारखे) शरीर सेन्सर"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"आपल्या शरीरात काय होत आहे जसे की हृदय गती, मोजण्यासाठी आपण वापरता त्या सेन्सरकडील डेटावर प्रवेश करण्यासाठी अॅप ला अनुमती देते."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"हृदय गती सारख्या, आपल्या शारीरिक स्थितीचे नियंत्रण करणार्या सेन्सरवरून डेटामध्ये प्रवेश करण्यासाठी अॅपला अनुमती देते."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"आपला सामाजिक प्रवाह वाचा"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"आपल्याकडील आणि आपल्या मित्रांकडील सामाजिक अद्यतनांवर प्रवेश करण्यास आणि त्यांचे संकालन करण्यास अॅप ला अनुमती देते. माहिती सामायिक करताना सावधगिरी बाळगा -- हे गोपनीयतेकडे दुर्लक्ष करून, आपण आणि सामाजिक नेटवर्कवरील आपल्या मित्रांमधील संप्रेषणे वाचण्यास अॅप ला अनुमती देते. टीप: या परवानगीची अंमलबजावणी सर्व सामाजिक नेटवर्कवर होऊ शकत नाही."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"आपल्या सामाजिक प्रवाहावर लिहा"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"कॅशे filesystem वाचण्यासाठी आणि लिहिण्यासाठी अॅप ला अनुमती देते."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP कॉल करा/प्राप्त करा"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"अॅपला SIP कॉल करण्याची आणि प्राप्त करण्याची अनुमती देते."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"नवीन टेलिकॉम कनेक्शनची नोंदणी करा"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"नवीन टेलिकॉम कनेक्शनची नोंदणी करण्यासाठी अॅपला अनुमती देते."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"टेलिकॉम कनेक्शन व्यवस्थापित करा"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"टेलिकॉम कनेक्शन व्यवस्थापित करण्यासाठी अॅप ला अनुमती देते."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"कॉल-मधील स्क्रीनशी परस्परसंवाद करा"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"वापरकर्ता कॉल-मधील स्क्रीन केव्हा आणि कशी पाहतो ते नियंत्रित करण्याची अॅपला अनुमती देते."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"टेलिफोनी सेवांशी परस्परसंवाद साधा"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"पुन्हा प्रयत्न करा"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"पुन्हा प्रयत्न करा"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"कमाल चेहरा अनलॉक प्रयत्न ओलांडले"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"चार्ज होत आहे, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"चार्ज झाली"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"आपले चार्जर कनेक्ट करा."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"सिम कार्ड नाही"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"टॅब्लेटमध्ये सिम कार्ड नाही."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"फोनमध्ये सिम कार्ड नाही."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"अनपिन करण्यापूर्वी संकेतशब्दासाठी विचारा"</string> <string name="battery_saver_description" msgid="2510530476513605742">"बॅटरीचे आयुष्य सुधारण्यात मदत होण्यासाठी, बॅटरी बचतकर्ता आपल्या डिव्हाइसचे कार्यप्रदर्शन कमी करतो आणि कंपन आणि बराच पार्श्वभूमी डेटा मर्यादित करतो. संकालनावर अवलंबून असणारे ईमेल, संदेशन आणि अन्य अॅप्स आपण ते उघडल्याशिवाय अद्यतनित होऊ शकत नाहीत.\n\nआपले डिव्हाइस चार्ज होत असते तेव्हा बॅटरी बचतकर्ता स्वयंचलितपणे बंद होतो."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"आपला कार्य न करण्याचा कालावधी <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> वाजता समाप्त होईपर्यंत"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"एक मिनिटासाठी"</item> <item quantity="other" msgid="6924190729213550991">"%d मिनिटांसाठी"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"एका तासासाठी"</item> <item quantity="other" msgid="5408537517529822157">"%d तासांसाठी"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"अनिश्चितपणे"</string> </resources> diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml index 26bf08a6ac61..95d7cef62ec1 100644 --- a/core/res/res/values-ms-rMY/strings.xml +++ b/core/res/res/values-ms-rMY/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"ubah suai kad kenalan sendiri"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Membenarkan apl menukar atau menambah maklumat profil peribadi yang disimpan pada peranti anda, seperti nama dan maklumat kenalan anda. Ini bermakna apl boleh mengenal pasti anda dan menghantar maklumat profil anda kepada orang lain."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"penderia (spt. denyut jantung)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Membenarkan apl mengakses data dari penderia yang anda gunakan untuk mengukur perkara yang berlaku dalam tubuh anda, seperti kadar denyutan jantung."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Membenarkan apl mengakses data dari penderia yang memantau keadaan fizikal anda, seperti kadar denyutan jantung anda."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"baca aliran sosial anda"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Membenarkan apl mengakses dan menyegerakkan kemas kini sosial daripada anda dan rakan anda. Berhati-hati semasa berkongsi maklumat - ini membenarkan apl untuk membaca komunikasi di antara anda dan rakan anda pada rangkaian sosial tanpa mengira kerahsiaan. Nota: kebenaran ini tidak boleh dikuatkuasakan pada semua rangkaian sosial."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"tulis ke aliran sosial anda"</string> @@ -716,6 +716,14 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Membenarkan apl membaca dan menulis cache sistem fail."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"buat/terima panggilan SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Membenarkan apl membuat dan menerima panggilan SIP."</string> + <!-- no translation found for permlab_register_provider (2654513709546459553) --> + <skip /> + <!-- no translation found for permdesc_register_provider (7571533832018681544) --> + <skip /> + <!-- no translation found for permlab_connection_manager (1116193254522105375) --> + <skip /> + <!-- no translation found for permdesc_connection_manager (5925480810356483565) --> + <skip /> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"berinteraksi dengan skrin dalam panggilan"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Membenarkan apl mengawal masa dan cara pengguna melihat skrin dalam panggilan."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"berinteraksi dengan perkhidmatan telefoni"</string> @@ -905,10 +913,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Cuba lagi"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Cuba lagi"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Telah melepasi had cubaan Buka Kunci Wajah"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Mengecas, (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Sudah dicas"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Sambungkan pengecas anda."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Tiada kad SIM"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tiada kad SIM dalam tablet."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Kad SIM tiada dalam telefon."</string> @@ -1776,6 +1780,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Minta kata laluan sebelum menyahsemat"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Untuk membantu memperbaik hayat bateri, penjimat bateri mengurangkan prestasi peranti anda dan menghadkan getaran serta kebanyakan data latar belakang. E-mel, pemesejan dan apl lain yang bergantung pada penyegerakan mungkin tidak dikemas kini melainkan anda membuka apl tersebut.\n\nPenjimat bateri dimatikan secara automatik semasa peranti anda mengecas."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Sehingga waktu gendala anda berakhir pada <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Selama satu minit"</item> <item quantity="other" msgid="6924190729213550991">"Selama %d minit"</item> @@ -1784,5 +1792,7 @@ <item quantity="one" msgid="3480040795582254384">"Selama satu jam"</item> <item quantity="other" msgid="5408537517529822157">"Selama %d jam"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Selama-lamanya"</string> </resources> diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml index 3e156a89cb68..999fb48f5456 100644 --- a/core/res/res/values-my-rMM/strings.xml +++ b/core/res/res/values-my-rMM/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"သင့်ရဲ့ အဆက်အသွယ်ကဒ် အား ပြင်ရန်"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"အပလီကေးရှင်းအား စက်မှာ သိမ်းထားသော သင့်နာမည် နှင့် အဆက်အသွယ် သတင်းအချက်အလက်များကဲ့သို့သော ကိုယ်ရေးကိုယ်တာ အချက်အလက်များအား ပြင်ဆင်ခွင့် သို့ ထည့်ခွင့် ပြုခြင်း။ အပလီကေးရှင်းမှ သင့်အား သိရှိနိုင်ပြီး သင့်ကိုယ်ရေးအချက်အလက်များအား အခြားသူများကို ပေးပို့နိုင်ပါသည်"</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"ခန္ဓာကိုယ် အာရံခံကိရိယာများ (နှလုံးခုန်နှုန်း စောင့်ကြည့်စက် လို)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"appအား သင့် ခန္ဓာကိုယ် အတွင်းမှာ၊ နှလုံးခုန်နှုန်းလို၊ ဘာတွေ ဖြစ်ပျက်နေကြောင်းကို တိုင်းထွာရန် အသုံးပြုသည့် အာရုံခံကိရိယာများ ထံမှ ဒေတာများကို ရယူသုံးခွင့် ပေးထားသည်။"</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"သင်၏ နှလုံးခုန်နှုန်းလို ရုပ်ပိုင်း အခြေအနေကို စောင့်ကြပ်သည့် အာရုံခံစက်များထံမှ ဒေတာများကို appအား ရယူသုံးခွင့် ပြုပါ။"</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"သင့်လူမှုရေးရာအဖွဲ့အစည်းတွင်ရေးသားရန်"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"အပလီကေးရှင်းအား သင်နှင့် သင့်သူငယ်ချင်းတို့၏ ဆိုရှယ်နက်ဝဘ်မှ နောက်ဆုံးပေါ် အချက်အလက်များအား အသုံးပြုခွင့်နင့် ထပ်တူညီအောင် လုပ်ဆောင်ခွင့် ပြုပါ။ သတင်းအချက်အလက် မျှဝေခြင်းတွင် သတိပြုရန် -- ဤသို့ ခွင့်ပြုခြင်းဖြင့် အပလီကေးရှင်းမှ ယုံကြည်စိတ်ချရမှုကို ဂရုမပြုပဲ သင် နှင့် သူငယ်ချင်းများကြား ဆက်သွယ်မှုများအား သိရှိနိုင်ပါသည်။ မှတ်ချက်။ ဤခွင့်ပြုချက်အား ဆိုရှယ်နက်ဝဘ် အားလုံးတွင် ခွင့်ပြုခြင်း မလုပ်သင့်ပါ။"</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"သင့်လူမှုရေးရာအဖွဲ့အစည်းတွင်ရေးသားရန်"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"appအား ဖိုင်စနစ်၏ကက်ရှကို ဖတ် နှင့် ရေး ခွင့်ပြုသည်။"</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP ခေါ်ဆိုမှုများ ခေါ်ရန်/လက်ခံရန်"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"SIP ခေါ်ဆိုမှုများ ခေါ်ရန်နှင့် လက်ခံနိုင်ရန် app ကို ခွင့်ပြုပါ။"</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"တယ်လီကွမ် ဆက်သွယ်မှု အသစ်ကို မှတ်ပုံတင်ရန်"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"appအား တယ်လီကွမ် ဆက်သွယ်မှု အသစ်ကို မှတ်ပုံတင်ခွင့် ပြုပါ။"</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"တယ်လီကွမ် ဆက်သွယ်မှုများကို စီမံရန်"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"appအား တယ်လီကွမ် ဆက်သွယ်မှုများကို စီမံခွင့် ပြုပါ။"</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"ခေါ်ဆိုမှု-အဝင် မျက်နှာပြင်နဲ့ တုံ့ပြန်လုပ်ကိုင်ရန်"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"appအား အသုံးပြုသူက ခေါ်ဆိုမှုအဝင် မျက်နှာပြင် ဘယ်အချိန်မှာ ဘယ်လို မြင်ရမှာကို ထိန်းချုပ်ခွင့်ပေးရန်"</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"တယ်လီဖုန်း ဝန်ဆောင်မှုများနှင့် အပြန်အလှန် တုံ့ပြန်မှု"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"ထပ် စမ်းပါ"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"ထပ် စမ်းပါ"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"မျက်မှာမှတ် သော့ဖွင့်ခြင်း ခွင့်ပြုသော အကြိမ်ရေထက် ကျော်လွန်သွားပါပြီ"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"အားသွင်းနေပါသည်, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"အားသွင်းနေပါသည်"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"အားသွင်းကြိုးဖြင့် ဆက်သွယ်ပါ"</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"ဆင်းကဒ် မရှိပါ"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"တက်ပလက်ထဲတွင်း ဆင်းကဒ် မရှိပါ"</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ဖုန်းထဲတွင် ဆင်းကဒ် မရှိပါ"</string> @@ -1776,11 +1776,17 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ပင်မဖြုတ်မီမှာ စကားဝှက်ကို မေးကြည့်ရန်"</string> <string name="battery_saver_description" msgid="2510530476513605742">"ဘက်ထရီသက်တမ်း ကြာရှည်ခံရန်အတွက်၊ ဘက်ထရီချွေတာရေးအပိုင်းမှ သင့် စက်ပစ္စည်း၏ဆောင်ရွက်ချက်များကို လျော့ချပေးပြီး တုန်ခါမှုနှင့် နောက်ခံအချက်အလက်အများစုကို ကန့်သတ်ပေးသည်။ အီးမေး၊ စာပို့ခြင်း နှင့် တခြားapp များကို သင်ဖွင့်မထားပါက အချိန်နှင့်တပြေးညီ ညှိမပေးပါ။ \n\n စက်ပစ္စည်း အားသွင်းနေစဉ် ဘက်ထရီချွေတာရေးအပိုင်းသည် အလိုအလျောက်ပင် အလုပ်မလုပ်ပါ။"</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"သင်၏ စက်ရပ်ချိန် <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> မှာ ပြီးဆုံးသည့် အထိ။"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"တစ်မိနစ် အတွင်း"</item> <item quantity="other" msgid="6924190729213550991">"%d မိနစ် အတွင်း"</item> </plurals> <!-- String.format failed for translation --> <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) --> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"အကန့်အသတ်မရှိစွာ"</string> </resources> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 7f1ac707f030..f9e44e7106e7 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"endre ditt eget kontaktkort"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Lar appen endre eller legge til personlig profilinformasjon som er lagret på enheten din, som for eksempel navn og kontaktinformasjon. Dette betyr at appen kan identifisere deg og sende profilinformasjonen din til andre."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"kroppssensorer (som pulsmålere)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Gir appen tillatelse til å bruke data fra sensorer du bruker til å måle det som skjer i kroppen din, som f.eks. pulsen."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Gir appen tilgang til data fra sensorer som overvåker den fysiske tilstanden din, for eksempel hjertefrekvensen din."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"lese din sosiale strøm"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Lar appen lese og synkronisere sosiale oppdateringer fra deg selv og vennene dine. Vær forsiktig når du deler informasjon - med denne tillatelsen kan appen lese kommunikasjon mellom deg og vennene dine på sosiale nettverk, uavhengig av konfidensialitet. Vær oppmerksom på at denne tillatelsen kanskje ikke gjelder for alle sosiale nettverk."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"skrive i din sosiale strøm"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Lar appen lese og skrive til det bufrede filsystemet."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"foreta/motta SIP-anrop"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Tillater at appen utfører og mottar SIP-anrop."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"registrere nye telekom-tilkoblinger"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Lar appen registrere nye telekom-tilkoblinger."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"administrere telekom-tilkoblinger"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Lar appen administrere telekom-tilkoblinger."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"samhandle med skjermen for innkommende anrop"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Lar appen styre når og hvordan brukeren ser skjermen for innkommende anrop."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"samhandle med telefonitjenester"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Prøv på nytt"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Prøv på nytt"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Du har overskredet grensen for opplåsingsforsøk med Ansiktslås"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Lader, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Oppladet"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Koble til en batterilader."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM-kortet mangler"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nettbrettet mangler SIM-kort."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Ikke noe SIM-kort i telefonen."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Krev passord for å løsne apper"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Batterisparing reduserer enhetens ytelse og begrenser vibrering og de fleste bakgrunnsdata for å forbedre batterilevetiden. Det kan hende E-post, Meldinger og andre apper som er avhengige av synkronisering, ikke oppdateres med mindre du åpner dem.\n\nBatterisparing slås automatisk av når enheten lades."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Til hviletiden din ender kl. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"I ett minutt"</item> <item quantity="other" msgid="6924190729213550991">"I %d minutter"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"I én time"</item> <item quantity="other" msgid="5408537517529822157">"I %d timer"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"På ubestemt tid"</string> </resources> diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml index e2956a11a0d4..e93bee10d744 100644 --- a/core/res/res/values-ne-rNP/strings.xml +++ b/core/res/res/values-ne-rNP/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"तपाईँको आफ्नै सम्पर्क कार्ड परिमार्जन गर्नुहोस्"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"तपाईँको उपकरणमा भण्डार भएको व्याक्तिगत प्रोफाइल जानकारी, जस्तै तपाईँको नाम वा सम्पर्क जानकारीलाई परिवर्तन गर्न वा थप्नको लागि अनुप्रयोगलाई अनुमति दिन्छ। यसको मतलब अन्य अनुप्रयोगले तपाईँलाई चिन्न सक्छन् र सायद अन्यलाई तपाईँको प्रोफाइल जानकारी पठाउन सक्छन्।"</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"शरीर सेन्सर (हृदयदर मोनिटर जस्तै)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"हृदयदर झैं तपाईँको आफ्नो शरीरभित्र के भइरहेकोछ मापन गर्न प्रयोग सेन्सर द्वारा डेटा पहुँच गर्न अनुप्रयोगलाई अनुमति दिन्छ।"</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"तपाईँको हृदय गति जस्तो सेंसर बाट डेटा पहुँचको लागि अनुप्रयोग अनुमति दिन्छ जसले तपाईँको भौतिक अवस्था अनुगमन गर्छ।"</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"तपाईंको सामाजिक स्ट्रिम पढ्नुहोस्"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"तपाईँ र तपाईँका साथीहरूबाट सामाजिक अपडेटलाई पहुँच र सिंक गर्नको लागि अनुप्रयोगलाई अनुमति दिन्छ। जानकारी साझेदारी गर्दा सावधान रहनुहोस् -- समाजिक नेटवर्कहरूमा तपाईँ र तपाईँको साथीको बिचमा भएका संचारलाई पढ्न विश्वासनीयता बेगरै यसले अनुप्रयोगलाई अनुमति दिन्छ। नोट: यो अनुमति बलपूर्वक सबै सामाजिक नेटवर्कहरूमा सायद नगर्न सकिन्छ।"</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"तपाईँको सामाजिक प्रवाहमा लेख्नुहोस्"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"केस फाइल प्रणालीलाई पढ्न र लेख्नको लागि अनुप्रयोगलाई अनुमति दिन्छ।"</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP कलहरू प्राप्त/बनाउन"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"SIP कलहरू बनाउन र प्राप्त गर्न अनुप्रयोगलाई अनुमति दिन्छ।"</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"नयाँ दूरसंचार जडान दर्ता गर्नुहोस्"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"अनुप्रयोग लाई नयाँ दूरसंचार सम्पर्क दर्ता गर्न अनुमति दिन्छ।"</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"दूरसंचार जडान व्यवस्थापन गर्नुहोस्"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"अनुप्रयोग लाई टेलिकम जडान व्यवस्थापन गर्न अनुमति दिन्छ।"</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"आगमन कल स्क्रिन संग अन्तर्क्रिया गर्नुहोस्"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"कहिले र कसरी प्रयोगकर्ताले आगमन कल स्क्रीन हेर्न सक्दछ भनेर नियन्त्रण गर्न अनुप्रयोगलाई अनुमति दिनुहोस्।"</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"टेलिफोनी सेवा अन्तरक्रिया"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"फेरि प्रयास गर्नुहोस्"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"फेरि प्रयास गर्नुहोस्"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"अत्याधिक मोहडा खोल्ने प्रयासहरू बढी भए।"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"चार्ज हुँदै, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"चार्ज भयो"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"तपाईँको चार्जर जोड्नुहोस्।"</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM कार्ड छैन"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ट्याब्लेटमा SIM कार्ड छैन।"</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"फोनमा SIM कार्ड छैन।"</string> @@ -1784,6 +1784,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"पिन निकाल्नुअघि पासवर्ड सोध्नुहोस्"</string> <string name="battery_saver_description" msgid="2510530476513605742">"ब्याट्री जीवन सुधार्न, ब्याट्री बचतले आफ्नो उपकरणको प्रदर्शन र कम्पनको सीमा र सबैभन्दा पृष्ठभूमि डेटा कम गर्छ। इमेल, सन्देश, र अन्य अनुप्रयोगहरू जसले तपाईं तिनीहरूलाई नखोले सम्म समिकरण अद्यावधिक नगर्न सक्छ भनि भर पर्छ।\n\nब्याट्री बचतले तपाईँको उपकरण चार्ज हुँदै बेला तपाईँको उपकरण स्वचालित बन्द गर्छ।"</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"तपाईँको <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> डाउनटाइम समाप्त हुँदा सम्म"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"एक मिनेटको लागि"</item> <item quantity="other" msgid="6924190729213550991">"%d मिनेटको लागि"</item> @@ -1792,5 +1796,7 @@ <item quantity="one" msgid="3480040795582254384">"एक घण्टाको लागि"</item> <item quantity="other" msgid="5408537517529822157">"%d घण्टाको लागि"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"अनिश्चित"</string> </resources> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index f50077f7202e..f2564d889ff4 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"uw eigen contactkaart aanpassen"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Hiermee kan de app persoonlijke profielgegevens wijzigen of toevoegen die op uw apparaat zijn opgeslagen, zoals uw naam en contactgegevens. Dit betekent dat de app u kan identificeren en uw profielgegevens naar anderen kan verzenden."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"lichaamssensoren (zoals hartslagmeters)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Toestaan dat de app toegang krijgt tot gegevens van sensoren die u gebruikt om te meten wat er gebeurt in uw lichaam, zoals de hartslag."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Hiermee kan de app toegang krijgen tot gegevens van sensoren die uw lichamelijke conditie controleren, zoals uw hartslag."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"uw sociale stream lezen"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Hiermee kan de app toegang krijgen tot sociale updates van u en uw vrienden en deze synchroniseren. Wees voorzichtig bij het delen van informatie: hiermee kan de app communicatie lezen tussen u en uw vrienden op sociale netwerken, ongeacht de vertrouwelijkheid. Opmerking: deze toestemming kan niet worden afgedwongen voor alle sociale netwerken."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"schrijven naar sociale streams"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Hiermee kan de app het cachebestandssysteem lezen en schrijven."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP-oproepen plaatsen/ontvangen"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Toestaan dat de app SIP-oproepen plaatst en ontvangt."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"nieuwe telecomverbinding registreren"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Hiermee kan de app nieuwe telecomverbindingen registreren."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"telecomverbindingen beheren"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Hiermee kan de app telecomverbindingen beheren."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interactie met scherm in actieve oproep"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Hiermee kan de app bepalen wanneer en hoe de gebruiker het scherm in een actieve oproep te zien krijgt."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"communicatie met telefonische diensten"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Opnieuw proberen"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Nogmaals proberen"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Maximaal aantal pogingen voor Ontgrendelen via gezichtsherkenning overschreden"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Opladen, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Opgeladen"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Sluit de oplader aan."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Geen simkaart"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Geen SIM-kaart in tablet."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Geen SIM-kaart in telefoon."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Vragen om wachtwoord voordat items worden losgemaakt"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Accubesparing beperkt de prestaties van uw apparaat, de trilfunctie en de meeste achtergrondgegevens om de accuduur te verlengen.\n\nAccubesparing wordt automatisch uitgeschakeld wanneer uw apparaat wordt opgeladen."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Totdat uw downtime eindigt om <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Eén minuut"</item> <item quantity="other" msgid="6924190729213550991">"%d minuten"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Eén uur"</item> <item quantity="other" msgid="5408537517529822157">"%d uur"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Voor onbepaalde tijd"</string> </resources> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 9828832ae095..69ddf8391a9d 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"zmiana własnej karty kontaktu"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Pozwala aplikacji na zmianę lub dodanie osobistych informacji przechowywanych w Twoim profilu na urządzeniu (np. imienia i nazwiska lub adresu). Oznacza to, że aplikacja może Cię zidentyfikować i wysłać informacje z Twojego profilu do innych osób."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"czujniki ciała (np. monitorujące tętno)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Zezwala aplikacji na dostęp do danych z czujników mierzących procesy zachodzące w ciele, np. bicie serca (tętno)."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Pozwala aplikacji na dostęp do danych z czujników, które monitorują Twój stan fizyczny (np. tętno)."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"odczyt sieci społecznościowych"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Pozwala aplikacji na odczyt i synchronizację informacji publikowanych przez Ciebie i Twoich znajomych w sieciach społecznościowych. Zachowaj ostrożność, udostępniając informacje. Aplikacja z tym uprawnieniem może odczytać całą komunikację, którą prowadzisz ze swoimi znajomymi w sieciach społecznościowych, niezależnie od jej poufności. Uwaga: to uprawnienie może nie być egzekwowane we wszystkich sieciach społecznościowych."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"zapis sieci społecznościowych"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Pozwala aplikacji na odczyt i zapis w systemie plików pamięci podręcznej."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"wykonywanie/odbieranie połączeń SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Pozwala aplikacji na wykonywanie i odbieranie połączeń SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"rejestrowanie nowych połączeń telekomunikacyjnych"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Zezwala aplikacji na rejestrowanie nowych połączeń telekomunikacyjnych."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"zarządzanie połączeniami telekomunikacyjnymi"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Zezwala aplikacji na zarządzanie połączeniami telekomunikacyjnymi."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interakcje z ekranem połączenia"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Zezwala aplikacji na kontrolowanie, kiedy i w jaki sposób użytkownik widzi ekran połączenia."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"korzystanie z usług telefonii"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Spróbuj ponownie."</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Spróbuj ponownie."</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Przekroczono maksymalną liczbę prób rozpoznania twarzy."</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Ładowanie (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Naładowany"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Podłącz ładowarkę."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Brak karty SIM"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Brak karty SIM w tablecie."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Brak karty SIM w telefonie."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Aby odpiąć, poproś o hasło"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Aby wydłużyć czas pracy baterii, Oszczędzanie baterii ogranicza aktywność urządzenia, w tym wibracje i przetwarzanie większości danych w tle. Poczta, SMS i inne synchronizowane aplikacje mogą nie aktualizować swojej zawartości, dopóki ich nie otworzysz.\n\nOszczędzanie baterii wyłącza się automatycznie podczas ładowania urządzenia."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Do zakończenia przestoju o <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Przez minutę"</item> <item quantity="other" msgid="6924190729213550991">"Przez %d min"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Przez 1 godz."</item> <item quantity="other" msgid="5408537517529822157">"Przez %d godz."</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Na czas nieokreślony"</string> </resources> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 90d3b7514176..84100f075aee 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"modificar o próprio cartão de contacto"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permite que a aplicação altere ou adicione dados de perfil pessoais guardados no dispositivo, tais como o seu nome e informações de contacto. Isto significa que outras aplicações podem identificá-lo e enviar os seus dados de perfil a terceiros."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"sensores corporais (como monitores do ritmo cardíaco)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Permite à aplicação aceder a dados de sensores que o utilizador usa para medir o que está a acontecer no seu corpo, por exemplo o ritmo cardíaco."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Permite que a aplicação aceda a dados de sensores que monitorizam a sua condição física, como o ritmo cardíaco."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"ler o seu fluxo social"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permite que a aplicação aceda e sincronize atualizações de redes sociais suas e dos seus amigos. Tenha cuidado ao partilhar informações, pois esta ação permite que a aplicação leia comunicações entre si e os seus amigos nas redes sociais, independentemente do grau de confidencialidade. Nota: esta autorização pode não ser aplicada a todas as redes sociais."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"escrever para o seu fluxo social"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permite à aplicação ler e escrever no sistema de ficheiros da cache."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"efetuar/receber chamadas SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Permite que a aplicação efetue e receba chamadas SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"registar novas ligações de telecomunicação"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Permite que a aplicação registe novas ligações de telecomunicação."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"gerir ligações de telecomunicação"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Permite que a aplicação faça a gestão das ligações de telecomunicação."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interagir com o ecrã durante uma chamada"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Permite que a aplicação controle quando e como o utilizador vê o ecrã durante uma chamada."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"Interagir com serviços telefónicos"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Tentar novamente"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Tentar novamente"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Excedido o n.º máximo de tentativas de Desbloqueio Através do Rosto"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"A carregar, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Carregado"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Ligue o carregador."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Nenhum cartão SIM"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nenhum cartão SIM no tablet."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Nenhum cartão SIM no telefone."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pedir palavra-passe antes de soltar"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Para ajudar a melhorar a duração da bateria, a poupança de bateria reduz o desempenho do dispositivo e limita a vibração e a maior parte dos dados de segundo plano. O email, as mensagens e outras aplicações que dependem da sincronização não podem ser atualizados, exceto se os abrir.\n\nA poupança de bateria desliga-se automaticamente quando o dispositivo estiver a carregar."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Até o período de inatividade terminar às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Durante um minuto"</item> <item quantity="other" msgid="6924190729213550991">"Durante %d minutos"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Durante uma hora"</item> <item quantity="other" msgid="5408537517529822157">"Durante %d horas"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidamente"</string> </resources> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 1f8283b4a314..3c0ab1ea6fa2 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"mod. próprio cartão contato"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permite que o app altere ou adicione informações pessoais de perfil armazenadas em seu dispositivo, como seu nome e informações de contato. Isso significa que o app pode identificá-lo e enviar as informações de seus perfil para terceiros."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"sensores corporais"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Permite que o app acesse dados de sensores usados para medir o que acontece em seu corpo, como seus batimentos cardíacos."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Permite que o app acesse dados de sensores que monitoram sua condição física, como a frequência cardíaca."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"ler suas transmissões sociais"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permite que o app acesse e sincronize suas atualizações sociais e as de seus amigos. Tenha cuidado ao compartilhar informações: isto permite que o app leia as mensagens trocadas por você e seus amigos em redes sociais, independentemente de sua confidencialidade. Obsservaç: pode não ser aplicável a todas as redes sociais."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"escrever p/ suas transm. soc."</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permite que o app leia e grave o sistema de arquivos cache."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"fazer/receber chamadas SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Permite que o app faça e receba chamadas SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"registrar nova conexão de telecomunicações"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Permite que o app registre novas conexões de telecomunicações."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"gerenciar conexões de telecomunicações"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Permite que o app gerencie conexões de telecomunicações."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interagir com chamada na tela"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Permite que o app controle quando e como o usuário visualiza a chamada na tela."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"interagir com os serviços de telefonia"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Tente novamente"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Tente novamente"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"O número máximo de tentativas de Desbloqueio por reconhecimento facial foi excedido"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Carregando, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Carregado"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Conecte o seu carregador."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Sem cartão SIM"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Não há um cartão SIM no tablet."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Não há um cartão SIM no telefone."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pedir senha antes de liberar"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Para ajudar a melhorar a vida útil da bateria, a economia de bateria reduz o desempenho do dispositivo e restringe a vibração e a maioria dos dados em segundo plano. É possível que apps de e-mail, mensagens, entre outros que dependem de sincronização não sejam atualizados a menos que sejam abertos.\n\nA economia de bateria é desativada automaticamente quando o dispositivo estiver carregando."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Até o período de inatividade terminar às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Por 1 minuto"</item> <item quantity="other" msgid="6924190729213550991">"Por %d minutos"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Por 1 hora"</item> <item quantity="other" msgid="5408537517529822157">"Por %d horas"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidamente"</string> </resources> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index de3201b346c9..6ae7f52bba49 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"modifică cartea dvs. de vizită"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permite aplicaţiei să schimbe sau să adauge conţinut în informaţiile personale din profil stocate pe dispozitivul dvs., cum ar fi numele şi informaţiile dvs. de contact. Aceasta înseamnă că aplicaţia vă poate identifica şi poate trimite informaţiile din profilul dvs. altor persoane."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"senzori (ex.: senzori de ritm cardiac)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Permite aplicației să acceseze datele de la senzorii pe care îi utilizați pentru a măsura funcțiile corpului, cum ar fi ritmul cardiac."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Permite aplicației să acceseze date de la senzorii care vă monitorizează starea fizică, cum ar fi ritmul cardiac."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"citeşte fluxul social"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permite aplicaţiei să acceseze şi să sincronizeze actualizările sociale de la dvs. şi de la prietenii dvs. Daţi dovadă de precauţie când distribuiţi informaţii - cu această permisiune aplicaţia citeşte comunicările realizate între dvs. şi prietenii dvs. în reţelele sociale, indiferent de gradul de confidenţialitate a acestora. Notă: această permisiune nu poate fi aplicată pentru toate reţelele sociale."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"scrie în fluxul social"</string> @@ -716,6 +716,14 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permite aplicaţiei să scrie şi să citească sistemul de fişiere cache."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"efectuarea/primirea apelurilor SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Permite aplicației să efectueze și să primească apeluri SIP."</string> + <!-- no translation found for permlab_register_provider (2654513709546459553) --> + <skip /> + <!-- no translation found for permdesc_register_provider (7571533832018681544) --> + <skip /> + <!-- no translation found for permlab_connection_manager (1116193254522105375) --> + <skip /> + <!-- no translation found for permdesc_connection_manager (5925480810356483565) --> + <skip /> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interacțiune cu ecranul în timpul unui apel"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Permite aplicației să controleze când și cum vede utilizatorul ecranul în timpul unui apel."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"să interacționeze cu servicii de telefonie"</string> @@ -905,10 +913,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Încercaţi din nou"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Încercaţi din nou"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"S-a depăşit numărul maxim de încercări pentru Deblocare facială"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Se încarcă, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Încărcată"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Conectaţi încărcătorul."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Niciun card SIM"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nu există card SIM în computerul tablet PC."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Telefonul nu are card SIM."</string> @@ -1776,6 +1780,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicită parola înainte de a anula fixarea"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Pentru a ajuta la îmbunătățirea duratei bateriei, modul Economisirea bateriei reduce performanțele dispozitivului și limitează vibrațiile și majoritatea datelor de fundal. Mesajele prin e-mail și alte aplicații care se bazează pe sincronizare nu se vor actualiza dacă nu le deschideți.\n\nEconomisirea baterie se dezactivează automat când dispozitivul se încarcă."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Până când inactivitatea dvs. se încheie la <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Timp de un minut"</item> <item quantity="other" msgid="6924190729213550991">"Timp de %d (de) minute"</item> @@ -1784,5 +1792,7 @@ <item quantity="one" msgid="3480040795582254384">"Timp de o oră"</item> <item quantity="other" msgid="5408537517529822157">"Timp de %d (de) ore"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Nedefinit"</string> </resources> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 913a3165fbee..c12a0c8f6638 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"Изменение ваших контактных данных"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Приложение сможет изменять вашу личную информацию (например, имя и контактные данные), сохраненную на устройстве. Получив эти данные, приложение сможет отправить их другим пользователям."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"датчики (например, пульсометр)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Приложение получит доступ к данным приборов, используемых для измерения ваших физиологических показателей (например, пульса)."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Приложение сможет получить доступ к данным датчиков, размещенных на теле, например измеряющих частоту сердцебиения."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"Просмотр записей в вашей социальной ленте"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Приложение сможет просматривать и синхронизировать записи, публикуемые вами и вашими друзьями в социальных сетях. Будьте осторожны при передаче информации! С этим разрешением приложение сможет просматривать вашу переписку с друзьями в социальных сетях независимо от настроек конфиденциальности. Примечание. Это разрешение может применяться не во всех социальных сетях."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"Добавление записей в вашу социальную ленту"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Приложение сможет выполнять чтение и запись в файловую систему кеша."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"Входящие и исходящие вызовы SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Разрешить вызовы по протоколу SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"регистрация подключений"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Регистрация новых сетевых подключений."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"управление подключениями"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Управление сетевыми подключениями."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"Управление экраном во время разговора"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Управление экраном во время разговора."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"доступ к службам телефонии"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Повторите попытку"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Повторите попытку"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Все попытки войти с помощью Фейсконтроля использованы"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Идет зарядка (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Заряжено"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Подключите зарядное устройство"</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Нет SIM-карты"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"SIM-карта не установлена."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"SIM-карта не установлена."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Запрашивать пароль для отключения блокировки"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Чтобы продлить время работы устройства от батареи, в режиме энергосбережения снижается производительность, а также ограничивается использование вибросигнала и фоновой передачи данных. Данные, требующие синхронизации, могут обновляться только когда вы откроете приложение.\n\nРежим энергосбережения автоматически отключается во время зарядки устройства."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"До отключения режима (в <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>)"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"1 мин."</item> <item quantity="other" msgid="6924190729213550991">"%d мин."</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"1 ч."</item> <item quantity="other" msgid="5408537517529822157">"%d ч."</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Бессрочно"</string> </resources> diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml index d94be04399d8..b8042f7e7d12 100644 --- a/core/res/res/values-si-rLK/strings.xml +++ b/core/res/res/values-si-rLK/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"ඔබගේ සම්බන්ධතා පත වෙනස් කිරීම"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"ඔබගේ නම සහ සම්බන්ධතා තොරතුරු වැනි ඔබගේ උපාංගයේ ආචයනය කරන ලද පුද්ගලික පැතිකඩ තොරතුරු වෙනස් කිරීමට හෝ එකතු කිරීමට යෙදුමට අවසර දෙන්න. මෙමගින් යෙදුමට ඔබව හඳුනා ගත හැකි අතර අනෙක් අයට ඔබගේ පැතිකඩ තොරතුරු යැවිය හැකි බව කියවෙයි."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"සිරුර සංවේදකයන් (හෘද ස්පන්දන වේගය නිරීක්ෂණය කිරීම වැනි)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"හෘද ස්පන්දන වේගය වැනි ඔබගේ සිරුර තුළ සිදුවන්නේ කුමක් දැයි මැනීමට ඔබ භාවිත කරන සංවේදකයන්ගෙන් දත්ත ලබාගැනීමට යෙදුමට ඉඩ ලබාදෙන්න."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"හෘද ස්පන්දන වේගය වැනි ඔබගේ ශාරීරික තත්ත්වය නිරීක්ෂණය කරන සංවේදක වලින් දත්ත ලබාගැනීමට යෙදුමට ඉඩ දෙන්න."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"ඔබගේ සමාජ ප්රවාහය කියවන්න"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"ඔබගේ සහ ඔබගේ යහළුවන්ගේ සමාජ යාවත්කාලීනයන් වෙත පිවිසීමට හෝ සමමුහුර්ත කිරීමට යෙදුමට අවසර දෙන්න. තොරතුරු බෙදා ගැනීමේ දී සැලකිලිමත් වන්න -- විශ්වාසයකින් තොරව සමාජ ජාලවල ඔබගේ සහ ඔබගේ යහළුවන් අතර සන්නිවේදන කියවීමට මෙමගින් යෙදුමට අවසර දෙයි. සටහන: සියලු සමාජ ජාලවල මෙම අවසරය බල නොකරයි."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"ඔබගේ සමාජ ප්රවාහය වෙත ලිවීම"</string> @@ -716,6 +716,14 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"හැඹිලි ගොනු පද්ධති කියවීමට සහ ලිවීමට යෙදුමට අවසර දෙන්න."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP ඇමතුම් සිදුකිරීමට/ලබාගැනීමට"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"SIP ඇමතුම් සිදුකිරීමට සහ ලබාගැනීමට යෙදුමට ඉඩ දෙන්න."</string> + <!-- no translation found for permlab_register_provider (2654513709546459553) --> + <skip /> + <!-- no translation found for permdesc_register_provider (7571533832018681544) --> + <skip /> + <!-- no translation found for permlab_connection_manager (1116193254522105375) --> + <skip /> + <!-- no translation found for permdesc_connection_manager (5925480810356483565) --> + <skip /> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"ලැබෙන ඇමතුම් තිරය සමග අන්තර් ක්රියාකාරී වන්න"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ලැබෙන ඇමතුම් තිරය පරිශීලකයාට පෙනෙන්නේ කෙදිනද සහ කෙසේද යැයි පාලනය කිරීමට යෙදුමට අවසර දෙන්න."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"දුරකථන සේවාවන් සමඟ සම්බන්ධ වීම"</string> @@ -905,10 +913,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"නැවත උත්සාහ කරන්න"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"නැවත උත්සාහ කරන්න"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"මුහුණ භාවිතයෙන් අඟුළු හැරීමේ උපරිම ප්රයන්තයන් ගණන ඉක්මවා ඇත"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"ආරෝපණය වෙමින්, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"අරෝපිතයි"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"ඔබගේ ආරෝපකයට සම්බන්ධ කරන්න."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM පත නැත"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ටැබ්ලටයේ SIM පත නොමැත."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"දුරකථනය තුළ SIM පත නැත."</string> @@ -1778,6 +1782,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ගැලවීමට පෙර මුරපදය විමසන්න"</string> <string name="battery_saver_description" msgid="2510530476513605742">"බැටරියේ ජීව කාලය දියුණු කිරීමට උදව් කිරීමට, ඔබගේ උපාංගයේ ක්රියාකාරිත්වය සහ සීමා කළ කම්පනයන් සහ බොහොමයක් පසුබිම් දත්ත බැටරි සුරැකීමෙන් අඩු කරයි. සමමුහුර්ත කිරීම බලාපොරොත්තු වෙන ඊ-තැපෑල, පණිවිඩ යැවීම සහ වෙනත් යෙදුම් යාවත්කාලීන වන්නේ ඔබ ඒවා විවෘත කළ විට පමණි.\n\nඔබගේ උපාංගය ආරෝපණය වන විට බැටරි සුරැකීම ස්වයංක්රීයව අක්රිය වේ."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"ඔබගේ බිඳවැටුම් වේලාව <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> දී අවසන්වන තුරු"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"විනාඩි එකක් සඳහා"</item> <item quantity="other" msgid="6924190729213550991">"විනාඩි %d සඳහා"</item> @@ -1786,5 +1794,7 @@ <item quantity="one" msgid="3480040795582254384">"පැයක් සඳහා"</item> <item quantity="other" msgid="5408537517529822157">"පැය %d ක් සඳහා"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"අනියත ආකාරයට"</string> </resources> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index bed560f2699a..2ac1c56632e3 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"upraviť vlastnú kartu kontaktu"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Umožňuje aplikácii zmeniť alebo pridať do osobného profilu informácie uložené vo vašom zariadení, ako je vaše meno a kontaktné informácie. Znamená to, že vás aplikácia môže identifikovať a odoslať informácie o vašom profile ostatným aplikáciám."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"telesné senzory (napr. snímače tepu)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Umožňuje aplikácii pristupovať k údajom zo senzorov, pomocou ktorých meriate činnosť svojho tela, napríklad tep."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Umožňuje aplikácii získať prístup k údajom senzorov monitorujúcich vašu fyzickú kondíciu (napríklad pulz)."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"čítať váš sociálny stream"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Umožňuje aplikácii pristupovať k sociálnym aktualizáciám od vás a vašich priateľov a synchronizovať ich. Pri zdieľaní informácií dávajte pozor – toto povolenie umožňuje aplikácii čítať komunikáciu medzi vami a vašimi priateľmi v sociálnych sieťach, a to bez ohľadu na jej dôvernosť. Poznámka: Toto povolenie nie je možné vynucovať v prípade všetkých sociálnych sietí."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"písať do vášho sociálneho streamu"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Umožňuje aplikácii čítať a zapisovať do súborového systému vyrovnávacej pamäte."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"uskutočňovanie/príjem hovorov SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Umožňuje aplikácii uskutočňovať a prijímať hovory SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"registrácia nových pripojení telefonických sietí"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Povoľuje aplikácii registrovať nové pripojenia telekomunikačnej siete."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"správa pripojení telefonických sietí"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Povoľuje aplikácii spravovať pripojenia telekomunikačnej siete."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interakcia s obrazovkou hovoru"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Umožňuje aplikácii ovládať, kedy a ako sa používateľovi zobrazí obrazovka hovoru."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"komunikovať s telefonickými službami"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Skúsiť znova"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Skúsiť znova"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Prekročili ste maximálny povolený počet pokusov o odomknutie tvárou"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Prebieha nabíjanie, <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Nabitá batéria"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Pripojte nabíjačku."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Nie je vložená karta SIM"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"V tablete nie je žiadna karta SIM."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"V telefóne nie je žiadna karta SIM."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pred uvoľnením požiadať o heslo"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Na predĺženie výdrže batérie šetrič batérie znižuje výkonnosť zariadenia a obmedzuje vibrácie a prenos údajov na pozadí. E-mail, správy a ďalšie aplikácie, ktoré používajú synchronizáciu, sa možno nebudú aktualizovať, dokiaľ ich neotvoríte.\n\nPri nabíjaní zariadenia sa šetrič batérie automaticky vypne."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Dokým o <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> neskončí výpadok"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Na jednu minútu"</item> <item quantity="other" msgid="6924190729213550991">"Na %d min"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Na 1 h"</item> <item quantity="other" msgid="5408537517529822157">"Na %d h"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Natrvalo"</string> </resources> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index 5a6ed07e6c60..fc7d93e045ee 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"spreminj. vaše osebne vizitke"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Aplikaciji omogoča spreminjanje ali dodajanje osebnih podatkov v profilu, ki so shranjeni v napravi, na primer ime in podatki za stik. To pomeni, da vas lahko aplikacija prepozna in vaše podatke v profilu pošlje drugim."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"tipala telesnih funkcij (npr. merilniki srčnega utripa)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Aplikaciji dovoli dostop do podatkov tipal, ki jih uporabljate za merjenje procesov v telesu, kot je srčni utrip."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Aplikaciji omogoča dostop do podatkov tipal, ki nadzirajo vaše fizično stanje, med drugim vaš srčni utrip."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"branje vašega družabnega toka"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Aplikaciji omogoča dostop do vaših objav in objav vaših prijateljev v družabnih omrežjih ter njihovo sinhronizacijo. Previdno pri objavljanju informacij – aplikacija lahko s tem bere komunikacijo med vami in prijatelji v družabnih omrežjih, ne glede na zasebnost. Opomba: Tega dovoljenja ni mogoče uveljaviti v vseh družabnih omrežjih."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"pisanje v vaš družabni tok"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Aplikaciji omogoča branje in pisanje v datotečni sistem predpomnilnika."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"opravljanje/sprejemanje klicev SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Aplikaciji omogoča opravljanje in sprejemanje klicev SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"registriranje nove telekomunikacijske povezave"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Aplikaciji omogoča registriranje novih telekomunikacijskih povezav."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"upravljanje telekomunikacijskih povezav"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Aplikaciji omogoča upravljanje telekomunikacijskih povezav."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interakcija z zaslonom pri klicu"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Aplikaciji omogoča nadzor nad tem, kdaj in kako uporabnik vidi zaslon pri klicu."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"uporaba telefonskih storitev"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Poskusi znova"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Poskusite znova"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Presegli ste dovoljeno število poskusov odklepanja z obrazom"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Polnjenje (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Napolnjeno"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Priključite napajalnik."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Ni kartice SIM"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"V tabličnem računalniku ni kartice SIM."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"V telefonu ni kartice SIM."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pred odpenjanjem vprašaj za geslo"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Varčevanje z energijo akumulatorja poveča čas delovanja akumulatorja, tako da zmanjša zmogljivost delovanja naprave in omeji vibriranje ter prenos večine podatkov v ozadju. Aplikacije za e-pošto, sporočanje in drugo, ki uporabljajo sinhroniziranje, se morda ne posodabljajo, razen če jih odprete.\n\nVarčevanje z energijo se samodejno izklopi med polnjenjem akumulatorja naprave."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Do konca prekinitve delovanja ob <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Za eno minuto"</item> <item quantity="other" msgid="6924190729213550991">"Za %d min"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Za eno uro"</item> <item quantity="other" msgid="5408537517529822157">"Za %d h"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Za nedoločen čas"</string> </resources> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index a2c21280c0f8..4b44223fb0a2 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"измена ваше контакт картице"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Дозвољава апликацији да мења или додаје нове личне информације о профилу ускладиштене на уређају, као што су име и контакт информације. То значи да апликација може да вас идентификује и шаље другима информације о профилу."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"телесни сензори (нпр. срчани монитор)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Дозвољава апликацији да приступа подацима сензора које користите за мерење телесних функција, као што је срчани пулс."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Дозвољава апликацији да приступа подацима са сензора који надгледају физичку кондицију, као што је број откуцаја срца."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"читање друштвеног стрима"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Дозвољава апликацији да приступа вашим друштвеним ажурирањима и друштвеним ажурирањима пријатеља и да их синхронизује. Будите опрезни када делите информације – ово омогућава апликацији да чита преписке између вас и пријатеља на друштвеним мрежама, без обзира на поверљивост. Напомена: Ова дозвола се можда не примењује на све друштвене мреже."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"писање у друштвени стрим"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Дозвољава апликацији да чита систем датотека кеша и уписује податке у њега."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"упућивање/пријем SIP позива"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Омогућава апликацији да упућује и прима SIP позиве."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"регистровање нових веза са телекомуникационим мрежама"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Дозвољава апликацији да региструје нове везе са телекомуникационим мрежама."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"управљање везама са телекомуникационим мрежама"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Дозвољава апликацији да управља везама са телекомуникационим мрежама."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"комуницирај са екраном током позива"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Дозвољава апликацији да контролише када и како се кориснику приказује екран током позива."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"да ступа у интеракцију са телефонским услугама"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Покушајте поново"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Покушајте поново"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Премашен је највећи дозвољени број покушаја Откључавања лицем"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Пуњење, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Напуњено"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Повежите пуњач."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Нема SIM картице"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"У таблету нема SIM картице."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"У телефон није уметнута SIM картица."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Тражи лозинку пре откачињања"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Да би смањила потрошњу батерије, Штедња батерије снижава перформансе уређаја, ограничава вибрацију и већину позадинских података. Имејл, размена порука и друге апликације које се ослањају на синхронизацију се можда неће ажурирати ако их не отворите.\n\nШтедња батерије се аутоматски искључује када се уређај пуни."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Док се прекид рада не заврши у <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Један минут"</item> <item quantity="other" msgid="6924190729213550991">"%d мин"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Један сат"</item> <item quantity="other" msgid="5408537517529822157">"%d с"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Бесконачно"</string> </resources> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index a9a7891e85cc..90085291c8e3 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"ändra ditt eget kontaktkort"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Tillåter att appen ändrar eller lägger till personliga profiluppgifter som sparats på din enhet, till exempel ditt namn och dina kontaktuppgifter. Det innebär att appen kan identifiera dig och skicka profiluppgifter till andra."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"kroppssens. (för hjärtat m.m.)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Tillåter att appen får åtkomst till data från sensorer som används för att mäta vad som sker inuti kroppen, till exempel hjärtfrekvens."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Ger appen åtkomst till information från sensorer om ditt fysiska tillstånd, till exempel din puls."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"läs mitt sociala flöde"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Tillåter att appen kommer åt och synkroniserar sociala uppdateringar från dig och dina vänner. Var försiktig när du delar information – med den här behörigheten tillåts appen att läsa kommunikation mellan dig och dina vänner på sociala nätverk oavsett sekretessnivå. Observera att den här behörigheten kanske inte är tillämplig på alla sociala nätverk."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"skriv till mitt sociala flöde"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Tillåter att appen läser och skriver till cachefilsystemet."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"gör/ta emot SIP-anrop"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Tillåter att appen gör och tar emot SIP-anrop."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"registrera ny telekommunikationsanslutning"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Tillåter att appen registrerar nya telekommunikationsanslutningar."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"hantera telekommunikationsanslutningar"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Tillåter att appen hanterar telekommunikationsanslutningar."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interagera med skärmen för inkommande samtal"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Tillåter att appen kontrollerar hur och när användaren ser skärmen för inkommande samtal."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"samverka med telefonitjänster"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Försök igen"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Försök igen"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Du har försökt låsa upp med Ansiktslås för många gånger"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Laddar (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Batteriet har laddats"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Anslut din laddare."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Inget SIM-kort"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Inget SIM-kort i surfplattan."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Inget SIM-kort i telefonen."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Be om lösenord innan skärmen slutar fästas"</string> <string name="battery_saver_description" msgid="2510530476513605742">"I batterisparläget reduceras enhetens prestanda så att batteriet ska räcka längre, och vibration samt den mesta användningen av bakgrundsdata begränsas. Det kan hända att appar för e-post, sms och annat som kräver synkronisering inte uppdateras förrän du öppnar dem.\n\nBatterisparläget inaktiveras automatiskt när enheten laddas."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Tills avbrottstiden är slut <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"I en minut"</item> <item quantity="other" msgid="6924190729213550991">"I %d minuter"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"I en timme"</item> <item quantity="other" msgid="5408537517529822157">"I %d timmar"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"För alltid"</string> </resources> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index d59f445b5dfc..785f2ff1be52 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"rekebisha kadi yako mwenyewe ya mawasiliano"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Inaruhusu programu kubadilisha au kuongeza taarifa ya maelezo mafupi ya kibinafsi yaliyohifadhiwa kwenye kifaa chako, kama vile jina lako na taarifa ya anwani. Hii inamaanisha kuwa programu inaweza kukutambua na inaweza kutuma taarifa ya maelezo yako mafupi kwa wengine."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"vipima hali ya mwili (kama mpigo wa moyo)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Huruhusu programu kufikia data kutoka kwenye vipima mawimbi unavyotumia kupima kinachoendelea mwilini mwako kama vile mpigo wa moyo."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Huruhusu programu kufikia data kutoka vihisi vinavyofuatilia hali yako ya kimwili, kama vile mapigo ya moyo."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"soma mipasho yako wa kijamii"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Huruhusu programu kufikia na kupatanisha masasisho ya kijamii kutoka kwa marafiki zako. Kuwa makini wakati unashiriki taarifa -- hii huruhusu programu kusoma mawasiliano kati yako na marafiki zako kwenye mitandao jamii, bila kujali usiri. Kumbuka: idhini hii haiwezi kutekelezwa kwenye mitandao yote ya jamii."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"kuandikia mipasho yako wa kijamii"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Huruhusu programu kusoma na kuandika mfumo wa faili wa akiba."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"piga/pokea simu za SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Ruhusu programu ipige na kupokea simu za SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"sajili muunganisho mpya wa mawasiliano ya simu"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Huruhusu programu kuandikisha miunganisho mipya ya mawasiliano ya simu."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"dhibiti miunganisho ya mawasiliano ya simu"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Huruhusu programu kudhibiti miunganisho ya mawasiliano ya simu."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"wezesha mwingiliano na skrini ya simu inayoingia"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Huruhusu programu kudhibiti wakati na jinsi mtumiaji anavyoona skrini ya simu inayoingia."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"shirikiana na huduma za simu"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Jaribu tena"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Jaribu tena"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Majaribio ya Juu ya Kufungua Uso yamezidishwa"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Inachaji <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Betri imejaa"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Unganisha chaja yako"</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Hakuna SIM kadi"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Hakuna SIM kadi katika kompyuta ndogo."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Hakuna SIM kadi kwenye simu."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Omba nenosiri kabla hujabandua"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Ili kusaidia kuokoa muda wa matumizi wa betri, kiokoa betri hupunguza utendaji wa kifaa chako na kuzuia kutetema na data nyingi ya chinichini. Barua pepe, kutuma ujumbe na programu zingine zinazotegemea usawazishaji huenda hazitasasisha usipozifungua.\n\nKiokoa betri hujizima kiotomatiki kifaa chako kikianza kuchajiwa."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Hadi <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> wakati wa kutotenda kazi kwa kifaa chako unapoisha"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Kwa dakika moja"</item> <item quantity="other" msgid="6924190729213550991">"Kwa dakika %d"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Kwa saa moja"</item> <item quantity="other" msgid="5408537517529822157">"Kwa saa %d"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Bila kikomo"</string> </resources> diff --git a/core/res/res/values-sw600dp/bools.xml b/core/res/res/values-sw600dp/bools.xml index ddc48c575381..00f45c1512a2 100644 --- a/core/res/res/values-sw600dp/bools.xml +++ b/core/res/res/values-sw600dp/bools.xml @@ -19,7 +19,6 @@ <bool name="show_ongoing_ime_switcher">true</bool> <bool name="kg_share_status_area">false</bool> <bool name="kg_sim_puk_account_full_screen">false</bool> - <bool name="kg_show_ime_at_screen_on">false</bool> <!-- No camera for you, tablet user --> <bool name="kg_enable_camera_default_widget">false</bool> <bool name="kg_center_small_widgets_vertically">true</bool> diff --git a/core/res/res/values-sw720dp/dimens_material.xml b/core/res/res/values-sw720dp/dimens_material.xml new file mode 100644 index 000000000000..3b97b7a17b59 --- /dev/null +++ b/core/res/res/values-sw720dp/dimens_material.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<resources> + + <!-- Preference activity, vertical padding for the header list --> + <dimen name="preference_screen_header_vertical_padding_material">8dp</dimen> + +</resources> diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml index f19420d58d75..8bec63ad05ba 100644 --- a/core/res/res/values-ta-rIN/strings.xml +++ b/core/res/res/values-ta-rIN/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"உங்கள் சொந்த தொடர்பு அட்டையை மாற்றுதல்"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"உங்கள் சாதனத்தில் சேமிக்கப்பட்ட உங்கள் பெயர் மற்றும் தொடர்பு தகவல் போன்ற தனிப்பட்ட சுயவிவரத் தகவலை மாற்ற அல்லது சேர்க்க பயன்பாட்டை அனுமதிக்கிறது. அதாவது பயன்பாடு உங்களை அடையாளப்படுத்தலாம், உங்கள் சுயவிவரத் தகவலை மற்றவர்களுக்கு அனுப்பலாம்."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"உடல் உணர்விகள் (இதயத்துடிப்பு கண்காணித்தல் போன்றவை)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"இதயத் துடிப்பு போன்று உங்கள் உடலில் நிகழும் மாற்றங்களை அளவிட, நீங்கள் பயன்படுத்தும் உணர்விகளிடமிருந்து தரவை அணுக, பயன்பாட்டை அனுமதிக்கிறது."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"உங்கள் இதயத்துடிப்பு விகிதம் போன்ற உங்கள் உடல்நிலையைக் கண்காணிக்கும் உணர்விகளில் இருந்து தரவை அணுக பயன்பாடுகளை அனுமதிக்கும்."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"எனது சமூக ஸ்ட்ரீமைப் படித்தல்"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"உங்களிடமிருந்தும், உங்கள் நண்பர்களிடமிருந்தும் வரும் சமூகப் புதுப்பிப்புகளை அணுகி ஒத்திசைக்கப் பயன்பாட்டை அனுமதிக்கிறது. தகவலைப் பகிரும்போது எச்சரிக்கையாக இருக்கவும் -- ரகசியத்தன்மையைப் பொருட்படுத்தாமல், சமூக நெட்வொர்க்குகளில் உங்களுக்கும், உங்கள் நண்பர்களுக்கிடையேயும் உள்ள தொடர்புகளைப் படிக்க பயன்பாட்டை அனுமதிக்கிறது. குறிப்பு: இந்த அனுமதி எல்லா சமூக நெட்வொர்க்குகளிலும் செயல்படுத்தப்படாமல் இருக்கலாம்."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"உங்கள் சமூக ஸ்ட்ரீமில் எழுதுக"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"தற்காலிகச் சேமிப்பு கோப்பு அமைப்பைப் படிக்க மற்றும் எழுத, பயன்பாட்டை அனுமதிக்கிறது."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP அழைப்புகளைச் செய்தல்/பெறுதல்"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"SIP அழைப்புகளைச் செய்ய/பெற, பயன்பாட்டை அனுமதிக்கிறது."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"புதிய தொலைத்தொடர்பு இணைப்பைப் பதிவுசெய்"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"புதிய தொலைத்தொடர்பு இணைப்புகளைப் பதிவுசெய்ய, பயன்பாட்டை அனுமதிக்கும்."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"தொலைத்தொடர்பு இணைப்புகளை நிர்வகி"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"தொலைத்தொடர்பு இணைப்புகளை நிர்வகிக்க, பயன்பாட்டை அனுமதிக்கும்."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"உள்வரும் அழைப்பிற்கான திரையுடன் ஊடாடுதல்"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"உள்வரும் அழைப்பிற்கான திரையைப் பயனர் எப்போது மற்றும் எப்படிக் காணவேண்டும் என்பதைக் கட்டுப்படுத்துவதற்குப் பயன்பாட்டை அனுமதிக்கிறது."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"டெலிஃபோனி சேவைகளுடனான ஊடாடல்"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"மீண்டும் முயற்சிக்கவும்"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"மீண்டும் முயற்சிக்கவும்"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"முகம் திறப்பதற்கான அதிகபட்ச முயற்சிகள் கடந்தன"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"சார்ஜ் ஏற்றுகிறது, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"சார்ஜ் செய்யப்பட்டது"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"உங்கள் சார்ஜரை இணைக்கவும்."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"சிம் கார்டு இல்லை"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"டேப்லெட்டில் சிம் கார்டு இல்லை."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"தொலைபேசியில் சிம் கார்டு இல்லை."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"அகற்றும் முன் கடவுச்சொல்லைக் கேள்"</string> <string name="battery_saver_description" msgid="2510530476513605742">"பேட்டரியின் ஆயுட்காலத்தை அதிகரிக்க, பேட்டரி சேமிப்பான் சாதனத்தின் செயல்திறனைக் குறைத்து, அதிர்வுறுவதையும் பெரும்பாலான பின்புலத் தரவையும் வரம்பிடுகிறது. ஒத்திசைவைச் சார்ந்திருக்கும் மின்னஞ்சல், மெசேஜ், மேலும் பிற பயன்பாடுகளைத் திறக்கும் வரை, அவை புதுப்பிக்கப்படாமல் இருக்கலாம்.\n\nசாதனம் சார்ஜ் ஆகும் போது, பேட்டரி சேமிப்பான் தானாகவே முடக்கப்படும்."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> முடியும் வரை"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"ஒரு நிமிடம்"</item> <item quantity="other" msgid="6924190729213550991">"%d நிமிடங்கள்"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"ஒரு மணி நேரம்"</item> <item quantity="other" msgid="5408537517529822157">"%d மணிநேரம்"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"வரையறையற்றது"</string> </resources> diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml index 8bfe52f2a987..0219a9623b9b 100644 --- a/core/res/res/values-te-rIN/strings.xml +++ b/core/res/res/values-te-rIN/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"మీ స్వంత సంప్రదింపు కార్డును సవరించడం"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"మీ పరికరంలో నిల్వ చేయబడిన వ్యక్తిగత ప్రొఫైల్ సమాచారాన్ని అనగా మీ పేరు మరియు సంప్రదింపు సమాచారం వంటివి మార్చడానికి లేదా జోడించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. అనువర్తనం మిమ్మల్ని గుర్తించగలదని మరియు మీ ప్రొఫైల్ సమాచారాన్ని ఇతరులకు పంపగలదని దీని అర్థం."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"శరీర సెన్సార్లు (హృదయ స్పందన మానిటర్లు వంటివి)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"మీ శరీరం లోపల జరిగే వాటిని అంటే హృదయ స్పందన వంటివి కొలవడానికి మీరు ఉపయోగించే సెన్సార్ల నుండి డేటాను ప్రాప్యత చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"మీ శారీరక పరిస్థితిని అనగా మీ గుండె స్పందన రేటు వంటి వాటిని పర్యవేక్షించే సెన్సార్ల నుండి డేటాను ప్రాప్యత చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"మీ సామాజిక ప్రసారాన్ని చదవడం"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"మీరు మరియు మీ స్నేహితులు సమర్పించిన తాజా సామాజిక విషయాలను ప్రాప్యత చేయడానికి మరియు సమకాలీకరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. సమాచారాన్ని భాగస్వామ్యం చేస్తున్నప్పుడు జాగ్రత్తగా ఉండండి -- ఇది గోప్యతతో సంబంధం లేకుండా, మీ మధ్య మరియు మీ స్నేహితుల మధ్య జరిగిన కమ్యూనికేషన్లను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది. గమనిక: ఈ అనుమతి అన్ని సామాజిక నెట్వర్క్ల్లో అమలు చేయబడకపోవచ్చు."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"మీ సామాజిక ప్రసారానికి వ్రాయడం"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"కాష్ ఫైల్సిస్టమ్ను చదవడానికి మరియు వ్రాయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP కాల్లను చేయడానికి/స్వీకరించడానికి"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"SIP కాల్లను చేయడానికి మరియు స్వీకరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"కొత్త టెలికామ్ కనెక్షన్లను నమోదు చేయడం"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"కొత్త టెలికామ్ కనెక్షన్లను నమోదు చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"టెలికామ్ కనెక్షన్లను నిర్వహించడం"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"టెలికామ్ కనెక్షన్లను నిర్వహించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"ఇన్-కాల్ స్క్రీన్తో పరస్పర చర్య చేయడం"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"వినియోగదారునికి ఇన్-కాల్ స్క్రీన్ ఎప్పుడు, ఎలా కనిపించాలనే దాన్ని నియంత్రించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"టెలిఫోన్ సేవలతో పరస్పర చర్య చేయడం"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"మళ్లీ ప్రయత్నించండి"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"మళ్లీ ప్రయత్నించండి"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"ముఖంతో అన్లాక్ ప్రయత్నాల గరిష్ట పరిమితి మించిపోయారు"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"ఛార్జ్ అవుతోంది, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"ఛార్జ్ అయింది"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"మీ ఛార్జర్ను కనెక్ట్ చేయండి."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"సిమ్ కార్డు లేదు"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"టాబ్లెట్లో సిమ్ కార్డు లేదు."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ఫోన్లో సిమ్ కార్డు లేదు."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"అన్పిన్ చేయడానికి ముందు పాస్వర్డ్ కోసం అడుగు"</string> <string name="battery_saver_description" msgid="2510530476513605742">"బ్యాటరీ సామర్థ్యాన్ని మెరుగుపరచడంలో సహాయపడటానికి, బ్యాటరీ సేవర్ మీ పరికరం పనితీరుని తగ్గిస్తుంది మరియు వైబ్రేషన్ను మరియు అత్యధిక నేపథ్య డేటాను పరిమితపరుస్తుంది. అలాగే సమకాలీకరణపై ఆధారపడే ఇమెయిల్, సందేశ సేవ మరియు ఇతర అనువర్తనాలు మీరు వాటిని తెరిస్తే మినహా నవీకరించబడకపోవచ్చు.\n\nమీ పరికరం ఛార్జింగ్లో ఉన్నప్పుడు బ్యాటరీ సేవర్ స్వయంచాలకంగా ఆఫ్ చేయబడుతుంది."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"మీ వృథా సమయం <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>కి ముగిసే వరకు"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"ఒక నిమిషానికి"</item> <item quantity="other" msgid="6924190729213550991">"%d నిమిషాలకి"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"ఒక గంటకు"</item> <item quantity="other" msgid="5408537517529822157">"%d గంటలకు"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"నిరవధికంగా"</string> </resources> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index d9c01bb2cda2..fa6c0e83f632 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"แก้ไขบัตรผู้ติดต่อของคุณเอง"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงหรือเพิ่มข้อมูลโปรไฟล์ส่วนตัวที่จัดเก็บไว้บนอุปกรณ์ของคุณ เช่น ชื่อและข้อมูลติดต่อ ซึ่งหมายความว่าแอปพลิเคชันจะสามารถระบุตัวตนของคุณและส่งข้อมูลโปรไฟล์ของคุณให้แก่ผู้อื่นได้"</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"เซ็นเซอร์ร่างกาย (เช่น วัดอัตราการเต้นของหัวใจ)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"ช่วยให้แอปสามารถเข้าถึงข้อมูลจากเซ็นเซอร์ที่คุณใช้เพื่อวัดความเป็นไปภายในร่างกายของคุณ เช่น อัตราการเต้นของหัวใจ"</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"อนุญาตให้แอปเข้าถึงข้อมูลจากเซ็นเซอร์ที่ตรวจสอบสภาพทางกายภาพ เช่น อัตราการเต้นของหัวใจ"</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"อ่านสตรีมเครือข่ายสังคม"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"อนุญาตให้แอปพลิเคชันเข้าถึงและซิงค์การอัปเดตทางสังคมจากคุณและเพื่อน โปรดแชร์ข้อมูลอย่างระมัดระวังเนื่องจากการอนุญาตนี้ทำให้แอปพลิเคชันสามารถอ่านการติดต่อระหว่างคุณและเพื่อนในเครือข่ายสังคมได้ ไม่ว่าจะมีการรักษาข้อมูลที่เป็นความลับแบบใดก็ตาม หมายเหตุ: การอนุญาตนี้อาจไม่สามารถใช้งานได้กับทุกเครือข่ายสังคม"</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"เขียนในสตรีมเครือข่ายสังคม"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"อนุญาตให้แอปพลิเคชันอ่านและเขียนระบบไฟล์แคช"</string> <string name="permlab_use_sip" msgid="2052499390128979920">"โทร/รับสาย SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"อนุญาตให้แอปโทรและรับสาย SIP"</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"ลงทะเบียนการเชื่อมต่อโทรคมนาคมใหม่"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"อนุญาตให้แอปลงทะเบียนการเชื่อมต่อโทรคมนาคมใหม่"</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"จัดการการเชื่อมต่อโทรคมนาคม"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"อนุญาตให้แอปจัดการการเชื่อมต่อโทรคมนาคม"</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"โต้ตอบกับหน้าจอขณะกำลังใช้สาย"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"อนุญาตให้แอปควบคุมเวลาและลักษณะที่ผู้ใช้เห็นหน้าจอขณะกำลังใช้สาย"</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"โต้ตอบกับบริการโทรศัพท์"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"ลองอีกครั้ง"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"ลองอีกครั้ง"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"มีความพยายามที่จะใช้ Face Unlock เกินขีดจำกัด"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"กำลังชาร์จ, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"ชาร์จแล้ว"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"เสียบที่ชาร์จของคุณ"</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"ไม่มีซิมการ์ด"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ไม่มีซิมการ์ดในแท็บเล็ต"</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ไม่มีซิมการ์ดในโทรศัพท์"</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ขอรหัสผ่านก่อนเลิกตรึง"</string> <string name="battery_saver_description" msgid="2510530476513605742">"เพื่อให้สามารถใช้แบตเตอรี่ได้ยาวนานขึ้น โหมดประหยัดแบตเตอรี่จะลดการทำงานของอุปกรณ์ และจำกัดการสั่นรวมถึงข้อมูลแบ็กกราวด์เกือบทั้งหมด อีเมล การรับส่งข้อความ และแอปอื่นๆ ที่ใช้การซิงค์อาจไม่อัปเดตจนกว่าคุณจะเปิดใช้\n\nโหมดประหยัดแบตเตอรี่จะปิดอัตโนมัติเมื่อชาร์จอุปกรณ์"</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"จนกว่าจะสิ้นสุดช่วงเวลาที่เครื่องไม่ทำงานในเวลา <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"1 นาที"</item> <item quantity="other" msgid="6924190729213550991">"%d นาที"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"1 ชั่วโมง"</item> <item quantity="other" msgid="5408537517529822157">"%d ชั่วโมง"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"ไม่มีกำหนด"</string> </resources> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index 8ba750efcddc..41e271861eff 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"baguhin sarili mo contact card"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Pinapayagan ang app na baguhin ang o magdagdag sa personal na impormasyon ng profile na naka-imbak sa iyong device, gaya ng iyong pangalan at impormasyon sa pakikipag-ugnay. Nangangahulugan ito na makikilala ka ng app at maaari nitong ipadala ang impormasyon ng iyong profile sa iba."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"mga sensor sa katawan (gaya ng mga heart rate monitor)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Pinapayagan ang app na i-access ang data mula sa mga sensor na ginagamit mo upang sukatin kung anong nangyayari sa iyong katawan, gaya ng heart rate."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Pinapayagan ang app na i-access ang data mula sa mga sensor na sumusubaybay sa iyong pisikal na kundisyon, tulad ng iyong heart rate."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"basahin ang iyong social stream"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Pinapayagan ang app na mag-access at mag-sync ng mga social na update mula sa iyo at sa iyong mga kaibigan. Maging maingat kapag nagbabahagi ng impormasyon -- pinapayagan nito ang app na magbasa ng mga pakikipag-ugnayan sa pagitan mo at ng iyong mga kaibigan sa mga social network, ano pa man ang katayuan sa pagiging kumpedensyal nito. Tandaan: hindi maaaring ipatupad ang pahintulot na ito sa lahat ng social network."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"magsulat sa iyong social stream"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Pinapayagan ang app na basahin at isulat ang cache filesystem."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"magsagawa/tumanggap ng mga tawag sa SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Pinapayagan ang app na magsagawa at makatanggap ng mga tawag sa SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"magrehistro ng bagong koneksyon sa telecom"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Pinapayagan ang app na magrehistro ng mga bagong koneksyon sa telecom."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"papamahalaan ang mga koneksyon sa telecom"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Pinapayagan ang app na mamahala ng mga koneksyon sa telecom."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"makipag-ugnayan sa in-call na screen"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Nagbibigay-daan sa app na kontrolin kung kailan at kung paano makikita ng user ang in-call na screen."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"makipag-ugnayan sa mga serbisyo sa telephony"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Subukang muli"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Subukang muli"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Nalagpasan na ang maximum na mga pagtatangka sa Face Unlock"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Nagcha-charge, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Siningil"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Ikonekta ang iyong charger."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Walang SIM card"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Walang SIM card sa tablet."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Walang SIM card sa telepono."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Humingi ng password bago mag-unpin"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Upang makatulong na mas mapatagal ang baterya, binabawasan ng battery saver ang pagganap ng iyong device at nililimitahan ang pag-vibrate at ang karamihan ng data ng background. Hindi maaaring ma-update ang email, pagmemensahe at iba pang mga app na umaasa sa pagsi-sync maliban kung bubuksan mo ang mga ito.\n\nAwtomatikong mao-off ang battery saver kapag nagcha-charge ang iyong device."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Hanggang sa matapos ang iyong downtime nang <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Sa loob ng isang minuto"</item> <item quantity="other" msgid="6924190729213550991">"Sa loob ng %d (na) minuto"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Sa loob ng isang oras"</item> <item quantity="other" msgid="5408537517529822157">"Sa loob ng %d (na) oras"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Walang tiyak na katapusan"</string> </resources> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index ea497edb0705..8ddc7f8ea11e 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"kendi kişi kartınızı değiştirme"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Uygulamaya adınız ve iletişim bilgileriniz gibi cihazınızda saklanan kişisel profil bilgilerini değiştirme veya bunlara ekleme yapma izni verir. Bu izin, uygulamanın sizi tanımlayabileceği ve profil bilgilerinizi başkalarına gönderebileceği anlamına gelir."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"vücut sensörleri (kalp atış hızı takip cihazları gibi)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Uygulamanın, kalp atış hızınız gibi vücudunuzla ilgili olayları ölçmek için kullandığınız sensörlerden gelen verilere erişmesine izin verir."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Uygulamanın, nabzınız gibi fiziksel durumunuzu izleyen sensörlerin gönderdiği verilere erişmesine izin verir."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"sosyal akışınızı okuma"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Uygulamaya size veya arkadaşlarınıza ait sosyal güncellemelere erişme ve bunları senkronize etme izni verir. Bilgi paylaşırken dikkatli olun. Bu izin, uygulamanın sosyal ağlarda sizinle arkadaşlarınız arasındaki iletişimi, gizliliğine bakılmaksızın okumasına olanak sağlar. Not: Bu izin tüm sosyal ağlar için geçerli olmayabilir."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"sosyal akışınıza yazma"</string> @@ -716,6 +716,14 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Uygulamaya, önbellek dosya sisteminde okuma ve yazma yapma izni verir."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP çağrıları yapma/alma"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Uygulamanın SIP çağrıları yapmasına ve almasına izin verir."</string> + <!-- no translation found for permlab_register_provider (2654513709546459553) --> + <skip /> + <!-- no translation found for permdesc_register_provider (7571533832018681544) --> + <skip /> + <!-- no translation found for permlab_connection_manager (1116193254522105375) --> + <skip /> + <!-- no translation found for permdesc_connection_manager (5925480810356483565) --> + <skip /> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"çağrı ekranıyla etkileşimde bulunma"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Uygulamaya, kullanıcının çağrı ekranını ne zaman ve nasıl göreceğini denetleme izni verir."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"telefon hizmetleriyle etkileşimde bulunma"</string> @@ -905,10 +913,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Tekrar deneyin"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Tekrar deneyin"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Yüz Tanıma Kilidi için maksimum deneme sayısı aşıldı"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Şarj oluyor (<xliff:g id="PERCENT">%%</xliff:g><xliff:g id="NUMBER">%d</xliff:g>)"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Şarj oldu"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="PERCENT">%%</xliff:g><xliff:g id="NUMBER">%d</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Şarj cihazınızı takın."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM kart yok"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tablette SIM kart yok."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Telefonda SIM kart yok."</string> @@ -1776,6 +1780,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Sabitlemeyi kaldırmadan önce şifre sor"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Pil tasarrufu, pilin ömrünü uzatmaya yardımcı olmak amacıyla cihazınızın performansını düşürür ve arka plan verilerini sınırlar. E-posta, mesajlaşma ve senkronizasyona dayalı diğer uygulamalar siz açmadığınız müddetçe güncellenemez. \n\nPil tasarrufu, cihaz şarj olurken otomatik olarak kapanır."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Kesinti süreniz <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> saatinde sona erene kadar"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Bir dakika süreyle"</item> <item quantity="other" msgid="6924190729213550991">"%d dakika süreyle"</item> @@ -1784,5 +1792,7 @@ <item quantity="one" msgid="3480040795582254384">"Bir saat süreyle"</item> <item quantity="other" msgid="5408537517529822157">"%d saat süreyle"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Süresiz"</string> </resources> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index 25ba77c69d53..ca66cbb9fd9f 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"змінювати картки контактів"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Дозволяє програмі змінювати чи додавати особисту інформацію профілю, збережену на пристрої, як-от ваше ім’я та контактну інформацію. Це означає, що програма може ідентифікувати вашу особу та надсилати дані вашого профілю іншим."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"датчики на тілі (як-от пульсометр)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Дозволяє додатку отримувати дані з датчиків, які вимірюють фізіологічні процеси, як-от пульс."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Додаток має доступ до даних із датчиків, які відстежують фізичний стан, зокрема пульс."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"читати ваш соціальний потік"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Дозволяє програмі отримувати доступ до оновлень із соціальних мереж від вас і ваших друзів та синхронізувати їх. Будьте обережні, надаючи доступ до інформації – це дозволяє програмі читати повідомлення, якими ви та ваші друзі обмінювалися в соціальних мережах, незалежно від конфіденційності. Зауважте: цей дозвіл не можна застосовувати в усіх соціальних мережах."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"писати у ваш соціальний потік"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Дозволяє програмі читати з файлової системи кеш-пам’яті та писати в неї."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"здійснювати й отримувати дзвінки через протокол SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Додаток зможе здійснювати й отримувати дзвінки через протокол SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"реєстрація нових телекомунікаційних з’єднань"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Додаток може реєструвати нові телекомунікаційні з’єднання."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"керування телекомунікаційними з’єднаннями"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Додаток може керувати телекомунікаційними з’єднаннями."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"взаємодіяти з екраном вхідного дзвінка"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Додаток може контролювати, коли та як користувач бачить екран вхідного дзвінка."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"взаємодіяти з телефонними службами"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Повторіть спробу"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Повторіть спробу"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Перевищено максимальну кількість спроб розблокування за допомогою функції \"Фейсконтроль\""</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Заряджається, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Заряджено"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Підкл. заряд. пристрій."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Відсутня SIM-карта"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"У пристр. нема SIM-карти."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"У тел. немає SIM-карти."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Запитувати пароль перед відкріпленням"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Щоб подовжити час роботи акумулятора, функція заощадження заряду акумулятора знизить продуктивність пристрою й обмежить вібрацію та більшість фонових даних. Електронна пошта, повідомлення й інші додатки, які синхронізуються, можуть не оновлюватися, доки ви їх не відкриєте.\n\nФункція заощадження заряду акумулятора автоматично вимкнеться, коли пристрій заряджатиметься."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Термін простою закінчується о <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Протягом хвилини"</item> <item quantity="other" msgid="6924190729213550991">"Протягом %d хв"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Протягом години"</item> <item quantity="other" msgid="5408537517529822157">"Протягом %d год"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Без обмежень"</string> </resources> diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml index a298353d7a8f..faeab4d54b1b 100644 --- a/core/res/res/values-ur-rPK/strings.xml +++ b/core/res/res/values-ur-rPK/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"اپنے رابطہ کارڈ میں ترمیم کریں"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"ایپ کو آپ کے آلے پر اسٹور کردہ ذاتی پروفائل کی معلومات، جیسے آپ کا نام اور رابطے کی معلومات تبدیل یا اس میں شامل کرنے کی اجازت دیتا ہے۔ اس کا مطلب یہ ہے کہ ایپ آپ کی نشاندہی کرسکتی اور آپ کے پروفائل کی معلومات دوسروں کو بھیج سکتی ہے۔"</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"باڈی سینسرز (جیسے دل کی دھڑکن کے مانیٹرز)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"ایپ کو ان سینسرز سے ڈیٹا تک رسائی کی اجازت دیتا ہے، جنہیں آپ اپنے جسم کے اندر چل رہی چیزوں کی پیمائش کیلئے استعمال کرتے ہیں، جیسے کہ دل کی دھڑکن۔"</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"ان سینسرز سے ڈیٹا تک رسائی حاصل کرنے کی اجازت دیتی ہے جو آپ کی حرکت قلب کی شرح جیسی آپ کی فزیکل صورتحال کو مانیٹر کرتے ہیں۔"</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"اپنا سوشل سلسلہ پڑھیں"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"ایپ کو آپ اور آپ کے دوستوں کے سماجی اپ ڈیٹس تک رسائی حاصل کرنے اور انہیں مطابقت پذیر بنانے کی اجازت دیتا ہے۔ معلومات کا اشتراک کرتے وقت محتاط رہیں -- رازداری سے قطع نظر، یہ سماجی نیٹ ورکس پر آپ اور آپ کے دوستوں کے بیچ مواصلتوں کو پڑھنے کی اجازت دیتا ہے۔ نوٹ: یہ اجازت سبھی سماجی نیٹ ورکس پر نافذ نہیں کی جاسکتی ہے۔"</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"اپنے سوشل سلسلہ میں لکھیں"</string> @@ -716,6 +716,14 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"ایپ کو کیش فائل سسٹم پڑھنے اور لکھنے کی اجازت دیتا ہے۔"</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP کالز کریں/موصول کریں"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"ایپ کو SIP کالز کرنے اور موصول کرنے کی اجازت دیتا ہے۔"</string> + <!-- no translation found for permlab_register_provider (2654513709546459553) --> + <skip /> + <!-- no translation found for permdesc_register_provider (7571533832018681544) --> + <skip /> + <!-- no translation found for permlab_connection_manager (1116193254522105375) --> + <skip /> + <!-- no translation found for permdesc_connection_manager (5925480810356483565) --> + <skip /> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"درون کال اسکرین کے ساتھ تعامل کریں"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ایپ کو صارف کے درون کال اسکرین دیکھنے کے وقت اور طریقے کو کنٹرول کرنے کی اجازت دیتا ہے۔"</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"ٹیلیفونی سروسز کے ساتھ تعامل کریں"</string> @@ -905,10 +913,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"دوبارہ کوشش کریں"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"دوبارہ کوشش کریں"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"چہرہ کے ذریعے غیر مقفل کریں کی زیادہ سے زیادہ کوششوں سے تجاوز کرگیا"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"چارج ہو رہا ہے، <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"چارج ہو گیا"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"اپنا چاجر لگائیں۔"</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"کوئی SIM کارڈ نہیں ہے"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ٹیبلیٹ میں کوئی SIM کارڈ نہیں ہے۔"</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"فون میں کوئی SIM کارڈ نہیں ہے۔"</string> @@ -1776,6 +1780,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"پن ہٹانے سے پہلے پاس ورڈ طلب کریں"</string> <string name="battery_saver_description" msgid="2510530476513605742">"بیٹری کی میعاد بہتر بنانے میں مدد کرنے کیلئے، بیٹری سیور آپ کے آلہ کی کارکردگی میں تخفیف کر دیتی ہے اور وائبریشن اور پس منظر کے زیادہ تر ڈیٹا کو محدود کر دیتی ہے۔ ای میل، پیغام رسانی اور مطابقت پذیری پر انحصار کرنے والی دیگر ایپس ممکن ہے اس وقت تک اپ ڈیٹ نہ ہوں جب تک آپ انہیں نہ کھولیں۔\n\nآپ کا آلہ چارج ہوتے وقت بیٹری سیور خود بخود آف ہو جاتی ہے۔"</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> پر آپ کا آخری وقت ختم ہونے تک"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"ایک منٹ کیلئے"</item> <item quantity="other" msgid="6924190729213550991">"%d منٹ کیلئے"</item> @@ -1784,5 +1792,7 @@ <item quantity="one" msgid="3480040795582254384">"ایک گھنٹے کیلئے"</item> <item quantity="other" msgid="5408537517529822157">"%d گھنٹوں کیلئے"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"غیر متعینہ"</string> </resources> diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml index 41c55478a143..cf426e2ed1bd 100644 --- a/core/res/res/values-uz-rUZ/strings.xml +++ b/core/res/res/values-uz-rUZ/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"shaxsiy kontaktlar kartangizni o‘zgartirish"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Ilovaga qurilmangizga zaxiralangan ismingiz va aloqa ma’lumotlaringiz kabi shaxsiy profillingiz ma’lumotlarini o‘zgartirish yoki ularga ma’lumot qo‘shish imkonini beradi. Bu ilova sizni tanib olishi va profil ma’lumotlaringizni boshqalarga jo‘natishi mumkinligini bildiradi."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"sezgichlar (m-n, yurak urishi)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Ilova sizning jismoniy ko‘rsatkichlaringizni (m-n, yurak urishi) o‘lchaydigan sezgich ma’lumotlariga kirish vakolatini oladi."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Ilovaga sezgichlardan olingan jismoniy holatingiz haqidagi ma’lumotlarni, masalan, yurak urishini kuzatish uchun ruxsat beradi."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"ijtimoiy uzatishni o‘qish"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Ilovaga siz va do‘stlaringizning ijtimoiy tarmoqlaridagi yangiliklarga kirish va ularni sinxronlashga ruxsat beradi. Ma’lumot ulashayotganda ehtiyot bo‘ling -- u ilovaga ijtimoiy tarmoqlarda maxfiyligidan qat’iy nazar siz va do‘stlaringiz o‘rtasidagi yozishmalarni o‘qish imkonini beradi. Diqqat qiling: ushbu ruxsat na barcha ijtimoiy tarmoqlarda talab qilinishi mumkin."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"ijtimoiy uzatishga yozish"</string> @@ -716,6 +716,14 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Ilova kesh fayl tizimini o‘qishi va unga yozishi mumkin."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP qo‘ng‘iroqlarini amalga oshirish/qabul qilish"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Ilovaga SIP qo‘ng‘iroqlarini amalga oshirish va qabul qilish uchun ruxsat beradi."</string> + <!-- no translation found for permlab_register_provider (2654513709546459553) --> + <skip /> + <!-- no translation found for permdesc_register_provider (7571533832018681544) --> + <skip /> + <!-- no translation found for permlab_connection_manager (1116193254522105375) --> + <skip /> + <!-- no translation found for permdesc_connection_manager (5925480810356483565) --> + <skip /> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"suhbat vaqtida ekranni boshqarish"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Ilova suhbat vaqtida ekranni boshqarishi mumkin."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"telefoniya xizmatlarini bilan aloqa qilish"</string> @@ -905,10 +913,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Qaytadan urining"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Qaytadan urining"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Yuzni tanitib qulfni ochishga urinish miqdoridan oshib ketdi"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Quvvatlanyapti: <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Zaryad to‘la"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Zaryadlagichni ulang."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM karta yo‘q"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Planshetingizga SIM karta yo‘q."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Telefoningizga SIM karta yo‘q."</string> @@ -1776,6 +1780,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Bo‘shatishdan oldin parol so‘ralsin"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Batareya quvvatini uzoqroq vaqtga yetkazish uchun quvvat tejash funksiyasi qurilmangiz unumdorligini kamaytiradi hamda uning tebranishi va orqa fonda internetdan foydalanishni cheklaydi. Sinxronlanib turishi lozim bo‘lgan e-pochta, xabar almashinuv va boshqa ilovalar esa ishga tushirilmaguncha yangilanmaydi.\n\nQurilmani quvvat oldirish uchun energiya manbayiga ulashingiz bilanoq, quvvat tejash funksiyasi avtomatik tarzda o‘chadi."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Tanaffus vaqti tugaguncha – <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"1 daqiqa"</item> <item quantity="other" msgid="6924190729213550991">"%d daqiqa"</item> @@ -1784,5 +1792,7 @@ <item quantity="one" msgid="3480040795582254384">"1 soat"</item> <item quantity="other" msgid="5408537517529822157">"%d soat"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Uzluksiz ravishda"</string> </resources> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 222fcfe9401b..5acd5bbec711 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"sửa đổi thẻ liên hệ của riêng bạn"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Cho phép ứng dụng thay đổi hoặc thêm vào thông tin tiểu sử cá nhân được lưu trữ trên thiết bị, chẳng hạn như tên và thông tin liên hệ của bạn. Điều này có nghĩa là ứng dụng có thể xác định danh tính của bạn và gửi thông tin tiểu sử của bạn cho người khác."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"cảm biến cơ thể (như máy đo nhịp tim)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Cho phép ứng dụng truy cập dữ liệu từ cảm biến mà bạn sử dụng để đo những gì đang diễn ra bên trong cơ thể của bạn, chẳng hạn như nhịp tim."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Cho phép ứng dụng truy cập dữ liệu từ bộ cảm biến giám sát tình trạng sức khỏe của bạn, ví dụ như nhịp tim."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"đọc luồng xã hội của bạn"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Cho phép ứng dụng truy cập và đồng bộ hóa các cập nhật xã hội của bạn và bạn bè bạn. Hãy cẩn trọng khi chia sẻ thông tin -- việc này có thể cho phép ứng dụng đọc thông tin liên lạc giữa bạn và bạn bè bạn trên các mạng xã hội, bất kể tính bí mật là gì. Lưu ý: quyền này có thể không được thực thi trên tất cả các mạng xã hội."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"ghi luồng xã hội của bạn"</string> @@ -716,6 +716,14 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Cho phép ứng dụng đọc và ghi hệ thống tệp bộ nhớ cache."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"thực hiện/nhận các cuộc gọi qua SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Cho phép ứng dụng thực hiện và nhận các cuộc gọi qua SIP."</string> + <!-- no translation found for permlab_register_provider (2654513709546459553) --> + <skip /> + <!-- no translation found for permdesc_register_provider (7571533832018681544) --> + <skip /> + <!-- no translation found for permlab_connection_manager (1116193254522105375) --> + <skip /> + <!-- no translation found for permdesc_connection_manager (5925480810356483565) --> + <skip /> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"tương tác với màn hình trong cuộc gọi"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Cho phép ứng dụng kiểm soát thời gian và cách người dùng nhìn thấy màn hình trong cuộc gọi."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"tương tác với dịch vụ điện thoại"</string> @@ -905,10 +913,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Thử lại"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Thử lại"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Đã vượt quá số lần Mở khóa bằng khuôn mặt tối đa"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Đang sạc, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Pin đầy"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Kết nối bộ sạc của bạn."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Không có thẻ SIM nào"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Không có thẻ SIM nào trong máy tính bảng."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Không có thẻ SIM nào trong điện thoại."</string> @@ -1776,6 +1780,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Hỏi mật khẩu trước khi bỏ ghim"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Để giúp tăng tuổi thọ pin, trình tiết kiệm pin sẽ giảm hiệu suất thiết bị của bạn và hạn chế chế rung và hầu hết dữ liệu nền. Email, nhắn tin và các ứng dụng khác dựa trên đồng bộ hóa không thể cập nhật trừ khi bạn mở chúng.\n\nTrình tiết kiệm pin tự động tắt khi thiết bị của bạn đang sạc."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Cho tới khi thời gian ngừng hoạt động của bạn kết thúc vào <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Trong một phút"</item> <item quantity="other" msgid="6924190729213550991">"Trong %d phút"</item> @@ -1784,5 +1792,7 @@ <item quantity="one" msgid="3480040795582254384">"Trong một giờ"</item> <item quantity="other" msgid="5408537517529822157">"Trong %d giờ"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Không giới hạn"</string> </resources> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index d1711b4f8928..f32c8c096761 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"修改您自己的名片"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"允许该应用更改或添加您设备上存储的个人资料信息,例如您的姓名和联系信息。这意味着该应用可以识别您的身份,并可能将您的个人资料信息发送给他人。"</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"人体传感器(如心跳速率检测器)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"允许应用访问您用于测量身体状况(如心跳速率)的传感器中的数据。"</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"允许该应用存取监测您身体状况的传感器所收集的数据,例如您的心率。"</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"读取您的社交信息流"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"允许该应用访问并同步您和朋友的社交动态信息。在分享信息时一定要小心,因为此权限可让该应用读取您与社交网络上的朋友之间的交流信息。"</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"写入您的社交信息流"</string> @@ -716,6 +716,14 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"允许应用读取和写入缓存文件系统。"</string> <string name="permlab_use_sip" msgid="2052499390128979920">"拨打/接听SIP电话"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"允许该应用拨打和接听SIP电话。"</string> + <!-- no translation found for permlab_register_provider (2654513709546459553) --> + <skip /> + <!-- no translation found for permdesc_register_provider (7571533832018681544) --> + <skip /> + <!-- no translation found for permlab_connection_manager (1116193254522105375) --> + <skip /> + <!-- no translation found for permdesc_connection_manager (5925480810356483565) --> + <skip /> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"与通话屏幕互动"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"允许应用控制用户看到通话屏幕的时机和方式。"</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"与电话服务交互"</string> @@ -905,10 +913,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"重试"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"重试"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"已超过“人脸解锁”尝试次数上限"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"正在充电,<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"充电完成"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"连接您的充电器。"</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"没有SIM卡"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"平板电脑中没有SIM卡。"</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"手机中无SIM卡"</string> @@ -1776,6 +1780,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"取消时要求输入密码"</string> <string name="battery_saver_description" msgid="2510530476513605742">"为了延长电池的续航时间,节电助手会降低设备的性能,并限制振动和大部分后台流量。对于电子邮件、聊天工具等依赖于同步功能的应用,可能要打开这类应用时才能收到新信息。\n\n节电助手会在设备充电时自动关闭。"</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"直到休息时间结束(<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>)"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"1分钟"</item> <item quantity="other" msgid="6924190729213550991">"%d分钟"</item> @@ -1784,5 +1792,7 @@ <item quantity="one" msgid="3480040795582254384">"1小时"</item> <item quantity="other" msgid="5408537517529822157">"%d小时"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"无限期"</string> </resources> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index 15a983293343..59ff983b3ba2 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"修改自己的聯絡資料"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"允許應用程式新增或更改裝置上儲存的個人資料,例如您的姓名和聯絡資訊。這表示應用程式可以識別您的身份,並將您的個人資料傳送給他人。"</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"身體感應器 (例如心跳監視器)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"允許應用程式存取用於測量身體狀況感應器的資料,例如心跳。"</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"允許應用程式存取感應器所收集的資料 (這類感應器可監測您的體能狀態,例如您的心跳速率)。"</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"讀取您的社交串流"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"允許應用程式存取並同步處理您和好友的最新動態。當您分享資訊時,請務必小心,因為這項權限允許應用程式讀取您和好友在社交網絡上的私人通訊,不論是否機密。注意:這項權限可能不適用於所有社交網絡。"</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"寫入您的社交串流"</string> @@ -716,6 +716,14 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"允許應用程式讀取及寫入快取檔案系統。"</string> <string name="permlab_use_sip" msgid="2052499390128979920">"撥打/接聽 SIP 電話"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"允許應用程式撥打及接聽 SIP 電話。"</string> + <!-- no translation found for permlab_register_provider (2654513709546459553) --> + <skip /> + <!-- no translation found for permdesc_register_provider (7571533832018681544) --> + <skip /> + <!-- no translation found for permlab_connection_manager (1116193254522105375) --> + <skip /> + <!-- no translation found for permdesc_connection_manager (5925480810356483565) --> + <skip /> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"與通話畫面互動"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"允許應用程式控制通話畫面的顯示時間和方式。"</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"與電話語音服務互動"</string> @@ -905,10 +913,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"再試一次"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"再試一次"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"已超過臉容解鎖嘗試次數上限"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"充電中 (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"充電完成"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"請連接充電器。"</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"找不到 SIM 卡"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"平板電腦中沒有 SIM 卡。"</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"手機中沒有 SIM 卡。"</string> @@ -1776,6 +1780,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"取消固定時必須輸入密碼"</string> <string name="battery_saver_description" msgid="2510530476513605742">"省電模式可延長電池使用時間,但會降低裝置的效能,並限制震動和大部分背景數據傳輸。電郵、短訊及其他需要同步處理的應用程式可能只會在開啟時才會更新。\n\n裝置充電時,省電模式會自動關閉。"</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"直到停機時間於 <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> 結束"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"1 分鐘"</item> <item quantity="other" msgid="6924190729213550991">"%d 分鐘"</item> @@ -1784,5 +1792,7 @@ <item quantity="one" msgid="3480040795582254384">"1 小時"</item> <item quantity="other" msgid="5408537517529822157">"%d 小時"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"無限期"</string> </resources> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index aa2c7852e61c..1848795b73dd 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"修改自己的聯絡資訊"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"允許應用程式新增或變更裝置上儲存的個人資料,例如您的姓名和聯絡資訊。這項設定可讓應用程式識別您的身分,並可能將您的個人資料傳送給他人。"</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"身體感應器 (例如心律監測器)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"允許應用程式存取感應器從您的身體測得的資料,例如心跳頻率。"</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"允許應用程式存取感測器所收集的資料 (這類感測器可監測您的體能狀態,例如您的心跳速率)。"</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"讀取您的社交串流"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"允許應用程式存取並同步處理您和好友的最新動態。因此,當您分享資訊時請小心,因為這項權限可讓應用程式讀取您和好友在社交網路上的私人通訊,包括機密通訊。注意:並非所有社交網路皆適用於這項權限。"</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"寫入您的社交串流"</string> @@ -716,6 +716,14 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"允許應用程式讀取及寫入快取檔案系統。"</string> <string name="permlab_use_sip" msgid="2052499390128979920">"撥打/接聽 SIP 通話"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"允許應用程式撥打及接聽 SIP 通話。"</string> + <!-- no translation found for permlab_register_provider (2654513709546459553) --> + <skip /> + <!-- no translation found for permdesc_register_provider (7571533832018681544) --> + <skip /> + <!-- no translation found for permlab_connection_manager (1116193254522105375) --> + <skip /> + <!-- no translation found for permdesc_connection_manager (5925480810356483565) --> + <skip /> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"與通話螢幕互動"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"允許應用程式控制使用者看到通話螢幕的時機和方式。"</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"與電話語音服務互動"</string> @@ -905,10 +913,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"再試一次"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"再試一次"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"已超過人臉解鎖嘗試次數上限"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"充電中 (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"充電完成"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"請連接充電器。"</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"找不到 SIM 卡"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"平板電腦中沒有 SIM 卡。"</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"手機未插入 SIM 卡。"</string> @@ -1776,6 +1780,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"取消固定時必須輸入密碼"</string> <string name="battery_saver_description" msgid="2510530476513605742">"節約耗電量功能會降低裝置的效能,並限制震動和大多數背景資料,藉此延長電池續航力。此外,電子郵件、簡訊和其他需要使用同步功能的應用程式若未開啟,將不會自動更新。\n\n當您為裝置充電時,節約耗電量功能會自動關閉。"</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"直到 <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> 停機時間結束"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"1 分鐘"</item> <item quantity="other" msgid="6924190729213550991">"%d 分鐘"</item> @@ -1784,5 +1792,7 @@ <item quantity="one" msgid="3480040795582254384">"1 小時"</item> <item quantity="other" msgid="5408537517529822157">"%d 小時"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"無限期"</string> </resources> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index f968a8785280..10d558f4853d 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -494,7 +494,7 @@ <string name="permlab_writeProfile" msgid="907793628777397643">"guqula ikhadi lakho lokuxhumana"</string> <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Ivumela uhlelo lokusebenza ukushintsha noma ingeze ulwazi lomuntu siqu lwephrofayela olulondolozwe kudivayisi yakho, njengegama lakho kanye nolwazi lokuxhumana. Lokhu kuchaza ukuthi ezinye izinhlelo zokusebenza zingakuhlonza bese zithumelela abanye ulwazi lephrofayela yakho."</string> <string name="permlab_bodySensors" msgid="4871091374767171066">"izinzwa zomzimba (njengeziqaphi zokulinganisela inhliziyo)"</string> - <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Ivumela uhlelo lokusebenza ukuze lufinyelele kudatha esuka kuzinzwa ozisebenzisayo ukuze lulinganise ukuthi kwenzakalani phakathi komzimba wakho, njengokulinganisela kwenhliziyo."</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Ivumela uhlelo lokusebenza ukuthi lufinyelele kudatha kusukela kuzinzwa eziqapha isimo sakho somzimba, esifana nesilinganiso senhliziyo yakho."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"funda ngezindlela zakho zokuxhumana nabanye abantu"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Ivumela uhlelo lokusebenza ukufinyelela nokuvumelanisa izibuyekezo zomphakathi ezivela kuwe nakubangani bakho. Qaphela uma waba ulwazi -- lokhu kuvumela uhlelo lokusebenza ukufunda ukuxhumana phakathi kwakho nabangani bakho kumanethiwekhi omphakathi, ngaphandle kokugcinwa kuyimfihlo. Qaphela: le mvume ingaphoqelelwa kuwo onke amanethiwekhi omphakathi."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"bhala indlela yakho yokuxhumana nabantu"</string> @@ -716,6 +716,10 @@ <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Ivumela uhlelo lokusebenza ukuthi ifunde futhi ibhale isistimu yokufayila amafayela esikhashana."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"yenza/thola amakholi we-SIP"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"Ivumela uhlelo lokusebenza ukwenza nokuthola amakholi we-SIP."</string> + <string name="permlab_register_provider" msgid="2654513709546459553">"bhalisa ukuxhumana kwezokuxhumana kwefoni okusha"</string> + <string name="permdesc_register_provider" msgid="7571533832018681544">"Ivumela uhlelo lokusebenza ukuthi lubhalise ukuxhumana kwezokuxhumana kwefoni okusha."</string> + <string name="permlab_connection_manager" msgid="1116193254522105375">"phatha ukuxhumana kwezokuxhumana kwefoni"</string> + <string name="permdesc_connection_manager" msgid="5925480810356483565">"Ivumela uhlelo lokusebenza ukuthi luphathe ukuxhumana kwezokuxhumana kwefoni."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"hlanganyela neskrini esingaphakathi kwekholi"</string> <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Ivumela uhlelo lokusebenza ukuthi lulawule ukuthi umsebenzisi ubona kanjani isikrini esingaphakathi kwekholi."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"sebenzisana namasevisi wefoni"</string> @@ -905,10 +909,6 @@ <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Zama futhi"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Zama futhi"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Ukuzama Kokuvula Ubuso Okuningi kudluliwe"</string> - <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Iyashaja (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="lockscreen_charged" msgid="321635745684060624">"Kushajiwe"</string> - <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="lockscreen_low_battery" msgid="1482873981919249740">"Xhuma ishaja yakho."</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Alikho ikhadi le-SIM."</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Alikho ikhadi le-SIM efonini."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Alikho ikhadi le-SIM efonini."</string> @@ -1776,6 +1776,10 @@ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Cela iphasiwedi ngaphambi kokususa ukuphina"</string> <string name="battery_saver_description" msgid="2510530476513605742">"Ukuze usize ukwenza kangcono impilo yebhethri, isilondolozi sebhethri sehlisa ukusebenza kwedivayisi yakho futhi sikhawulela ukudlidliza nedatha eningi yangasemuva. I-imeyili, imilayezo, nezinye izinhlelo zokusebenza ezincike ekuvumelaniseni kungenzeka zingabuyekezi ngaphandle kokuthi uzivule.\n\nIsilondolozi sebhethri sivaleka ngokuzenzakalelayo uma idivayisi yakho ishaja."</string> <string name="downtime_condition_summary" msgid="8761776337475705749">"Kuze kuphele isikhathi sakho ngo-<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> + <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) --> + <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) --> + <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) --> + <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) --> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Iminithi elilodwa"</item> <item quantity="other" msgid="6924190729213550991">"Amaminithi angu-%d"</item> @@ -1784,5 +1788,7 @@ <item quantity="one" msgid="3480040795582254384">"Ihora elilodwa"</item> <item quantity="other" msgid="5408537517529822157">"Amahora angu-%d"</item> </plurals> + <!-- no translation found for zen_mode_until (7336308492289875088) --> + <skip /> <string name="zen_mode_forever" msgid="4316804956488785559">"Unaphakade"</string> </resources> diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml index a8b5d6d5fe29..bb9885c9d890 100644 --- a/core/res/res/values/arrays.xml +++ b/core/res/res/values/arrays.xml @@ -298,162 +298,75 @@ <item>@drawable/quickcontact_badge_overlay_pressed_light</item> <!-- Material assets --> - <item>@drawable/ab_share_pack_mtrl_alpha</item> - <item>@drawable/ab_solid_shadow_mtrl_alpha</item> - <item>@drawable/btn_cab_done_mtrl_alpha</item> - <item>@drawable/btn_check_to_off_mtrl_000</item> - <item>@drawable/btn_check_to_off_mtrl_001</item> - <item>@drawable/btn_check_to_off_mtrl_002</item> - <item>@drawable/btn_check_to_off_mtrl_003</item> - <item>@drawable/btn_check_to_off_mtrl_004</item> - <item>@drawable/btn_check_to_off_mtrl_005</item> - <item>@drawable/btn_check_to_off_mtrl_006</item> - <item>@drawable/btn_check_to_off_mtrl_007</item> - <item>@drawable/btn_check_to_off_mtrl_008</item> - <item>@drawable/btn_check_to_off_mtrl_009</item> - <item>@drawable/btn_check_to_off_mtrl_010</item> - <item>@drawable/btn_check_to_off_mtrl_011</item> - <item>@drawable/btn_check_to_off_mtrl_012</item> - <item>@drawable/btn_check_to_off_mtrl_013</item> - <item>@drawable/btn_check_to_off_mtrl_014</item> - <item>@drawable/btn_check_to_off_mtrl_015</item> - <item>@drawable/btn_check_to_on_mtrl_000</item> - <item>@drawable/btn_check_to_on_mtrl_001</item> - <item>@drawable/btn_check_to_on_mtrl_002</item> - <item>@drawable/btn_check_to_on_mtrl_003</item> - <item>@drawable/btn_check_to_on_mtrl_004</item> - <item>@drawable/btn_check_to_on_mtrl_005</item> - <item>@drawable/btn_check_to_on_mtrl_006</item> - <item>@drawable/btn_check_to_on_mtrl_007</item> - <item>@drawable/btn_check_to_on_mtrl_008</item> - <item>@drawable/btn_check_to_on_mtrl_009</item> - <item>@drawable/btn_check_to_on_mtrl_010</item> - <item>@drawable/btn_check_to_on_mtrl_011</item> - <item>@drawable/btn_check_to_on_mtrl_012</item> - <item>@drawable/btn_check_to_on_mtrl_013</item> - <item>@drawable/btn_check_to_on_mtrl_014</item> - <item>@drawable/btn_check_to_on_mtrl_015</item> - <item>@drawable/btn_radio_to_off_mtrl_000</item> - <item>@drawable/btn_radio_to_off_mtrl_001</item> - <item>@drawable/btn_radio_to_off_mtrl_002</item> - <item>@drawable/btn_radio_to_off_mtrl_003</item> - <item>@drawable/btn_radio_to_off_mtrl_004</item> - <item>@drawable/btn_radio_to_off_mtrl_005</item> - <item>@drawable/btn_radio_to_off_mtrl_006</item> - <item>@drawable/btn_radio_to_off_mtrl_007</item> - <item>@drawable/btn_radio_to_off_mtrl_008</item> - <item>@drawable/btn_radio_to_off_mtrl_009</item> - <item>@drawable/btn_radio_to_off_mtrl_010</item> - <item>@drawable/btn_radio_to_off_mtrl_011</item> - <item>@drawable/btn_radio_to_off_mtrl_012</item> - <item>@drawable/btn_radio_to_off_mtrl_013</item> - <item>@drawable/btn_radio_to_off_mtrl_014</item> - <item>@drawable/btn_radio_to_off_mtrl_015</item> - <item>@drawable/btn_radio_to_on_mtrl_000</item> - <item>@drawable/btn_radio_to_on_mtrl_001</item> - <item>@drawable/btn_radio_to_on_mtrl_002</item> - <item>@drawable/btn_radio_to_on_mtrl_003</item> - <item>@drawable/btn_radio_to_on_mtrl_004</item> - <item>@drawable/btn_radio_to_on_mtrl_005</item> - <item>@drawable/btn_radio_to_on_mtrl_006</item> - <item>@drawable/btn_radio_to_on_mtrl_007</item> - <item>@drawable/btn_radio_to_on_mtrl_008</item> - <item>@drawable/btn_radio_to_on_mtrl_009</item> - <item>@drawable/btn_radio_to_on_mtrl_010</item> - <item>@drawable/btn_radio_to_on_mtrl_011</item> - <item>@drawable/btn_radio_to_on_mtrl_012</item> - <item>@drawable/btn_radio_to_on_mtrl_013</item> - <item>@drawable/btn_radio_to_on_mtrl_014</item> - <item>@drawable/btn_radio_to_on_mtrl_015</item> - <item>@drawable/btn_rating_star_off_mtrl_alpha</item> - <item>@drawable/btn_rating_star_on_mtrl_alpha</item> - <item>@drawable/btn_star_mtrl_alpha</item> - <item>@drawable/btn_switch_to_off_mtrl_00001</item> - <item>@drawable/btn_switch_to_off_mtrl_00002</item> - <item>@drawable/btn_switch_to_off_mtrl_00003</item> - <item>@drawable/btn_switch_to_off_mtrl_00004</item> - <item>@drawable/btn_switch_to_off_mtrl_00005</item> - <item>@drawable/btn_switch_to_off_mtrl_00006</item> - <item>@drawable/btn_switch_to_off_mtrl_00007</item> - <item>@drawable/btn_switch_to_off_mtrl_00008</item> - <item>@drawable/btn_switch_to_off_mtrl_00009</item> - <item>@drawable/btn_switch_to_off_mtrl_00010</item> - <item>@drawable/btn_switch_to_off_mtrl_00011</item> - <item>@drawable/btn_switch_to_off_mtrl_00012</item> - <item>@drawable/btn_switch_to_on_mtrl_00001</item> - <item>@drawable/btn_switch_to_on_mtrl_00002</item> - <item>@drawable/btn_switch_to_on_mtrl_00003</item> - <item>@drawable/btn_switch_to_on_mtrl_00004</item> - <item>@drawable/btn_switch_to_on_mtrl_00005</item> - <item>@drawable/btn_switch_to_on_mtrl_00006</item> - <item>@drawable/btn_switch_to_on_mtrl_00007</item> - <item>@drawable/btn_switch_to_on_mtrl_00008</item> - <item>@drawable/btn_switch_to_on_mtrl_00009</item> - <item>@drawable/btn_switch_to_on_mtrl_00010</item> - <item>@drawable/btn_switch_to_on_mtrl_00011</item> - <item>@drawable/btn_switch_to_on_mtrl_00012</item> - <item>@drawable/btn_toggle_indicator_mtrl_alpha</item> - <item>@drawable/expander_close_mtrl_alpha</item> - <item>@drawable/expander_open_mtrl_alpha</item> - <item>@drawable/fastscroll_thumb_mtrl_alpha</item> - <item>@drawable/fastscroll_track_mtrl_alpha</item> + <item>@drawable/ab_share_pack_material</item> + <item>@drawable/ab_solid_shadow_material</item> + <item>@drawable/activated_background_material</item> + <item>@drawable/btn_borderless_material</item> + <item>@drawable/btn_cab_done_material</item> + <item>@drawable/btn_check_material_anim</item> + <item>@drawable/btn_default_material</item> + <item>@drawable/btn_radio_material_anim</item> + <item>@drawable/btn_star_material</item> + <item>@drawable/btn_toggle_material</item> + <item>@drawable/cab_background_bottom_material</item> + <item>@drawable/cab_background_top_material</item> + <item>@drawable/dialog_background_material</item> + <item>@drawable/dialog_background_shadow_material</item> + <item>@drawable/edit_text_material</item> + <item>@drawable/expander_group_material</item> + <item>@drawable/fastscroll_label_left_material</item> + <item>@drawable/fastscroll_label_right_material</item> + <item>@drawable/fastscroll_thumb_material</item> + <item>@drawable/fastscroll_track_material</item> <item>@drawable/ic_ab_back_material</item> - <item>@drawable/ic_cab_done_mtrl_alpha</item> - <item>@drawable/ic_clear_mtrl_alpha</item> - <item>@drawable/ic_commit_search_api_mtrl_alpha</item> + <item>@drawable/ic_clear_material</item> + <item>@drawable/ic_commit_search_api_material</item> <item>@drawable/ic_dialog_alert_material</item> - <item>@drawable/ic_find_next_mtrl_alpha</item> - <item>@drawable/ic_find_previous_mtrl_alpha</item> + <item>@drawable/ic_find_next_material</item> + <item>@drawable/ic_find_previous_material</item> <item>@drawable/ic_go_search_api_material</item> - <item>@drawable/ic_media_route_disabled_mtrl_alpha</item> - <item>@drawable/ic_media_route_off_mtrl_alpha</item> - <item>@drawable/ic_media_route_on_0_mtrl_alpha</item> - <item>@drawable/ic_media_route_on_1_mtrl_alpha</item> - <item>@drawable/ic_media_route_on_2_mtrl_alpha</item> - <item>@drawable/ic_media_route_on_mtrl_alpha</item> + <item>@drawable/ic_media_route_connecting_material</item> + <item>@drawable/ic_media_route_material</item> <item>@drawable/ic_menu_copy_material</item> <item>@drawable/ic_menu_cut_material</item> - <item>@drawable/ic_menu_find_mtrl_alpha</item> + <item>@drawable/ic_menu_find_material</item> <item>@drawable/ic_menu_moreoverflow_material</item> <item>@drawable/ic_menu_paste_material</item> - <item>@drawable/ic_menu_search_mtrl_alpha</item> + <item>@drawable/ic_menu_search_material</item> <item>@drawable/ic_menu_selectall_material</item> <item>@drawable/ic_menu_share_material</item> <item>@drawable/ic_search_api_material</item> <item>@drawable/ic_voice_search_api_material</item> - <item>@drawable/list_divider_mtrl_alpha</item> - <item>@drawable/list_section_divider_mtrl_alpha</item> - <item>@drawable/popup_background_mtrl_mult</item> - <item>@drawable/progress_mtrl_alpha</item> - <item>@drawable/scrollbar_handle_mtrl_alpha</item> - <item>@drawable/scrubber_control_from_pressed_mtrl_000</item> - <item>@drawable/scrubber_control_from_pressed_mtrl_001</item> - <item>@drawable/scrubber_control_from_pressed_mtrl_002</item> - <item>@drawable/scrubber_control_from_pressed_mtrl_003</item> - <item>@drawable/scrubber_control_from_pressed_mtrl_004</item> - <item>@drawable/scrubber_control_from_pressed_mtrl_005</item> - <item>@drawable/scrubber_control_off_pressed_mtrl_alpha</item> - <item>@drawable/scrubber_control_off_mtrl_alpha</item> - <item>@drawable/scrubber_control_on_pressed_mtrl_alpha</item> - <item>@drawable/scrubber_control_on_mtrl_alpha</item> - <item>@drawable/scrubber_control_to_pressed_mtrl_000</item> - <item>@drawable/scrubber_control_to_pressed_mtrl_001</item> - <item>@drawable/scrubber_control_to_pressed_mtrl_002</item> - <item>@drawable/scrubber_control_to_pressed_mtrl_003</item> - <item>@drawable/scrubber_control_to_pressed_mtrl_004</item> - <item>@drawable/scrubber_control_to_pressed_mtrl_005</item> - <item>@drawable/scrubber_primary_mtrl_alpha</item> - <item>@drawable/scrubber_track_mtrl_alpha</item> - <item>@drawable/spinner_mtrl_am_alpha</item> - <item>@drawable/switch_track_mtrl_alpha</item> - <item>@drawable/text_cursor_mtrl_alpha</item> - <item>@drawable/textfield_activated_mtrl_alpha</item> - <item>@drawable/textfield_default_mtrl_alpha</item> - <item>@drawable/textfield_search_activated_mtrl_alpha</item> - <item>@drawable/textfield_search_default_mtrl_alpha</item> - <item>@drawable/text_select_handle_left_mtrl_alpha</item> - <item>@drawable/text_select_handle_middle_mtrl_alpha</item> - <item>@drawable/text_select_handle_right_mtrl_alpha</item> + <item>@drawable/item_background_borderless_material</item> + <item>@drawable/item_background_material</item> + <item>@drawable/list_divider_material</item> + <item>@drawable/list_section_divider_material</item> + <item>@drawable/notification_material_action_background</item> + <item>@drawable/notification_material_media_action_background</item> + <item>@drawable/popup_background_material</item> + <item>@drawable/progress_horizontal_material</item> + <item>@drawable/progress_indeterminate_horizontal_material</item> + <item>@drawable/progress_large_material</item> + <item>@drawable/progress_medium_material</item> + <item>@drawable/progress_small_material</item> + <item>@drawable/ratingbar_full_empty_material</item> + <item>@drawable/ratingbar_full_filled_material</item> + <item>@drawable/ratingbar_full_material</item> + <item>@drawable/scrollbar_handle_material</item> + <item>@drawable/scrubber_control_material_anim</item> + <item>@drawable/scrubber_control_selector_material</item> + <item>@drawable/scrubber_progress_horizontal_material</item> + <item>@drawable/spinner_background_material</item> + <item>@drawable/spinner_textfield_background_material</item> + <item>@drawable/switch_thumb_material_anim</item> + <item>@drawable/switch_track_material</item> + <item>@drawable/tab_indicator_material</item> + <item>@drawable/text_cursor_material</item> + <item>@drawable/textfield_search_material</item> + <item>@drawable/text_select_handle_left_material</item> + <item>@drawable/text_select_handle_middle_material</item> + <item>@drawable/text_select_handle_right_material</item> + <item>@drawable/ic_account_circle</item> </array> <!-- Do not translate. These are all of the color state list resources that should be diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 251652e20440..91a8598b6cea 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2363,6 +2363,18 @@ representation this attribute can be used for providing such. --> <attr name="contentDescription" format="string" localization="suggested" /> + <!-- Sets the id of a view before which this one is visited in accessibility traversal. + A screen-reader must visit the content of this view before the content of the one + it precedes. + @see android.view.View#setAccessibilityTraversalBefore(int)} --> + <attr name="accessibilityTraversalBefore" format="integer" /> + + <!-- Sets the id of a view after which this one is visited in accessibility traversal. + A screen-reader must visit the content of the other view before the content of + this one. + @see android.view.View#setAccessibilityTraversalAfter(int)} --> + <attr name="accessibilityTraversalAfter" format="integer" /> + <!-- Name of the method in this View's context to invoke when the view is clicked. This name must correspond to a public method that takes exactly one parameter of type View. For instance, if you specify @@ -2772,25 +2784,32 @@ <attr name="layout_width" /> <attr name="layout_height" /> <!-- Specifies extra space on the left, top, right and bottom - sides of this view. This space is outside this view's bounds. --> + sides of this view. This space is outside this view's bounds. + Margin values should be positive. --> <attr name="layout_margin" format="dimension" /> <!-- Specifies extra space on the left side of this view. - This space is outside this view's bounds. --> + This space is outside this view's bounds. + Margin values should be positive. --> <attr name="layout_marginLeft" format="dimension" /> <!-- Specifies extra space on the top side of this view. - This space is outside this view's bounds. --> + This space is outside this view's bounds. + Margin values should be positive.--> <attr name="layout_marginTop" format="dimension" /> <!-- Specifies extra space on the right side of this view. - This space is outside this view's bounds. --> + This space is outside this view's bounds. + Margin values should be positive.--> <attr name="layout_marginRight" format="dimension" /> <!-- Specifies extra space on the bottom side of this view. - This space is outside this view's bounds. --> + This space is outside this view's bounds. + Margin values should be positive.--> <attr name="layout_marginBottom" format="dimension" /> <!-- Specifies extra space on the start side of this view. - This space is outside this view's bounds. --> + This space is outside this view's bounds. + Margin values should be positive.--> <attr name="layout_marginStart" format="dimension" /> <!-- Specifies extra space on the end side of this view. - This space is outside this view's bounds. --> + This space is outside this view's bounds. + Margin values should be positive.--> <attr name="layout_marginEnd" format="dimension" /> </declare-styleable> @@ -4862,6 +4881,12 @@ <attr name="thickness" format="dimension" /> <!-- Indicates whether the drawable's level affects the way the gradient is drawn. --> <attr name="useLevel" /> + <!-- If set, specifies the color to apply to the drawable as a tint. By default, + no tint is applied. May be a color state list. --> + <attr name="tint" /> + <!-- When a tint color is set, specifies its Porter-Duff blending mode. The + default value is src_in, which treats the drawable as an alpha mask. --> + <attr name="tintMode" /> </declare-styleable> <!-- Used to specify the size of the shape for GradientDrawable. --> @@ -4898,7 +4923,7 @@ <!-- Y coordinate of the origin of the gradient within the shape. --> <attr name="centerY" format="float|fraction" /> <!-- Radius of the gradient, used only with radial gradient. --> - <attr name="gradientRadius" format="float|fraction" /> + <attr name="gradientRadius" format="float|fraction|dimension" /> </declare-styleable> <!-- Used to fill the shape of GradientDrawable with a solid color. --> @@ -5689,6 +5714,17 @@ <attr name="reparent" format="boolean"/> </declare-styleable> + <!-- Use <code>changeBounds</code>as the root tag of the XML resource that + describes a {@link android.transition.ChangeBounds} transition. + The attributes of the {@link android.R.styleable#Transition Transition} + resource are available in addition to the specific attributes of ChangeBounds + described here. --> + <declare-styleable name="ChangeBounds"> + <!-- Resize the view by adjusting the clipBounds rather than changing the + dimensions of the view itself. The default value is false. --> + <attr name="resizeClip" format="boolean"/> + </declare-styleable> + <!-- Use <code>transitionManager</code> as the root tag of the XML resource that describes a {@link android.transition.TransitionManager TransitionManager}. --> @@ -7436,7 +7472,10 @@ <!-- Push object to the bottom of its container, not changing its size. --> <flag name="bottom" value="0x50" /> </attr> + <!-- Icon drawable to use for the collapse button. --> <attr name="collapseIcon" format="reference" /> + <!-- Text to set as the content description for the collapse button. --> + <attr name="collapseContentDescription" format="string" /> <!-- Reference to a theme that should be used to inflate popups shown by widgets in the toolbar. --> <attr name="popupTheme" format="reference" /> diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml index 18e4f2f9b3a8..457131a4f84a 100644 --- a/core/res/res/values/bools.xml +++ b/core/res/res/values/bools.xml @@ -18,7 +18,6 @@ <bool name="kg_enable_camera_default_widget">true</bool> <bool name="kg_center_small_widgets_vertically">false</bool> <bool name="kg_top_align_page_shrink_on_bouncer_visible">true</bool> - <bool name="kg_show_ime_at_screen_on">true</bool> <bool name="action_bar_embed_tabs">true</bool> <bool name="action_bar_embed_tabs_pre_jb">false</bool> <bool name="split_action_bar_is_narrow">true</bool> diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml index 235bf84561fc..9f83db4909e7 100644 --- a/core/res/res/values/colors.xml +++ b/core/res/res/values/colors.xml @@ -136,6 +136,8 @@ <color name="notification_media_primary_color">@color/primary_text_material_dark</color> <color name="notification_media_secondary_color">@color/secondary_text_material_dark</color> + <color name="notification_progress_background_color">@color/secondary_text_material_light</color> + <!-- Keyguard colors --> <color name="keyguard_avatar_frame_color">#ffffffff</color> <color name="keyguard_avatar_frame_shadow_color">#80000000</color> diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml index 5773b943abf0..46ec83827e8b 100644 --- a/core/res/res/values/colors_material.xml +++ b/core/res/res/values/colors_material.xml @@ -22,7 +22,7 @@ <color name="background_floating_material_light">#ffeeeeee</color> <color name="primary_material_dark">#ff212121</color> - <color name="primary_material_light">#ffbdbdbd</color> + <color name="primary_material_light">#ffe0e0e0</color> <color name="primary_dark_material_dark">#ff000000</color> <color name="primary_dark_material_light">#ff757575</color> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index eed2ef2b1ba6..60d8210b4886 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -27,6 +27,7 @@ <item><xliff:g id="id">sync_failing</xliff:g></item> <item><xliff:g id="id">sync_active</xliff:g></item> <item><xliff:g id="id">cast</xliff:g></item> + <item><xliff:g id="id">hotspot</xliff:g></item> <item><xliff:g id="id">location</xliff:g></item> <item><xliff:g id="id">bluetooth</xliff:g></item> <item><xliff:g id="id">nfc</xliff:g></item> @@ -1787,13 +1788,21 @@ be disabled) but individual Features can be disabled using ImsConfig.setFeatureValue() --> <bool name="imsServiceAllowTurnOff">true</bool> - <!-- Flag specifying whether VoLTE & VT is availasble on device --> - <bool name="config_device_volte_vt_available">false</bool> + <!-- Flag specifying whether VoLTE is available on device --> + <bool name="config_device_volte_available">false</bool> - <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + <!-- Flag specifying whether VoLTE should be available for carrier: independent of carrier provisioning. If false: hard disabled. If true: then depends on carrier provisioning, availability etc --> - <bool name="config_carrier_volte_vt_available">false</bool> + <bool name="config_carrier_volte_available">false</bool> + + <!-- Flag specifying whether VT is available on device --> + <bool name="config_device_vt_available">false</bool> + + <!-- Flag specifying whether VT should be available for carrier: independent of + carrier provisioning. If false: hard disabled. If true: then depends on carrier + provisioning, availability etc --> + <bool name="config_carrier_vt_available">false</bool> <bool name="config_networkSamplingWakesDevice">true</bool> @@ -1876,4 +1885,11 @@ <bool name="config_switch_phone_on_voice_reg_state_change">true</bool> <bool name="config_sms_force_7bit_encoding">false</bool> + + <!-- Flag indicating whether strict threshold is used, or lenient threshold is used, + when evaluating RSRP for LTE antenna bar display + 0. Strict threshold + 1. Lenient threshold + --> + <integer name="config_LTE_RSRP_threshold_type">1</integer> </resources> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 26d313371ae1..71f66ba7b6af 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -367,12 +367,15 @@ <dimen name="timepicker_time_label_size">60sp</dimen> <dimen name="timepicker_extra_time_label_margin">-30dp</dimen> <dimen name="timepicker_ampm_label_size">16sp</dimen> - <dimen name="timepicker_ampm_left_padding">6dip</dimen> - <dimen name="timepicker_separator_padding">4dip</dimen> - <dimen name="timepicker_header_height">96dip</dimen> - <dimen name="timepicker_minimum_margin_sides">48dip</dimen> - <dimen name="timepicker_minimum_margin_top_bottom">24dip</dimen> - <dimen name="timepicker_radial_picker_dimen">270dip</dimen> + <dimen name="timepicker_ampm_horizontal_padding">12dp</dimen> + <dimen name="timepicker_ampm_vertical_padding">16dp</dimen> + <dimen name="timepicker_am_bottom_padding">1dp</dimen> + <dimen name="timepicker_pm_top_padding">2dp</dimen> + <dimen name="timepicker_separator_padding">4dp</dimen> + <dimen name="timepicker_header_height">96dp</dimen> + <dimen name="timepicker_minimum_margin_sides">48dp</dimen> + <dimen name="timepicker_minimum_margin_top_bottom">24dp</dimen> + <dimen name="timepicker_radial_picker_dimen">270dp</dimen> <!-- Used by SimpleMonthView --> <dimen name="datepicker_day_number_size">12sp</dimen> diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml index 450658e22526..515922de12bd 100644 --- a/core/res/res/values/dimens_material.xml +++ b/core/res/res/values/dimens_material.xml @@ -15,7 +15,7 @@ --> <resources> <!-- Preference activity, vertical padding for the header list --> - <dimen name="preference_screen_header_vertical_padding_material">8dp</dimen> + <dimen name="preference_screen_header_vertical_padding_material">0dp</dimen> <!-- Preference activity side margins --> <dimen name="preference_screen_side_margin_material">0dp</dimen> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 7568252d912b..c0a5ab26ad66 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2590,4 +2590,14 @@ <!-- @hide --> <public-padding type="attr" name="private_resource_pad" end="0x01010500" /> + <!-- =============================================================== + Resources added in version 22 of the platform + =============================================================== --> + <eat-comment /> + + <public type="attr" name="resizeClip"/> + <public type="attr" name="collapseContentDescription"/> + <public type="attr" name="accessibilityTraversalBefore" /> + <public type="attr" name="accessibilityTraversalAfter" /> + </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 987b291f5485..27616c7b143e 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1449,9 +1449,8 @@ <string name="permlab_bodySensors">body sensors (like heart rate monitors) </string> <!-- Description of the body sensors permission, listed so the user can decide whether to allow the application to access data from body sensors. [CHAR LIMIT=NONE] --> - <string name="permdesc_bodySensors" product="default">Allows the app to - access data from sensors you use to measure what’s happening inside your - body, such as heart rate.</string> + <string name="permdesc_bodySensors" product="default">Allows the app to access data from sensors + that monitor your physical condition, such as your heart rate.</string> <!-- Title of the read social stream permission, listed so the user can decide whether to allow the application to read information from the user's social stream. [CHAR LIMIT=30] --> <string name="permlab_readSocialStream" product="default">read your social stream</string> @@ -2116,6 +2115,16 @@ <string name="permdesc_use_sip">Allows the app to make and receive SIP calls.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_register_provider">register new telecom connection</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permdesc_register_provider">Allows the app to register new telecom connections.</string> + + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_connection_manager">manage telecom connections</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permdesc_connection_manager">Allows the app to manage telecom connections.</string> + + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_bind_incall_service">interact with in-call screen</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_bind_incall_service">Allows the app to control when and how the user sees the in-call screen.</string> @@ -2523,19 +2532,6 @@ <!-- Shown when face unlock failed multiple times so we're just using the backup --> <string name="faceunlock_multiple_failures">Maximum Face Unlock attempts exceeded</string> - <!-- When the lock screen is showing and the phone plugged in, and the battery - is not fully charged, show the current charge %. --> - <string name="lockscreen_plugged_in">Charging, <xliff:g id="number">%d</xliff:g><xliff:g id="percent">%%</xliff:g></string> - <!-- When the lock screen is showing, the phone is plugged in and the battery is fully - charged, say that it is charged. --> - <string name="lockscreen_charged">Charged</string> - <!-- A short representation of charging information, e.g "34%" --> - <string name="lockscreen_battery_short"><xliff:g id="number">%d</xliff:g><xliff:g id="percent">%%</xliff:g></string> - - <!-- When the lock screen is showing and the battery is low, warn user to plug - in the phone soon. --> - <string name="lockscreen_low_battery">Connect your charger.</string> - <!-- Shown in the lock screen when there is no SIM card. --> <string name="lockscreen_missing_sim_message_short">No SIM card</string> <!-- Shown in the lock screen when there is no SIM card. --> @@ -3513,6 +3509,9 @@ <!-- [CHAR LIMIT=40] Title of dialog that is shown when performing a system upgrade. --> <string name="android_upgrading_title">Android is upgrading\u2026</string> + <!-- [CHAR LIMIT=40] Title of dialog that is shown when system is starting. --> + <string name="android_start_title">Android is starting\u2026</string> + <!-- [CHAR LIMIT=NONE] Message shown in upgrading dialog for each .apk that is optimized. --> <string name="android_upgrading_apk">Optimizing app <xliff:g id="number" example="123">%1$d</xliff:g> of @@ -4877,18 +4876,36 @@ <!-- [CHAR_LIMIT=NONE] Zen mode: Condition summary for built-in downtime condition, if active --> <string name="downtime_condition_summary">Until your downtime ends at <xliff:g id="formattedTime" example="10.00 PM">%1$s</xliff:g></string> - <!-- Zen mode condition: time duration in minutes. [CHAR LIMIT=NONE] --> + <!-- Zen mode condition - summary: time duration in minutes. [CHAR LIMIT=NONE] --> + <plurals name="zen_mode_duration_minutes_summary"> + <item quantity="one">For one minute (until <xliff:g id="formattedTime" example="10:00 PM">%2$s</xliff:g>)</item> + <item quantity="other">For %1$d minutes (until <xliff:g id="formattedTime" example="10:00 PM">%2$s</xliff:g>)</item> + </plurals> + + <!-- Zen mode condition - summary: time duration in hours. [CHAR LIMIT=NONE] --> + <plurals name="zen_mode_duration_hours_summary"> + <item quantity="one">For one hour (until <xliff:g id="formattedTime" example="10:00 PM">%2$s</xliff:g>)</item> + <item quantity="other">For %1$d hours (until <xliff:g id="formattedTime" example="10:00 PM">%2$s</xliff:g>)</item> + </plurals> + + <!-- Zen mode condition - line one: time duration in minutes. [CHAR LIMIT=NONE] --> <plurals name="zen_mode_duration_minutes"> <item quantity="one">For one minute</item> <item quantity="other">For %d minutes</item> </plurals> - <!-- Zen mode condition: time duration in hours. [CHAR LIMIT=NONE] --> + <!-- Zen mode condition - line one: time duration in hours. [CHAR LIMIT=NONE] --> <plurals name="zen_mode_duration_hours"> <item quantity="one">For one hour</item> <item quantity="other">For %d hours</item> </plurals> + <!-- Zen mode condition - line two: ending time. [CHAR LIMIT=NONE] --> + <string name="zen_mode_until">Until <xliff:g id="formattedTime" example="10:00 PM">%1$s</xliff:g></string> + <!-- Zen mode condition: no exit criteria. [CHAR LIMIT=NONE] --> <string name="zen_mode_forever">Indefinitely</string> + + <!-- Content description for the Toolbar icon used to collapse an expanded action mode. [CHAR LIMIT=NONE] --> + <string name="toolbar_collapse_description">Collapse</string> </resources> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index ba15e9cc28c0..dd871399b6fc 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -1218,6 +1218,7 @@ please see styles_device_defaults.xml. <item name="buttonGravity">top</item> <item name="navigationButtonStyle">@style/Widget.Toolbar.Button.Navigation</item> <item name="collapseIcon">?attr/homeAsUpIndicator</item> + <item name="collapseContentDescription">@string/toolbar_collapse_description</item> <item name="contentInsetStart">16dp</item> <item name="touchscreenBlocksFocus">true</item> </style> diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml index f9fca00d3ba4..cc3ded505079 100644 --- a/core/res/res/values/styles_material.xml +++ b/core/res/res/values/styles_material.xml @@ -320,50 +320,48 @@ please see styles_device_defaults.xml. <item name="textColor">?attr/textColorPrimaryDisableOnly</item> </style> - <style name="TextAppearance.Material.Widget.ActionMode"/> - <style name="TextAppearance.Material.Widget.ActionMode.Title" - parent="TextAppearance.Material.Title"> - <item name="textSize">@dimen/text_size_title_material_toolbar</item> - </style> - <style name="TextAppearance.Material.Widget.ActionMode.Title.Inverse" - parent="TextAppearance.Material.Title.Inverse"> - <item name="textSize">@dimen/text_size_title_material_toolbar</item> - </style> - <style name="TextAppearance.Material.Widget.ActionMode.Subtitle" - parent="TextAppearance.Material.Subhead"> - <item name="textSize">@dimen/text_size_subtitle_material_toolbar</item> - </style> - <style name="TextAppearance.Material.Widget.ActionMode.Subtitle.Inverse" - parent="TextAppearance.Material.Subhead.Inverse"> - <item name="textSize">@dimen/text_size_subtitle_material_toolbar</item> - </style> <style name="TextAppearance.Material.Widget.ActionBar.Title" parent="TextAppearance.Material.Title"> <item name="textSize">@dimen/text_size_title_material_toolbar</item> + <item name="textColor">?attr/textColorPrimary</item> </style> <style name="TextAppearance.Material.Widget.ActionBar.Title.Inverse" parent="TextAppearance.Material.Title.Inverse"> <item name="textSize">@dimen/text_size_title_material_toolbar</item> + <item name="textColor">?attr/textColorPrimaryInverse</item> </style> <style name="TextAppearance.Material.Widget.ActionBar.Subtitle" parent="TextAppearance.Material.Subhead"> <item name="textSize">@dimen/text_size_subtitle_material_toolbar</item> + <item name="textColor">?attr/textColorSecondary</item> </style> <style name="TextAppearance.Material.Widget.ActionBar.Subtitle.Inverse" parent="TextAppearance.Material.Subhead.Inverse"> <item name="textSize">@dimen/text_size_subtitle_material_toolbar</item> + <item name="textColor">?attr/textColorSecondaryInverse</item> </style> - <style name="TextAppearance.Material.Widget.ActionBar.Menu" parent="TextAppearance.Material.Menu"> + <style name="TextAppearance.Material.Widget.ActionBar.Menu" + parent="TextAppearance.Material.Menu"> <item name="textColor">?attr/actionMenuTextColor</item> <item name="textAllCaps">@bool/config_actionMenuItemAllCaps</item> </style> - - <style name="TextAppearance.Material.Widget.ActionBar.Menu.Inverse" parent="TextAppearance.Material.Menu.Inverse"> + <style name="TextAppearance.Material.Widget.ActionBar.Menu.Inverse" + parent="TextAppearance.Material.Menu.Inverse"> <item name="textColor">?attr/actionMenuTextColor</item> <item name="textAllCaps">@bool/config_actionMenuItemAllCaps</item> </style> + <style name="TextAppearance.Material.Widget.ActionMode"/> + <style name="TextAppearance.Material.Widget.ActionMode.Title" + parent="TextAppearance.Material.Widget.ActionBar.Title" /> + <style name="TextAppearance.Material.Widget.ActionMode.Title.Inverse" + parent="TextAppearance.Material.Widget.ActionBar.Title.Inverse" /> + <style name="TextAppearance.Material.Widget.ActionMode.Subtitle" + parent="TextAppearance.Material.Widget.ActionBar.Subtitle" /> + <style name="TextAppearance.Material.Widget.ActionMode.Subtitle.Inverse" + parent="TextAppearance.Material.Widget.ActionBar.Subtitle.Inverse" /> + <style name="TextAppearance.Material.Widget.Toolbar.Title" parent="TextAppearance.Material.Widget.ActionBar.Title" /> <style name="TextAppearance.Material.Widget.Toolbar.Subtitle" @@ -1093,16 +1091,16 @@ please see styles_device_defaults.xml. <!-- Dialog styles --> <style name="AlertDialog.Material" parent="AlertDialog"> - <item name="fullDark">@null</item> - <item name="topDark">@null</item> - <item name="centerDark">@null</item> - <item name="bottomDark">@null</item> - <item name="fullBright">@null</item> - <item name="topBright">@null</item> - <item name="centerBright">@null</item> - <item name="bottomBright">@null</item> - <item name="bottomMedium">@null</item> - <item name="centerMedium">@null</item> + <item name="fullDark">@empty</item> + <item name="topDark">@empty</item> + <item name="centerDark">@empty</item> + <item name="bottomDark">@empty</item> + <item name="fullBright">@empty</item> + <item name="topBright">@empty</item> + <item name="centerBright">@empty</item> + <item name="bottomBright">@empty</item> + <item name="bottomMedium">@empty</item> + <item name="centerMedium">@empty</item> <item name="layout">@layout/alert_dialog_material</item> <item name="listLayout">@layout/select_dialog_material</item> <item name="progressLayout">@layout/progress_dialog_material</item> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 47978ebf5792..afe7c78428b7 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1491,6 +1491,7 @@ <java-symbol type="layout" name="screen_title" /> <java-symbol type="layout" name="screen_title_icons" /> <java-symbol type="string" name="system_ui_date_pattern" /> + <java-symbol type="string" name="android_start_title" /> <java-symbol type="string" name="android_upgrading_title" /> <java-symbol type="string" name="bugreport_title" /> <java-symbol type="string" name="bugreport_message" /> @@ -1791,6 +1792,7 @@ <java-symbol type="drawable" name="notification_icon_legacy_bg" /> <java-symbol type="color" name="notification_media_primary_color" /> <java-symbol type="color" name="notification_media_secondary_color" /> + <java-symbol type="color" name="notification_progress_background_color" /> <java-symbol type="id" name="media_actions" /> <!-- From SystemUI --> @@ -1944,7 +1946,9 @@ <java-symbol type="id" name="time_header" /> <java-symbol type="id" name="hours" /> <java-symbol type="id" name="minutes" /> - <java-symbol type="id" name="ampm_label" /> + <java-symbol type="id" name="ampm_layout" /> + <java-symbol type="id" name="am_label" /> + <java-symbol type="id" name="pm_label" /> <java-symbol type="id" name="radial_picker" /> <java-symbol type="id" name="separator" /> <java-symbol type="id" name="date_picker_header" /> @@ -1981,6 +1985,9 @@ <java-symbol type="string" name="zen_mode_forever" /> <java-symbol type="plurals" name="zen_mode_duration_minutes" /> <java-symbol type="plurals" name="zen_mode_duration_hours" /> + <java-symbol type="plurals" name="zen_mode_duration_minutes_summary" /> + <java-symbol type="plurals" name="zen_mode_duration_hours_summary" /> + <java-symbol type="string" name="zen_mode_until" /> <java-symbol type="string" name="item_is_selected" /> <java-symbol type="string" name="day_of_week_label_typeface" /> @@ -2037,8 +2044,10 @@ <java-symbol type="attr" name="preferenceFragmentStyle" /> <java-symbol type="bool" name="skipHoldBeforeMerge" /> <java-symbol type="bool" name="imsServiceAllowTurnOff" /> - <java-symbol type="bool" name="config_device_volte_vt_available" /> - <java-symbol type="bool" name="config_carrier_volte_vt_available" /> + <java-symbol type="bool" name="config_device_volte_available" /> + <java-symbol type="bool" name="config_carrier_volte_available" /> + <java-symbol type="bool" name="config_device_vt_available" /> + <java-symbol type="bool" name="config_carrier_vt_available" /> <java-symbol type="bool" name="useImsAlwaysForEmergencyCall" /> <java-symbol type="attr" name="touchscreenBlocksFocus" /> <java-symbol type="layout" name="resolver_list_with_default" /> @@ -2082,7 +2091,10 @@ <java-symbol type="bool" name="config_switch_phone_on_voice_reg_state_change" /> <java-symbol type="string" name="whichHomeApplicationNamed" /> <java-symbol type="bool" name="config_sms_force_7bit_encoding" /> - - <!-- From MSIM Account --> <java-symbol type="layout" name="simple_account_item" /> + <java-symbol type="id" name="scrollIndicatorUp" /> + <java-symbol type="id" name="scrollIndicatorDown" /> + + <!-- From SignalStrength --> + <java-symbol type="integer" name="config_LTE_RSRP_threshold_type" /> </resources> diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml index b51974ec20dc..5640fc1b7ee1 100644 --- a/core/res/res/values/themes_material.xml +++ b/core/res/res/values/themes_material.xml @@ -781,9 +781,6 @@ please see themes_device_defaults.xml. <item name="textCheckMark">@drawable/indicator_check_mark_light</item> <item name="textCheckMarkInverse">@drawable/indicator_check_mark_dark</item> - <item name="fastScrollPreviewBackgroundLeft">@drawable/fastscroll_label_left_holo_light</item> - <item name="fastScrollPreviewBackgroundRight">@drawable/fastscroll_label_right_holo_light</item> - <item name="colorControlNormal">?attr/textColorSecondary</item> <item name="colorControlHighlight">@color/ripple_material_light</item> <item name="colorButtonNormal">@color/btn_default_material_light</item> @@ -819,9 +816,6 @@ please see themes_device_defaults.xml. <item name="textCheckMark">@drawable/indicator_check_mark_dark</item> <item name="textCheckMarkInverse">@drawable/indicator_check_mark_light</item> - <item name="fastScrollPreviewBackgroundLeft">@drawable/fastscroll_label_left_holo_dark</item> - <item name="fastScrollPreviewBackgroundRight">@drawable/fastscroll_label_right_holo_dark</item> - <item name="colorControlNormal">?attr/textColorSecondary</item> <item name="colorControlHighlight">@color/ripple_material_dark</item> <item name="colorButtonNormal">@color/btn_default_material_dark</item> @@ -1025,10 +1019,10 @@ please see themes_device_defaults.xml. <item name="textAppearance">@style/TextAppearance.Material</item> <item name="textAppearanceInverse">@style/TextAppearance.Material.Inverse</item> - <item name="listPreferredItemPaddingLeft">16dip</item> - <item name="listPreferredItemPaddingRight">16dip</item> - <item name="listPreferredItemPaddingStart">16dip</item> - <item name="listPreferredItemPaddingEnd">16dip</item> + <item name="listPreferredItemPaddingLeft">24dip</item> + <item name="listPreferredItemPaddingRight">24dip</item> + <item name="listPreferredItemPaddingStart">24dip</item> + <item name="listPreferredItemPaddingEnd">24dip</item> <item name="listDivider">@null</item> @@ -1141,10 +1135,10 @@ please see themes_device_defaults.xml. <item name="textAppearance">@style/TextAppearance.Material</item> <item name="textAppearanceInverse">@style/TextAppearance.Material.Inverse</item> - <item name="listPreferredItemPaddingLeft">16dip</item> - <item name="listPreferredItemPaddingRight">16dip</item> - <item name="listPreferredItemPaddingStart">16dip</item> - <item name="listPreferredItemPaddingEnd">16dip</item> + <item name="listPreferredItemPaddingLeft">24dip</item> + <item name="listPreferredItemPaddingRight">24dip</item> + <item name="listPreferredItemPaddingStart">24dip</item> + <item name="listPreferredItemPaddingEnd">24dip</item> <item name="listDivider">@null</item> diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml index b5241779a88a..226717ec21d0 100644 --- a/core/tests/coretests/AndroidManifest.xml +++ b/core/tests/coretests/AndroidManifest.xml @@ -1252,6 +1252,13 @@ </intent-filter> </activity> + <activity android:name="android.content.res.ResourceCacheActivity"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" /> + </intent-filter> + </activity> + </application> <instrumentation android:name="android.test.InstrumentationTestRunner" diff --git a/core/tests/coretests/res/anim/reset_state_anim.xml b/core/tests/coretests/res/anim/reset_state_anim.xml index 918d0a35b0a1..4bbbe62eba6f 100644 --- a/core/tests/coretests/res/anim/reset_state_anim.xml +++ b/core/tests/coretests/res/anim/reset_state_anim.xml @@ -1,4 +1,18 @@ <?xml version="1.0"?> +<!-- Copyright (C) 2014 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +--> <set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:propertyName="x" android:duration="100" android:valueTo="0" android:valueType="floatType"/> <objectAnimator android:propertyName="y" android:duration="100" android:valueTo="0" android:valueType="floatType"/> diff --git a/core/tests/coretests/res/anim/test_animator.xml b/core/tests/coretests/res/anim/test_animator.xml new file mode 100644 index 000000000000..49afc3f2b58d --- /dev/null +++ b/core/tests/coretests/res/anim/test_animator.xml @@ -0,0 +1,22 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2014 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +--> + +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- if you change this, you should also change AnimatorInflaterTest#testLoadAnimator--> + <objectAnimator android:propertyName="x" android:duration="100" android:valueTo="0" android:valueType="floatType"/> + <objectAnimator android:propertyName="y" android:duration="100" android:valueTo="1" android:valueType="floatType"/> + <objectAnimator android:propertyName="left" android:duration="100" android:valueTo="2" android:valueType="intType"/> +</set>
\ No newline at end of file diff --git a/core/tests/coretests/res/anim/test_state_anim.xml b/core/tests/coretests/res/anim/test_state_anim.xml index 9e08f68a3ebc..b6a4822ae153 100644 --- a/core/tests/coretests/res/anim/test_state_anim.xml +++ b/core/tests/coretests/res/anim/test_state_anim.xml @@ -1,4 +1,18 @@ <?xml version="1.0"?> +<!-- Copyright (C) 2014 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. +--> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true"> <set> diff --git a/core/tests/coretests/res/values-land/dimens.xml b/core/tests/coretests/res/values-land/dimens.xml new file mode 100644 index 000000000000..1ee9f1dbcd5d --- /dev/null +++ b/core/tests/coretests/res/values-land/dimens.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +--> +<resources> + <dimen name="resource_cache_test_orientation_dependent">3dp</dimen> +</resources>
\ No newline at end of file diff --git a/core/tests/coretests/res/values/dimens.xml b/core/tests/coretests/res/values/dimens.xml new file mode 100644 index 000000000000..00fc414327f1 --- /dev/null +++ b/core/tests/coretests/res/values/dimens.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +--> +<resources> + <dimen name="resource_cache_test_generic">10dp</dimen> + <dimen name="resource_cache_test_orientation_dependent">20dp</dimen> +</resources>
\ No newline at end of file diff --git a/core/tests/coretests/src/android/animation/AnimatorInflaterTest.java b/core/tests/coretests/src/android/animation/AnimatorInflaterTest.java new file mode 100644 index 000000000000..3c8185328582 --- /dev/null +++ b/core/tests/coretests/src/android/animation/AnimatorInflaterTest.java @@ -0,0 +1,61 @@ +/* +* Copyright (C) 2014 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.animation; + +import android.test.ActivityInstrumentationTestCase2; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import com.android.frameworks.coretests.R; + +public class AnimatorInflaterTest extends ActivityInstrumentationTestCase2<BasicAnimatorActivity> { + Set<Integer> identityHashes = new HashSet<Integer>(); + + public AnimatorInflaterTest() { + super(BasicAnimatorActivity.class); + } + + private void assertUnique(Object object) { + assertUnique(object, ""); + } + + private void assertUnique(Object object, String msg) { + final int code = System.identityHashCode(object); + assertTrue("object should be unique " + msg + ", obj:" + object, identityHashes.add(code)); + + } + + public void testLoadStateListAnimator() { + StateListAnimator sla1 = AnimatorInflater.loadStateListAnimator(getActivity(), + R.anim.test_state_anim); + sla1.setTarget(getActivity().mAnimatingButton); + StateListAnimator sla2 = AnimatorInflater.loadStateListAnimator(getActivity(), + R.anim.test_state_anim); + assertNull(sla2.getTarget()); + for (StateListAnimator sla : new StateListAnimator[]{sla1, sla2}) { + assertUnique(sla); + assertEquals(3, sla.getTuples().size()); + for (StateListAnimator.Tuple tuple : sla.getTuples()) { + assertUnique(tuple); + assertUnique(tuple.getAnimator()); + } + } + } + +} diff --git a/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java b/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java index 93808d9d7e1c..6bcf8fc43d10 100644 --- a/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java +++ b/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java @@ -19,11 +19,14 @@ import com.android.frameworks.coretests.R; import android.app.Activity; import android.os.Bundle; +import android.widget.Button; public class BasicAnimatorActivity extends Activity { + public Button mAnimatingButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.animator_basic); + mAnimatingButton = (Button) findViewById(R.id.animatingButton); } } diff --git a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java new file mode 100644 index 000000000000..e9fd5fbb3bab --- /dev/null +++ b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.content.res; + +import android.test.ActivityInstrumentationTestCase2; +import android.util.TypedValue; + +import com.android.frameworks.coretests.R; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class ConfigurationBoundResourceCacheTest + extends ActivityInstrumentationTestCase2<ResourceCacheActivity> { + + ConfigurationBoundResourceCache<Float> mCache; + + Method mCalcConfigChanges; + + public ConfigurationBoundResourceCacheTest() { + super(ResourceCacheActivity.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + mCache = new ConfigurationBoundResourceCache<Float>(getActivity().getResources()); + } + + public void testGetEmpty() { + assertNull(mCache.get(-1, null)); + } + + public void testSetGet() { + mCache.put(1, null, new DummyFloatConstantState(5f)); + assertEquals(5f, mCache.get(1, null)); + assertNotSame(5f, mCache.get(1, null)); + assertEquals(null, mCache.get(1, getActivity().getTheme())); + } + + public void testSetGetThemed() { + mCache.put(1, getActivity().getTheme(), new DummyFloatConstantState(5f)); + assertEquals(null, mCache.get(1, null)); + assertEquals(5f, mCache.get(1, getActivity().getTheme())); + assertNotSame(5f, mCache.get(1, getActivity().getTheme())); + } + + public void testMultiThreadPutGet() { + mCache.put(1, getActivity().getTheme(), new DummyFloatConstantState(5f)); + mCache.put(1, null, new DummyFloatConstantState(10f)); + assertEquals(10f, mCache.get(1, null)); + assertNotSame(10f, mCache.get(1, null)); + assertEquals(5f, mCache.get(1, getActivity().getTheme())); + assertNotSame(5f, mCache.get(1, getActivity().getTheme())); + } + + public void testVoidConfigChange() + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + TypedValue staticValue = new TypedValue(); + long key = 3L; + final Resources res = getActivity().getResources(); + res.getValue(R.dimen.resource_cache_test_generic, staticValue, true); + float staticDim = TypedValue.complexToDimension(staticValue.data, res.getDisplayMetrics()); + mCache.put(key, getActivity().getTheme(), + new DummyFloatConstantState(staticDim, staticValue.changingConfigurations)); + final Configuration cfg = res.getConfiguration(); + Configuration newCnf = new Configuration(cfg); + newCnf.orientation = cfg.orientation == Configuration.ORIENTATION_LANDSCAPE ? + Configuration.ORIENTATION_PORTRAIT + : Configuration.ORIENTATION_LANDSCAPE; + int changes = calcConfigChanges(res, newCnf); + assertEquals(staticDim, mCache.get(key, getActivity().getTheme())); + mCache.onConfigurationChange(changes); + assertEquals(staticDim, mCache.get(key, getActivity().getTheme())); + } + + public void testEffectiveConfigChange() + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + TypedValue changingValue = new TypedValue(); + long key = 4L; + final Resources res = getActivity().getResources(); + res.getValue(R.dimen.resource_cache_test_orientation_dependent, changingValue, true); + float changingDim = TypedValue.complexToDimension(changingValue.data, + res.getDisplayMetrics()); + mCache.put(key, getActivity().getTheme(), + new DummyFloatConstantState(changingDim, changingValue.changingConfigurations)); + + final Configuration cfg = res.getConfiguration(); + Configuration newCnf = new Configuration(cfg); + newCnf.orientation = cfg.orientation == Configuration.ORIENTATION_LANDSCAPE ? + Configuration.ORIENTATION_PORTRAIT + : Configuration.ORIENTATION_LANDSCAPE; + int changes = calcConfigChanges(res, newCnf); + assertEquals(changingDim, mCache.get(key, getActivity().getTheme())); + mCache.onConfigurationChange(changes); + assertNull(mCache.get(key, getActivity().getTheme())); + } + + public void testConfigChangeMultipleResources() + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + TypedValue staticValue = new TypedValue(); + TypedValue changingValue = new TypedValue(); + final Resources res = getActivity().getResources(); + res.getValue(R.dimen.resource_cache_test_generic, staticValue, true); + res.getValue(R.dimen.resource_cache_test_orientation_dependent, changingValue, true); + float staticDim = TypedValue.complexToDimension(staticValue.data, res.getDisplayMetrics()); + float changingDim = TypedValue.complexToDimension(changingValue.data, + res.getDisplayMetrics()); + mCache.put(R.dimen.resource_cache_test_generic, getActivity().getTheme(), + new DummyFloatConstantState(staticDim, staticValue.changingConfigurations)); + mCache.put(R.dimen.resource_cache_test_orientation_dependent, getActivity().getTheme(), + new DummyFloatConstantState(changingDim, changingValue.changingConfigurations)); + final Configuration cfg = res.getConfiguration(); + Configuration newCnf = new Configuration(cfg); + newCnf.orientation = cfg.orientation == Configuration.ORIENTATION_LANDSCAPE ? + Configuration.ORIENTATION_PORTRAIT + : Configuration.ORIENTATION_LANDSCAPE; + int changes = calcConfigChanges(res, newCnf); + assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic, + getActivity().getTheme())); + assertEquals(changingDim, mCache.get(R.dimen.resource_cache_test_orientation_dependent, + getActivity().getTheme())); + mCache.onConfigurationChange(changes); + assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic, + getActivity().getTheme())); + assertNull(mCache.get(R.dimen.resource_cache_test_orientation_dependent, + getActivity().getTheme())); + } + + public void testConfigChangeMultipleThemes() + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + TypedValue[] staticValues = new TypedValue[]{new TypedValue(), new TypedValue()}; + TypedValue[] changingValues = new TypedValue[]{new TypedValue(), new TypedValue()}; + float staticDim = 0; + float changingDim = 0; + final Resources res = getActivity().getResources(); + for (int i = 0; i < 2; i++) { + res.getValue(R.dimen.resource_cache_test_generic, staticValues[i], true); + staticDim = TypedValue + .complexToDimension(staticValues[i].data, res.getDisplayMetrics()); + + res.getValue(R.dimen.resource_cache_test_orientation_dependent, changingValues[i], + true); + changingDim = TypedValue.complexToDimension(changingValues[i].data, + res.getDisplayMetrics()); + final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null; + mCache.put(R.dimen.resource_cache_test_generic, theme, + new DummyFloatConstantState(staticDim, staticValues[i].changingConfigurations)); + mCache.put(R.dimen.resource_cache_test_orientation_dependent, theme, + new DummyFloatConstantState(changingDim, + changingValues[i].changingConfigurations)); + } + final Configuration cfg = res.getConfiguration(); + Configuration newCnf = new Configuration(cfg); + newCnf.orientation = cfg.orientation == Configuration.ORIENTATION_LANDSCAPE ? + Configuration.ORIENTATION_PORTRAIT + : Configuration.ORIENTATION_LANDSCAPE; + int changes = calcConfigChanges(res, newCnf); + for (int i = 0; i < 2; i++) { + final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null; + assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic, theme)); + assertEquals(changingDim, + mCache.get(R.dimen.resource_cache_test_orientation_dependent, theme)); + } + mCache.onConfigurationChange(changes); + for (int i = 0; i < 2; i++) { + final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null; + assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic, theme)); + assertNull(mCache.get(R.dimen.resource_cache_test_orientation_dependent, theme)); + } + } + + private int calcConfigChanges(Resources resources, Configuration configuration) + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + if (mCalcConfigChanges == null) { + mCalcConfigChanges = Resources.class.getDeclaredMethod("calcConfigChanges", + Configuration.class); + mCalcConfigChanges.setAccessible(true); + } + return (Integer) mCalcConfigChanges.invoke(resources, configuration); + + } + + static class DummyFloatConstantState extends + ConstantState<Float> { + + final Float mObj; + + int mChangingConf = 0; + + DummyFloatConstantState(Float obj) { + mObj = obj; + } + + DummyFloatConstantState(Float obj, int changingConf) { + mObj = obj; + mChangingConf = changingConf; + } + + @Override + public int getChangingConfigurations() { + return mChangingConf; + } + + @Override + public Float newInstance() { + return new Float(mObj); + } + } +} diff --git a/core/tests/coretests/src/android/content/res/ResourceCacheActivity.java b/core/tests/coretests/src/android/content/res/ResourceCacheActivity.java new file mode 100644 index 000000000000..f37e549940ec --- /dev/null +++ b/core/tests/coretests/src/android/content/res/ResourceCacheActivity.java @@ -0,0 +1,37 @@ +/* +* Copyright (C) 2014 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package android.content.res; + +import android.annotation.Nullable; +import android.app.Activity; +import android.os.Bundle; + +import java.lang.ref.WeakReference; + +public class ResourceCacheActivity extends Activity { + static WeakReference<ResourceCacheActivity> lastCreatedInstance; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + lastCreatedInstance = new WeakReference<ResourceCacheActivity>(this); + } + + public static ResourceCacheActivity getLastCreatedInstance() { + return lastCreatedInstance == null ? null : lastCreatedInstance.get(); + } +} diff --git a/core/tests/coretests/src/android/net/LinkAddressTest.java b/core/tests/coretests/src/android/net/LinkAddressTest.java index 7bc39744d3d9..adf8d95c0b66 100644 --- a/core/tests/coretests/src/android/net/LinkAddressTest.java +++ b/core/tests/coretests/src/android/net/LinkAddressTest.java @@ -33,8 +33,11 @@ import android.test.AndroidTestCase; import static android.test.MoreAsserts.assertNotEqual; import android.test.suitebuilder.annotation.SmallTest; +import static android.system.OsConstants.IFA_F_DADFAILED; import static android.system.OsConstants.IFA_F_DEPRECATED; +import static android.system.OsConstants.IFA_F_OPTIMISTIC; import static android.system.OsConstants.IFA_F_PERMANENT; +import static android.system.OsConstants.IFA_F_TEMPORARY; import static android.system.OsConstants.IFA_F_TENTATIVE; import static android.system.OsConstants.RT_SCOPE_HOST; import static android.system.OsConstants.RT_SCOPE_LINK; @@ -340,4 +343,73 @@ public class LinkAddressTest extends AndroidTestCase { l = new LinkAddress(V4 + "/28", IFA_F_PERMANENT, RT_SCOPE_LINK); assertParcelingIsLossless(l); } + + private void assertGlobalPreferred(LinkAddress l, String msg) { + assertTrue(msg, l.isGlobalPreferred()); + } + + private void assertNotGlobalPreferred(LinkAddress l, String msg) { + assertFalse(msg, l.isGlobalPreferred()); + } + + public void testIsGlobalPreferred() { + LinkAddress l; + + l = new LinkAddress(V4_ADDRESS, 32, 0, RT_SCOPE_UNIVERSE); + assertGlobalPreferred(l, "v4,global,noflags"); + + l = new LinkAddress("10.10.1.7/23", 0, RT_SCOPE_UNIVERSE); + assertGlobalPreferred(l, "v4-rfc1918,global,noflags"); + + l = new LinkAddress("10.10.1.7/23", 0, RT_SCOPE_SITE); + assertNotGlobalPreferred(l, "v4-rfc1918,site-local,noflags"); + + l = new LinkAddress("127.0.0.7/8", 0, RT_SCOPE_HOST); + assertNotGlobalPreferred(l, "v4-localhost,node-local,noflags"); + + l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_UNIVERSE); + assertGlobalPreferred(l, "v6,global,noflags"); + + l = new LinkAddress(V6_ADDRESS, 64, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE); + assertGlobalPreferred(l, "v6,global,permanent"); + + // IPv6 ULAs are not acceptable "global preferred" addresses. + l = new LinkAddress("fc12::1/64", 0, RT_SCOPE_UNIVERSE); + assertNotGlobalPreferred(l, "v6,ula1,noflags"); + + l = new LinkAddress("fd34::1/64", 0, RT_SCOPE_UNIVERSE); + assertNotGlobalPreferred(l, "v6,ula2,noflags"); + + l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_UNIVERSE); + assertGlobalPreferred(l, "v6,global,tempaddr"); + + l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_DADFAILED), + RT_SCOPE_UNIVERSE); + assertNotGlobalPreferred(l, "v6,global,tempaddr+dadfailed"); + + l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_DEPRECATED), + RT_SCOPE_UNIVERSE); + assertNotGlobalPreferred(l, "v6,global,tempaddr+deprecated"); + + l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_SITE); + assertNotGlobalPreferred(l, "v6,site-local,tempaddr"); + + l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_LINK); + assertNotGlobalPreferred(l, "v6,link-local,tempaddr"); + + l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_HOST); + assertNotGlobalPreferred(l, "v6,node-local,tempaddr"); + + l = new LinkAddress("::1/128", IFA_F_PERMANENT, RT_SCOPE_HOST); + assertNotGlobalPreferred(l, "v6-localhost,node-local,permanent"); + + l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_TENTATIVE), + RT_SCOPE_UNIVERSE); + assertNotGlobalPreferred(l, "v6,global,tempaddr+tentative"); + + l = new LinkAddress(V6_ADDRESS, 64, + (IFA_F_TEMPORARY|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC), + RT_SCOPE_UNIVERSE); + assertGlobalPreferred(l, "v6,global,tempaddr+optimistic"); + } } diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java index 4015b3d65bc7..abfed6e6f89a 100644 --- a/core/tests/coretests/src/android/net/LinkPropertiesTest.java +++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java @@ -31,8 +31,10 @@ public class LinkPropertiesTest extends TestCase { "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); private static InetAddress DNS1 = NetworkUtils.numericToInetAddress("75.208.7.1"); private static InetAddress DNS2 = NetworkUtils.numericToInetAddress("69.78.7.1"); + private static InetAddress DNS6 = NetworkUtils.numericToInetAddress("2001:4860:4860::8888"); private static InetAddress GATEWAY1 = NetworkUtils.numericToInetAddress("75.208.8.1"); private static InetAddress GATEWAY2 = NetworkUtils.numericToInetAddress("69.78.8.1"); + private static InetAddress GATEWAY6 = NetworkUtils.numericToInetAddress("fe80::6:0000:613"); private static String NAME = "qmi0"; private static int MTU = 1500; @@ -338,14 +340,14 @@ public class LinkPropertiesTest extends TestCase { assertFalse("newname".equals(link.getInterfaceName())); } - assertTrue(rmnet0.removeStackedLink(clat4)); + assertTrue(rmnet0.removeStackedLink("clat4")); assertEquals(0, rmnet0.getStackedLinks().size()); assertEquals(1, rmnet0.getAddresses().size()); assertEquals(1, rmnet0.getLinkAddresses().size()); assertEquals(1, rmnet0.getAllAddresses().size()); assertEquals(1, rmnet0.getAllLinkAddresses().size()); - assertFalse(rmnet0.removeStackedLink(clat4)); + assertFalse(rmnet0.removeStackedLink("clat4")); } private LinkAddress getFirstLinkAddress(LinkProperties lp) { @@ -370,7 +372,7 @@ public class LinkPropertiesTest extends TestCase { assertTrue(stacked.hasGlobalIPv6Address()); assertFalse(lp.hasIPv4Address()); assertFalse(lp.hasGlobalIPv6Address()); - lp.removeStackedLink(stacked); + lp.removeStackedLink("stacked"); assertFalse(lp.hasIPv4Address()); assertFalse(lp.hasGlobalIPv6Address()); @@ -453,4 +455,47 @@ public class LinkPropertiesTest extends TestCase { lp2.setLinkAddresses(lp.getLinkAddresses()); assertTrue(lp.equals(lp)); } + + @SmallTest + public void testIsProvisioned() { + LinkProperties lp4 = new LinkProperties(); + assertFalse("v4only:empty", lp4.isProvisioned()); + lp4.addLinkAddress(LINKADDRV4); + assertFalse("v4only:addr-only", lp4.isProvisioned()); + lp4.addDnsServer(DNS1); + assertFalse("v4only:addr+dns", lp4.isProvisioned()); + lp4.addRoute(new RouteInfo(GATEWAY1)); + assertTrue("v4only:addr+dns+route", lp4.isProvisioned()); + + LinkProperties lp6 = new LinkProperties(); + assertFalse("v6only:empty", lp6.isProvisioned()); + lp6.addLinkAddress(LINKADDRV6LINKLOCAL); + assertFalse("v6only:fe80-only", lp6.isProvisioned()); + lp6.addDnsServer(DNS6); + assertFalse("v6only:fe80+dns", lp6.isProvisioned()); + lp6.addRoute(new RouteInfo(GATEWAY6)); + assertFalse("v6only:fe80+dns+route", lp6.isProvisioned()); + lp6.addLinkAddress(LINKADDRV6); + assertTrue("v6only:fe80+global+dns+route", lp6.isProvisioned()); + lp6.removeLinkAddress(LINKADDRV6LINKLOCAL); + assertTrue("v6only:global+dns+route", lp6.isProvisioned()); + + LinkProperties lp46 = new LinkProperties(); + lp46.addLinkAddress(LINKADDRV4); + lp46.addLinkAddress(LINKADDRV6); + lp46.addDnsServer(DNS1); + lp46.addDnsServer(DNS6); + assertFalse("dualstack:missing-routes", lp46.isProvisioned()); + lp46.addRoute(new RouteInfo(GATEWAY1)); + assertTrue("dualstack:v4-provisioned", lp46.isProvisioned()); + lp6.addRoute(new RouteInfo(GATEWAY6)); + assertTrue("dualstack:both-provisioned", lp46.isProvisioned()); + + // A link with an IPv6 address and default route, but IPv4 DNS server. + LinkProperties mixed = new LinkProperties(); + mixed.addLinkAddress(LINKADDRV6); + mixed.addDnsServer(DNS1); + mixed.addRoute(new RouteInfo(GATEWAY6)); + assertFalse("mixed:addr6+route6+dns4", mixed.isProvisioned()); + } } diff --git a/docs/html/tools/testing/activity_testing.jd b/docs/html/tools/testing/activity_testing.jd index 88ac9b2351f7..8baa35de88e8 100644 --- a/docs/html/tools/testing/activity_testing.jd +++ b/docs/html/tools/testing/activity_testing.jd @@ -242,7 +242,7 @@ parent.link=index.html This changes when you run tests against the application. With instrumentation-based classes, you can invoke methods against the UI of the application under test. The other test classes don't allow this. To run an entire test method on the UI thread, you can annotate the thread - with <code>@UIThreadTest</code>. Notice that this will run <em>all</em> of the method statements + with <code>@UiThreadTest</code>. Notice that this will run <em>all</em> of the method statements on the UI thread. Methods that do not interact with the UI are not allowed; for example, you can't invoke <code>Instrumentation.waitForIdleSync()</code>. </p> diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java index 9fb3fb4a5670..d2799e1a496c 100644 --- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java @@ -16,6 +16,8 @@ package android.graphics.drawable; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.ColorFilter; @@ -41,6 +43,7 @@ import com.android.internal.R; */ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callback, Runnable, Animatable { + private static final String TAG = "AnimatedRotateDrawable"; private AnimatedRotateState mState; private boolean mMutated; @@ -186,6 +189,11 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac } @Override + public boolean canApplyTheme() { + return (mState != null && mState.canApplyTheme()) || super.canApplyTheme(); + } + + @Override public void invalidateDrawable(Drawable who) { final Callback callback = getCallback(); if (callback != null) { @@ -254,62 +262,112 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac } @Override - public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme) + public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser, + @NonNull AttributeSet attrs, @Nullable Theme theme) throws XmlPullParserException, IOException { - final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.AnimatedRotateDrawable); - super.inflateWithAttributes(r, parser, a, R.styleable.AnimatedRotateDrawable_visible); + updateStateFromTypedArray(a); + a.recycle(); - TypedValue tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotX); - final boolean pivotXRel = tv.type == TypedValue.TYPE_FRACTION; - final float pivotX = pivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); + inflateChildElements(r, parser, attrs, theme); - tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotY); - final boolean pivotYRel = tv.type == TypedValue.TYPE_FRACTION; - final float pivotY = pivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); + init(); + } - setFramesCount(a.getInt(R.styleable.AnimatedRotateDrawable_framesCount, 12)); - setFramesDuration(a.getInt(R.styleable.AnimatedRotateDrawable_frameDuration, 150)); + @Override + public void applyTheme(@Nullable Theme t) { + super.applyTheme(t); - final int res = a.getResourceId(R.styleable.AnimatedRotateDrawable_drawable, 0); - Drawable drawable = null; - if (res > 0) { - drawable = r.getDrawable(res, theme); + final AnimatedRotateState state = mState; + if (state == null) { + return; } - a.recycle(); + if (state.mThemeAttrs != null) { + final TypedArray a = t.resolveAttributes( + state.mThemeAttrs, R.styleable.AnimatedRotateDrawable); + try { + updateStateFromTypedArray(a); + verifyRequiredAttributes(a); + } catch (XmlPullParserException e) { + throw new RuntimeException(e); + } finally { + a.recycle(); + } + } + + if (state.mDrawable != null && state.mDrawable.canApplyTheme()) { + state.mDrawable.applyTheme(t); + } + + init(); + } + private void updateStateFromTypedArray(TypedArray a) { + final AnimatedRotateState state = mState; + + // Account for any configuration changes. + state.mChangingConfigurations |= a.getChangingConfigurations(); + + // Extract the theme attributes, if any. + state.mThemeAttrs = a.extractThemeAttrs(); + + if (a.hasValue(R.styleable.AnimatedRotateDrawable_pivotX)) { + final TypedValue tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotX); + state.mPivotXRel = tv.type == TypedValue.TYPE_FRACTION; + state.mPivotX = state.mPivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); + } + + if (a.hasValue(R.styleable.AnimatedRotateDrawable_pivotY)) { + final TypedValue tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotY); + state.mPivotYRel = tv.type == TypedValue.TYPE_FRACTION; + state.mPivotY = state.mPivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); + } + + setFramesCount(a.getInt( + R.styleable.AnimatedRotateDrawable_framesCount, state.mFramesCount)); + setFramesDuration(a.getInt( + R.styleable.AnimatedRotateDrawable_frameDuration, state.mFrameDuration)); + + final Drawable dr = a.getDrawable(R.styleable.AnimatedRotateDrawable_drawable); + if (dr != null) { + state.mDrawable = dr; + dr.setCallback(this); + } + } + + private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs, + Theme theme) throws XmlPullParserException, IOException { + final AnimatedRotateState state = mState; + + Drawable dr = null; int outerDepth = parser.getDepth(); int type; - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && - (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { - + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { if (type != XmlPullParser.START_TAG) { continue; } - if ((drawable = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) { - Log.w("drawable", "Bad element under <animated-rotate>: " - + parser .getName()); + if ((dr = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) { + Log.w(TAG, "Bad element under <animated-rotate>: " + parser.getName()); } } - if (drawable == null) { - Log.w("drawable", "No drawable specified for <animated-rotate>"); + if (dr != null) { + state.mDrawable = dr; + dr.setCallback(this); } + } - final AnimatedRotateState rotateState = mState; - rotateState.mDrawable = drawable; - rotateState.mPivotXRel = pivotXRel; - rotateState.mPivotX = pivotX; - rotateState.mPivotYRel = pivotYRel; - rotateState.mPivotY = pivotY; - - init(); - - if (drawable != null) { - drawable.setCallback(this); + private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException { + // If we're not waiting on a theme, verify required attributes. + if (mState.mDrawable == null && (mState.mThemeAttrs == null + || mState.mThemeAttrs[R.styleable.AnimatedRotateDrawable_drawable] == 0)) { + throw new XmlPullParserException(a.getPositionDescription() + + ": <animated-rotate> tag requires a 'drawable' attribute or " + + "child tag defining a drawable"); } } @@ -331,17 +389,27 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac return this; } + /** + * @hide + */ + public void clearMutated() { + super.clearMutated(); + mState.mDrawable.clearMutated(); + mMutated = false; + } + final static class AnimatedRotateState extends Drawable.ConstantState { Drawable mDrawable; + int[] mThemeAttrs; int mChangingConfigurations; - boolean mPivotXRel; - float mPivotX; - boolean mPivotYRel; - float mPivotY; - int mFrameDuration; - int mFramesCount; + boolean mPivotXRel = false; + float mPivotX = 0; + boolean mPivotYRel = false; + float mPivotY = 0; + int mFrameDuration = 150; + int mFramesCount = 12; private boolean mCanConstantState; private boolean mCheckedConstantState; @@ -358,6 +426,7 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection()); mDrawable.setBounds(orig.mDrawable.getBounds()); mDrawable.setLevel(orig.mDrawable.getLevel()); + mThemeAttrs = orig.mThemeAttrs; mPivotXRel = orig.mPivotXRel; mPivotX = orig.mPivotX; mPivotYRel = orig.mPivotYRel; @@ -379,6 +448,12 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac } @Override + public boolean canApplyTheme() { + return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme()) + || super.canApplyTheme(); + } + + @Override public int getChangingConfigurations() { return mChangingConfigurations; } diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java index cb09bbf3b3ab..5a3a6177d586 100644 --- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java @@ -139,27 +139,15 @@ public class AnimatedStateListDrawable extends StateListDrawable { @Override protected boolean onStateChange(int[] stateSet) { - final int keyframeIndex = mState.indexOfKeyframe(stateSet); - if (keyframeIndex == getCurrentIndex()) { - // Propagate state change to current keyframe. - final Drawable current = getCurrent(); - if (current != null) { - return current.setState(stateSet); - } - return false; - } - - // Attempt to find a valid transition to the keyframe. - if (selectTransition(keyframeIndex)) { - return true; - } - - // No valid transition, attempt to jump directly to the keyframe. - if (selectDrawable(keyframeIndex)) { - return true; - } - - return super.onStateChange(stateSet); + // If we're not already at the target index, either attempt to find a + // valid transition to it or jump directly there. + final int targetIndex = mState.indexOfKeyframe(stateSet); + final boolean changedIndex = targetIndex != getCurrentIndex() + && (selectTransition(targetIndex) || selectDrawable(targetIndex)); + + // Always call super.onStateChanged() to propagate the state change to + // the current drawable. + return super.onStateChange(stateSet) || changedIndex; } private boolean selectTransition(int toIndex) { @@ -359,24 +347,62 @@ public class AnimatedStateListDrawable extends StateListDrawable { throws XmlPullParserException, IOException { final TypedArray a = obtainAttributes( r, theme, attrs, R.styleable.AnimatedStateListDrawable); - super.inflateWithAttributes(r, parser, a, R.styleable.AnimatedStateListDrawable_visible); + updateStateFromTypedArray(a); + a.recycle(); - final StateListState stateListState = getStateListState(); - stateListState.setVariablePadding(a.getBoolean( - R.styleable.AnimatedStateListDrawable_variablePadding, false)); - stateListState.setConstantSize(a.getBoolean( - R.styleable.AnimatedStateListDrawable_constantSize, false)); - stateListState.setEnterFadeDuration(a.getInt( - R.styleable.AnimatedStateListDrawable_enterFadeDuration, 0)); - stateListState.setExitFadeDuration(a.getInt( - R.styleable.AnimatedStateListDrawable_exitFadeDuration, 0)); + inflateChildElements(r, parser, attrs, theme); - setDither(a.getBoolean(R.styleable.AnimatedStateListDrawable_dither, true)); - setAutoMirrored(a.getBoolean(R.styleable.AnimatedStateListDrawable_autoMirrored, false)); + init(); + } + + @Override + public void applyTheme(@Nullable Theme theme) { + super.applyTheme(theme); + final AnimatedStateListState state = mState; + if (state == null || state.mAnimThemeAttrs == null) { + return; + } + + final TypedArray a = theme.resolveAttributes( + state.mAnimThemeAttrs, R.styleable.AnimatedRotateDrawable); + updateStateFromTypedArray(a); a.recycle(); + init(); + } + + private void updateStateFromTypedArray(TypedArray a) { + final AnimatedStateListState state = mState; + + // Account for any configuration changes. + state.mChangingConfigurations |= a.getChangingConfigurations(); + + // Extract the theme attributes, if any. + state.mAnimThemeAttrs = a.extractThemeAttrs(); + + state.setVariablePadding(a.getBoolean( + R.styleable.AnimatedStateListDrawable_variablePadding, state.mVariablePadding)); + state.setConstantSize(a.getBoolean( + R.styleable.AnimatedStateListDrawable_constantSize, state.mConstantSize)); + state.setEnterFadeDuration(a.getInt( + R.styleable.AnimatedStateListDrawable_enterFadeDuration, state.mEnterFadeDuration)); + state.setExitFadeDuration(a.getInt( + R.styleable.AnimatedStateListDrawable_exitFadeDuration, state.mExitFadeDuration)); + + setDither(a.getBoolean( + R.styleable.AnimatedStateListDrawable_dither, state.mDither)); + setAutoMirrored(a.getBoolean( + R.styleable.AnimatedStateListDrawable_autoMirrored, state.mAutoMirrored)); + } + + private void init() { + onStateChange(getState()); + } + + private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs, + Theme theme) throws XmlPullParserException, IOException { int type; final int innerDepth = parser.getDepth() + 1; @@ -398,8 +424,6 @@ public class AnimatedStateListDrawable extends StateListDrawable { parseTransition(r, parser, attrs, theme); } } - - onStateChange(getState()); } private int parseTransition(@NonNull Resources r, @NonNull XmlPullParser parser, @@ -507,10 +531,20 @@ public class AnimatedStateListDrawable extends StateListDrawable { return this; } + /** + * @hide + */ + public void clearMutated() { + super.clearMutated(); + mMutated = false; + } + static class AnimatedStateListState extends StateListState { private static final int REVERSE_SHIFT = 32; private static final int REVERSE_MASK = 0x1; + int[] mAnimThemeAttrs; + final LongSparseLongArray mTransitions; final SparseIntArray mStateIds; @@ -519,6 +553,7 @@ public class AnimatedStateListDrawable extends StateListDrawable { super(orig, owner, res); if (orig != null) { + mAnimThemeAttrs = orig.mAnimThemeAttrs; mTransitions = orig.mTransitions.clone(); mStateIds = orig.mStateIds.clone(); } else { @@ -570,6 +605,11 @@ public class AnimatedStateListDrawable extends StateListDrawable { } @Override + public boolean canApplyTheme() { + return mAnimThemeAttrs != null || super.canApplyTheme(); + } + + @Override public Drawable newDrawable() { return new AnimatedStateListDrawable(this, null); } diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index ad0b4157f4d7..e65dbaf077b6 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -16,7 +16,6 @@ package android.graphics.drawable; import android.animation.Animator; import android.animation.AnimatorInflater; -import android.animation.ValueAnimator; import android.annotation.NonNull; import android.content.res.ColorStateList; import android.content.res.Resources; @@ -137,15 +136,11 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { private boolean mMutated; public AnimatedVectorDrawable() { - mAnimatedVectorState = new AnimatedVectorDrawableState(null); + this(null, null); } - private AnimatedVectorDrawable(AnimatedVectorDrawableState state, Resources res, - Theme theme) { - mAnimatedVectorState = new AnimatedVectorDrawableState(state); - if (theme != null && canApplyTheme()) { - applyTheme(theme); - } + private AnimatedVectorDrawable(AnimatedVectorDrawableState state, Resources res) { + mAnimatedVectorState = new AnimatedVectorDrawableState(state, mCallback, res); } @Override @@ -157,6 +152,15 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { return this; } + /** + * @hide + */ + public void clearMutated() { + super.clearMutated(); + mAnimatedVectorState.mVectorDrawable.clearMutated(); + mMutated = false; + } + @Override public ConstantState getConstantState() { mAnimatedVectorState.mChangingConfigurations = getChangingConfigurations(); @@ -281,7 +285,11 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { VectorDrawable vectorDrawable = (VectorDrawable) res.getDrawable( drawableRes, theme).mutate(); vectorDrawable.setAllowCaching(false); + vectorDrawable.setCallback(mCallback); pathErrorScale = vectorDrawable.getPixelSize(); + if (mAnimatedVectorState.mVectorDrawable != null) { + mAnimatedVectorState.mVectorDrawable.setCallback(null); + } mAnimatedVectorState.mVectorDrawable = vectorDrawable; } a.recycle(); @@ -308,9 +316,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { @Override public boolean canApplyTheme() { - return super.canApplyTheme() || mAnimatedVectorState != null - && mAnimatedVectorState.mVectorDrawable != null - && mAnimatedVectorState.mVectorDrawable.canApplyTheme(); + return (mAnimatedVectorState != null && mAnimatedVectorState.canApplyTheme()) + || super.canApplyTheme(); } @Override @@ -329,14 +336,22 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { ArrayList<Animator> mAnimators; ArrayMap<Animator, String> mTargetNameMap; - public AnimatedVectorDrawableState(AnimatedVectorDrawableState copy) { + public AnimatedVectorDrawableState(AnimatedVectorDrawableState copy, + Callback owner, Resources res) { if (copy != null) { mChangingConfigurations = copy.mChangingConfigurations; if (copy.mVectorDrawable != null) { - mVectorDrawable = (VectorDrawable) copy.mVectorDrawable.getConstantState().newDrawable(); - mVectorDrawable.mutate(); - mVectorDrawable.setAllowCaching(false); + final ConstantState cs = copy.mVectorDrawable.getConstantState(); + if (res != null) { + mVectorDrawable = (VectorDrawable) cs.newDrawable(res); + } else { + mVectorDrawable = (VectorDrawable) cs.newDrawable(); + } + mVectorDrawable = (VectorDrawable) mVectorDrawable.mutate(); + mVectorDrawable.setCallback(owner); + mVectorDrawable.setLayoutDirection(copy.mVectorDrawable.getLayoutDirection()); mVectorDrawable.setBounds(copy.mVectorDrawable.getBounds()); + mVectorDrawable.setAllowCaching(false); } if (copy.mAnimators != null) { final int numAnimators = copy.mAnimators.size(); @@ -358,18 +373,19 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { } @Override - public Drawable newDrawable() { - return new AnimatedVectorDrawable(this, null, null); + public boolean canApplyTheme() { + return (mVectorDrawable != null && mVectorDrawable.canApplyTheme()) + || super.canApplyTheme(); } @Override - public Drawable newDrawable(Resources res) { - return new AnimatedVectorDrawable(this, res, null); + public Drawable newDrawable() { + return new AnimatedVectorDrawable(this, null); } @Override - public Drawable newDrawable(Resources res, Theme theme) { - return new AnimatedVectorDrawable(this, res, theme); + public Drawable newDrawable(Resources res) { + return new AnimatedVectorDrawable(this, res); } @Override @@ -473,4 +489,21 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { } return true; } + + private final Callback mCallback = new Callback() { + @Override + public void invalidateDrawable(Drawable who) { + invalidateSelf(); + } + + @Override + public void scheduleDrawable(Drawable who, Runnable what, long when) { + scheduleSelf(what, when); + } + + @Override + public void unscheduleDrawable(Drawable who, Runnable what) { + unscheduleSelf(what); + } + }; } diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java index 9a9fd823b57e..a8b6c9438474 100644 --- a/graphics/java/android/graphics/drawable/AnimationDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java @@ -16,6 +16,8 @@ package android.graphics.drawable; +import com.android.internal.R; + import java.io.IOException; import org.xmlpull.v1.XmlPullParser; @@ -271,27 +273,25 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An @Override public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme) throws XmlPullParserException, IOException { + final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.AnimationDrawable); + super.inflateWithAttributes(r, parser, a, R.styleable.AnimationDrawable_visible); + updateStateFromTypedArray(a); + a.recycle(); - TypedArray a = obtainAttributes(r, theme, attrs, - com.android.internal.R.styleable.AnimationDrawable); - - super.inflateWithAttributes(r, parser, a, - com.android.internal.R.styleable.AnimationDrawable_visible); - - mAnimationState.setVariablePadding(a.getBoolean( - com.android.internal.R.styleable.AnimationDrawable_variablePadding, false)); - - mAnimationState.mOneShot = a.getBoolean( - com.android.internal.R.styleable.AnimationDrawable_oneshot, false); + inflateChildElements(r, parser, attrs, theme); - a.recycle(); + setFrame(0, true, false); + } + private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs, + Theme theme) throws XmlPullParserException, IOException { + TypedArray a; int type; final int innerDepth = parser.getDepth()+1; int depth; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT && - ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { + while ((type=parser.next()) != XmlPullParser.END_DOCUMENT + && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { if (type != XmlPullParser.START_TAG) { continue; } @@ -300,17 +300,15 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An continue; } - a = obtainAttributes( - r, theme, attrs, com.android.internal.R.styleable.AnimationDrawableItem); - int duration = a.getInt( - com.android.internal.R.styleable.AnimationDrawableItem_duration, -1); + a = obtainAttributes(r, theme, attrs, R.styleable.AnimationDrawableItem); + + final int duration = a.getInt(R.styleable.AnimationDrawableItem_duration, -1); if (duration < 0) { - throw new XmlPullParserException( - parser.getPositionDescription() + throw new XmlPullParserException(parser.getPositionDescription() + ": <item> tag requires a 'duration' attribute"); } - int drawableRes = a.getResourceId( - com.android.internal.R.styleable.AnimationDrawableItem_drawable, 0); + + final int drawableRes = a.getResourceId(R.styleable.AnimationDrawableItem_drawable, 0); a.recycle(); @@ -322,9 +320,9 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An // Empty } if (type != XmlPullParser.START_TAG) { - throw new XmlPullParserException(parser.getPositionDescription() + - ": <item> tag requires a 'drawable' attribute or child tag" + - " defining a drawable"); + throw new XmlPullParserException(parser.getPositionDescription() + + ": <item> tag requires a 'drawable' attribute or child tag" + + " defining a drawable"); } dr = Drawable.createFromXmlInner(r, parser, attrs, theme); } @@ -334,8 +332,14 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An dr.setCallback(this); } } + } - setFrame(0, true, false); + private void updateStateFromTypedArray(TypedArray a) { + mAnimationState.mVariablePadding = a.getBoolean( + R.styleable.AnimationDrawable_variablePadding, mAnimationState.mVariablePadding); + + mAnimationState.mOneShot = a.getBoolean( + R.styleable.AnimationDrawable_oneshot, mAnimationState.mOneShot); } @Override @@ -347,9 +351,17 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An return this; } + /** + * @hide + */ + public void clearMutated() { + super.clearMutated(); + mMutated = false; + } + private final static class AnimationState extends DrawableContainerState { private int[] mDurations; - private boolean mOneShot; + private boolean mOneShot = false; AnimationState(AnimationState orig, AnimationDrawable owner, Resources res) { diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java index cf6be486413b..79ac651a3573 100644 --- a/graphics/java/android/graphics/drawable/BitmapDrawable.java +++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java @@ -132,7 +132,7 @@ public class BitmapDrawable extends Drawable { */ @Deprecated public BitmapDrawable(Bitmap bitmap) { - this(new BitmapState(bitmap), null, null); + this(new BitmapState(bitmap), null); } /** @@ -140,7 +140,7 @@ public class BitmapDrawable extends Drawable { * the display metrics of the resources. */ public BitmapDrawable(Resources res, Bitmap bitmap) { - this(new BitmapState(bitmap), res, null); + this(new BitmapState(bitmap), res); mBitmapState.mTargetDensity = mTargetDensity; } @@ -151,7 +151,7 @@ public class BitmapDrawable extends Drawable { */ @Deprecated public BitmapDrawable(String filepath) { - this(new BitmapState(BitmapFactory.decodeFile(filepath)), null, null); + this(new BitmapState(BitmapFactory.decodeFile(filepath)), null); if (mBitmapState.mBitmap == null) { android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath); } @@ -162,7 +162,7 @@ public class BitmapDrawable extends Drawable { */ @SuppressWarnings("unused") public BitmapDrawable(Resources res, String filepath) { - this(new BitmapState(BitmapFactory.decodeFile(filepath)), null, null); + this(new BitmapState(BitmapFactory.decodeFile(filepath)), null); mBitmapState.mTargetDensity = mTargetDensity; if (mBitmapState.mBitmap == null) { android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath); @@ -176,7 +176,7 @@ public class BitmapDrawable extends Drawable { */ @Deprecated public BitmapDrawable(java.io.InputStream is) { - this(new BitmapState(BitmapFactory.decodeStream(is)), null, null); + this(new BitmapState(BitmapFactory.decodeStream(is)), null); if (mBitmapState.mBitmap == null) { android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is); } @@ -187,7 +187,7 @@ public class BitmapDrawable extends Drawable { */ @SuppressWarnings("unused") public BitmapDrawable(Resources res, java.io.InputStream is) { - this(new BitmapState(BitmapFactory.decodeStream(is)), null, null); + this(new BitmapState(BitmapFactory.decodeStream(is)), null); mBitmapState.mTargetDensity = mTargetDensity; if (mBitmapState.mBitmap == null) { android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is); @@ -684,6 +684,14 @@ public class BitmapDrawable extends Drawable { return this; } + /** + * @hide + */ + public void clearMutated() { + super.clearMutated(); + mMutated = false; + } + @Override protected boolean onStateChange(int[] stateSet) { final BitmapState state = mBitmapState; @@ -911,17 +919,12 @@ public class BitmapDrawable extends Drawable { @Override public Drawable newDrawable() { - return new BitmapDrawable(this, null, null); + return new BitmapDrawable(this, null); } @Override public Drawable newDrawable(Resources res) { - return new BitmapDrawable(this, res, null); - } - - @Override - public Drawable newDrawable(Resources res, Theme theme) { - return new BitmapDrawable(this, res, theme); + return new BitmapDrawable(this, res); } @Override @@ -934,16 +937,10 @@ public class BitmapDrawable extends Drawable { * The one constructor to rule them all. This is called by all public * constructors to set the state and initialize local properties. */ - private BitmapDrawable(BitmapState state, Resources res, Theme theme) { - if (theme != null && state.canApplyTheme()) { - // If we need to apply a theme, implicitly mutate. - mBitmapState = new BitmapState(state); - applyTheme(theme); - } else { - mBitmapState = state; - } + private BitmapDrawable(BitmapState state, Resources res) { + mBitmapState = state; - initializeWithState(state, res); + initializeWithState(mBitmapState, res); } /** diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java index 40711cff3901..e5b2b768cd16 100644 --- a/graphics/java/android/graphics/drawable/ClipDrawable.java +++ b/graphics/java/android/graphics/drawable/ClipDrawable.java @@ -16,6 +16,8 @@ package android.graphics.drawable; +import com.android.internal.R; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -49,12 +51,14 @@ import java.io.IOException; * @attr ref android.R.styleable#ClipDrawable_drawable */ public class ClipDrawable extends Drawable implements Drawable.Callback { - private ClipState mClipState; + private ClipState mState; private final Rect mTmpRect = new Rect(); public static final int HORIZONTAL = 1; public static final int VERTICAL = 2; + private boolean mMutated; + ClipDrawable() { this(null, null); } @@ -65,9 +69,9 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { public ClipDrawable(Drawable drawable, int gravity, int orientation) { this(null, null); - mClipState.mDrawable = drawable; - mClipState.mGravity = gravity; - mClipState.mOrientation = orientation; + mState.mDrawable = drawable; + mState.mGravity = gravity; + mState.mOrientation = orientation; if (drawable != null) { drawable.setCallback(this); @@ -79,19 +83,22 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { throws XmlPullParserException, IOException { super.inflate(r, parser, attrs, theme); - int type; - - TypedArray a = obtainAttributes( - r, theme, attrs, com.android.internal.R.styleable.ClipDrawable); + final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.ClipDrawable); - int orientation = a.getInt( - com.android.internal.R.styleable.ClipDrawable_clipOrientation, - HORIZONTAL); - int g = a.getInt(com.android.internal.R.styleable.ClipDrawable_gravity, Gravity.LEFT); - Drawable dr = a.getDrawable(com.android.internal.R.styleable.ClipDrawable_drawable); + // Reset mDrawable to preserve old multiple-inflate behavior. This is + // silly, but we have CTS tests that rely on it. + mState.mDrawable = null; + updateStateFromTypedArray(a); + inflateChildElements(r, parser, attrs, theme); + verifyRequiredAttributes(a); a.recycle(); + } + private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs, + Theme theme) throws XmlPullParserException, IOException { + Drawable dr = null; + int type; final int outerDepth = parser.getDepth(); while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { @@ -101,15 +108,68 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { dr = Drawable.createFromXmlInner(r, parser, attrs, theme); } - if (dr == null) { - throw new IllegalArgumentException("No drawable specified for <clip>"); + if (dr != null) { + mState.mDrawable = dr; + dr.setCallback(this); + } + } + + private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException { + // If we're not waiting on a theme, verify required attributes. + if (mState.mDrawable == null && (mState.mThemeAttrs == null + || mState.mThemeAttrs[R.styleable.ClipDrawable_drawable] == 0)) { + throw new XmlPullParserException(a.getPositionDescription() + + ": <clip> tag requires a 'drawable' attribute or " + + "child tag defining a drawable"); + } + } + + private void updateStateFromTypedArray(TypedArray a) { + final ClipState state = mState; + + // Account for any configuration changes. + state.mChangingConfigurations |= a.getChangingConfigurations(); + + // Extract the theme attributes, if any. + state.mThemeAttrs = a.extractThemeAttrs(); + + state.mOrientation = a.getInt(R.styleable.ClipDrawable_clipOrientation, state.mOrientation); + state.mGravity = a.getInt(R.styleable.ClipDrawable_gravity, state.mGravity); + + final Drawable dr = a.getDrawable(R.styleable.ClipDrawable_drawable); + if (dr != null) { + state.mDrawable = dr; + dr.setCallback(this); + } + } + + @Override + public void applyTheme(Theme t) { + super.applyTheme(t); + + final ClipState state = mState; + if (state == null || state.mThemeAttrs == null) { + return; + } + + final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ClipDrawable); + try { + updateStateFromTypedArray(a); + verifyRequiredAttributes(a); + } catch (XmlPullParserException e) { + throw new RuntimeException(e); + } finally { + a.recycle(); } - mClipState.mDrawable = dr; - mClipState.mOrientation = orientation; - mClipState.mGravity = g; + if (state.mDrawable != null && state.mDrawable.canApplyTheme()) { + state.mDrawable.applyTheme(t); + } + } - dr.setCallback(this); + @Override + public boolean canApplyTheme() { + return (mState != null && mState.canApplyTheme()) || super.canApplyTheme(); } // overrides from Drawable.Callback @@ -143,78 +203,78 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { @Override public int getChangingConfigurations() { return super.getChangingConfigurations() - | mClipState.mChangingConfigurations - | mClipState.mDrawable.getChangingConfigurations(); + | mState.mChangingConfigurations + | mState.mDrawable.getChangingConfigurations(); } @Override public boolean getPadding(Rect padding) { // XXX need to adjust padding! - return mClipState.mDrawable.getPadding(padding); + return mState.mDrawable.getPadding(padding); } @Override public boolean setVisible(boolean visible, boolean restart) { - mClipState.mDrawable.setVisible(visible, restart); + mState.mDrawable.setVisible(visible, restart); return super.setVisible(visible, restart); } @Override public void setAlpha(int alpha) { - mClipState.mDrawable.setAlpha(alpha); + mState.mDrawable.setAlpha(alpha); } @Override public int getAlpha() { - return mClipState.mDrawable.getAlpha(); + return mState.mDrawable.getAlpha(); } @Override public void setColorFilter(ColorFilter cf) { - mClipState.mDrawable.setColorFilter(cf); + mState.mDrawable.setColorFilter(cf); } @Override public void setTintList(ColorStateList tint) { - mClipState.mDrawable.setTintList(tint); + mState.mDrawable.setTintList(tint); } @Override public void setTintMode(Mode tintMode) { - mClipState.mDrawable.setTintMode(tintMode); + mState.mDrawable.setTintMode(tintMode); } @Override public int getOpacity() { - return mClipState.mDrawable.getOpacity(); + return mState.mDrawable.getOpacity(); } @Override public boolean isStateful() { - return mClipState.mDrawable.isStateful(); + return mState.mDrawable.isStateful(); } @Override protected boolean onStateChange(int[] state) { - return mClipState.mDrawable.setState(state); + return mState.mDrawable.setState(state); } @Override protected boolean onLevelChange(int level) { - mClipState.mDrawable.setLevel(level); + mState.mDrawable.setLevel(level); invalidateSelf(); return true; } @Override protected void onBoundsChange(Rect bounds) { - mClipState.mDrawable.setBounds(bounds); + mState.mDrawable.setBounds(bounds); } @Override public void draw(Canvas canvas) { - if (mClipState.mDrawable.getLevel() == 0) { + if (mState.mDrawable.getLevel() == 0) { return; } @@ -222,41 +282,41 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { final Rect bounds = getBounds(); int level = getLevel(); int w = bounds.width(); - final int iw = 0; //mClipState.mDrawable.getIntrinsicWidth(); - if ((mClipState.mOrientation & HORIZONTAL) != 0) { + final int iw = 0; //mState.mDrawable.getIntrinsicWidth(); + if ((mState.mOrientation & HORIZONTAL) != 0) { w -= (w - iw) * (10000 - level) / 10000; } int h = bounds.height(); - final int ih = 0; //mClipState.mDrawable.getIntrinsicHeight(); - if ((mClipState.mOrientation & VERTICAL) != 0) { + final int ih = 0; //mState.mDrawable.getIntrinsicHeight(); + if ((mState.mOrientation & VERTICAL) != 0) { h -= (h - ih) * (10000 - level) / 10000; } final int layoutDirection = getLayoutDirection(); - Gravity.apply(mClipState.mGravity, w, h, bounds, r, layoutDirection); + Gravity.apply(mState.mGravity, w, h, bounds, r, layoutDirection); if (w > 0 && h > 0) { canvas.save(); canvas.clipRect(r); - mClipState.mDrawable.draw(canvas); + mState.mDrawable.draw(canvas); canvas.restore(); } } @Override public int getIntrinsicWidth() { - return mClipState.mDrawable.getIntrinsicWidth(); + return mState.mDrawable.getIntrinsicWidth(); } @Override public int getIntrinsicHeight() { - return mClipState.mDrawable.getIntrinsicHeight(); + return mState.mDrawable.getIntrinsicHeight(); } @Override public ConstantState getConstantState() { - if (mClipState.canConstantState()) { - mClipState.mChangingConfigurations = getChangingConfigurations(); - return mClipState; + if (mState.canConstantState()) { + mState.mChangingConfigurations = getChangingConfigurations(); + return mState; } return null; } @@ -264,21 +324,44 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { /** @hide */ @Override public void setLayoutDirection(int layoutDirection) { - mClipState.mDrawable.setLayoutDirection(layoutDirection); + mState.mDrawable.setLayoutDirection(layoutDirection); super.setLayoutDirection(layoutDirection); } + @Override + public Drawable mutate() { + if (!mMutated && super.mutate() == this) { + mState.mDrawable.mutate(); + mMutated = true; + } + return this; + } + + /** + * @hide + */ + public void clearMutated() { + super.clearMutated(); + mState.mDrawable.clearMutated(); + mMutated = false; + } + final static class ClipState extends ConstantState { - Drawable mDrawable; + int[] mThemeAttrs; int mChangingConfigurations; - int mOrientation; - int mGravity; + + Drawable mDrawable; + + int mOrientation = HORIZONTAL; + int mGravity = Gravity.LEFT; private boolean mCheckedConstantState; private boolean mCanConstantState; ClipState(ClipState orig, ClipDrawable owner, Resources res) { if (orig != null) { + mThemeAttrs = orig.mThemeAttrs; + mChangingConfigurations = orig.mChangingConfigurations; if (res != null) { mDrawable = orig.mDrawable.getConstantState().newDrawable(res); } else { @@ -295,6 +378,12 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { } @Override + public boolean canApplyTheme() { + return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme()) + || super.canApplyTheme(); + } + + @Override public Drawable newDrawable() { return new ClipDrawable(this, null); } @@ -320,7 +409,7 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { } private ClipDrawable(ClipState state, Resources res) { - mClipState = new ClipState(state, this, res); + mState = new ClipState(state, this, res); } } diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java index 1253c46307bb..0f0c844f81cc 100644 --- a/graphics/java/android/graphics/drawable/ColorDrawable.java +++ b/graphics/java/android/graphics/drawable/ColorDrawable.java @@ -88,6 +88,14 @@ public class ColorDrawable extends Drawable { return this; } + /** + * @hide + */ + public void clearMutated() { + super.clearMutated(); + mMutated = false; + } + @Override public void draw(Canvas canvas) { final ColorFilter colorFilter = mPaint.getColorFilter(); @@ -291,17 +299,12 @@ public class ColorDrawable extends Drawable { @Override public Drawable newDrawable() { - return new ColorDrawable(this, null, null); + return new ColorDrawable(this); } @Override public Drawable newDrawable(Resources res) { - return new ColorDrawable(this, res, null); - } - - @Override - public Drawable newDrawable(Resources res, Theme theme) { - return new ColorDrawable(this, res, theme); + return new ColorDrawable(this); } @Override @@ -310,14 +313,8 @@ public class ColorDrawable extends Drawable { } } - private ColorDrawable(ColorState state, Resources res, Theme theme) { - if (theme != null && state.canApplyTheme()) { - mColorState = new ColorState(state); - applyTheme(theme); - } else { - mColorState = state; - } - + private ColorDrawable(ColorState state) { + mColorState = state; mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); } } diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index 9ae788cf6c90..1fac5b6bd986 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -917,6 +917,20 @@ public abstract class Drawable { } /** + * Clears the mutated state, allowing this drawable to be cached and + * mutated again. + * <p> + * This is hidden because only framework drawables can be cached, so + * custom drawables don't need to support constant state, mutate(), or + * clearMutated(). + * + * @hide + */ + public void clearMutated() { + // Default implementation is no-op. + } + + /** * Create a drawable from an inputstream */ public static Drawable createFromStream(InputStream is, String srcName) { @@ -1044,54 +1058,72 @@ public abstract class Drawable { final Drawable drawable; final String name = parser.getName(); - if (name.equals("selector")) { - drawable = new StateListDrawable(); - } else if (name.equals("animated-selector")) { - drawable = new AnimatedStateListDrawable(); - } else if (name.equals("level-list")) { - drawable = new LevelListDrawable(); - } else if (name.equals("layer-list")) { - drawable = new LayerDrawable(); - } else if (name.equals("transition")) { - drawable = new TransitionDrawable(); - } else if (name.equals("ripple")) { - drawable = new RippleDrawable(); - } else if (name.equals("color")) { - drawable = new ColorDrawable(); - } else if (name.equals("shape")) { - drawable = new GradientDrawable(); - } else if (name.equals("vector")) { - drawable = new VectorDrawable(); - } else if (name.equals("animated-vector")) { - drawable = new AnimatedVectorDrawable(); - } else if (name.equals("scale")) { - drawable = new ScaleDrawable(); - } else if (name.equals("clip")) { - drawable = new ClipDrawable(); - } else if (name.equals("rotate")) { - drawable = new RotateDrawable(); - } else if (name.equals("animated-rotate")) { - drawable = new AnimatedRotateDrawable(); - } else if (name.equals("animation-list")) { - drawable = new AnimationDrawable(); - } else if (name.equals("inset")) { - drawable = new InsetDrawable(); - } else if (name.equals("bitmap")) { - //noinspection deprecation - drawable = new BitmapDrawable(r); - if (r != null) { - ((BitmapDrawable) drawable).setTargetDensity(r.getDisplayMetrics()); - } - } else if (name.equals("nine-patch")) { - drawable = new NinePatchDrawable(); - if (r != null) { - ((NinePatchDrawable) drawable).setTargetDensity(r.getDisplayMetrics()); - } - } else { - throw new XmlPullParserException(parser.getPositionDescription() + - ": invalid drawable tag " + name); - } + switch (name) { + case "selector": + drawable = new StateListDrawable(); + break; + case "animated-selector": + drawable = new AnimatedStateListDrawable(); + break; + case "level-list": + drawable = new LevelListDrawable(); + break; + case "layer-list": + drawable = new LayerDrawable(); + break; + case "transition": + drawable = new TransitionDrawable(); + break; + case "ripple": + drawable = new RippleDrawable(); + break; + case "color": + drawable = new ColorDrawable(); + break; + case "shape": + drawable = new GradientDrawable(); + break; + case "vector": + drawable = new VectorDrawable(); + break; + case "animated-vector": + drawable = new AnimatedVectorDrawable(); + break; + case "scale": + drawable = new ScaleDrawable(); + break; + case "clip": + drawable = new ClipDrawable(); + break; + case "rotate": + drawable = new RotateDrawable(); + break; + case "animated-rotate": + drawable = new AnimatedRotateDrawable(); + break; + case "animation-list": + drawable = new AnimationDrawable(); + break; + case "inset": + drawable = new InsetDrawable(); + break; + case "bitmap": + drawable = new BitmapDrawable(r); + if (r != null) { + ((BitmapDrawable) drawable).setTargetDensity(r.getDisplayMetrics()); + } + break; + case "nine-patch": + drawable = new NinePatchDrawable(); + if (r != null) { + ((NinePatchDrawable) drawable).setTargetDensity(r.getDisplayMetrics()); + } + break; + default: + throw new XmlPullParserException(parser.getPositionDescription() + + ": invalid drawable tag " + name); + } drawable.inflate(r, parser, attrs, theme); return drawable; } @@ -1202,7 +1234,7 @@ public abstract class Drawable { * implemented for drawables that can have a theme applied. */ public Drawable newDrawable(Resources res, Theme theme) { - return newDrawable(); + return newDrawable(null); } /** diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index 4a719fee4920..326490ff884a 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -574,6 +574,15 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { } /** + * @hide + */ + public void clearMutated() { + super.clearMutated(); + mDrawableContainerState.clearMutated(); + mMutated = false; + } + + /** * A ConstantState that can contain several {@link Drawable}s. * * This class was made public to enable testing, and its visibility may change in a future @@ -583,8 +592,6 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { final DrawableContainer mOwner; final Resources mRes; - Theme mTheme; - SparseArray<ConstantStateFuture> mDrawableFutures; int mChangingConfigurations; @@ -593,11 +600,11 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { Drawable[] mDrawables; int mNumChildren; - boolean mVariablePadding; + boolean mVariablePadding = false; boolean mPaddingChecked; Rect mConstantPadding; - boolean mConstantSize; + boolean mConstantSize = false; boolean mComputedConstantSize; int mConstantWidth; int mConstantHeight; @@ -618,8 +625,8 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { boolean mMutated; int mLayoutDirection; - int mEnterFadeDuration; - int mExitFadeDuration; + int mEnterFadeDuration = 0; + int mExitFadeDuration = 0; boolean mAutoMirrored; @@ -792,17 +799,17 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { } final void applyTheme(Theme theme) { - // No need to call createAllFutures, since future drawables will - // apply the theme when they are prepared. - final int N = mNumChildren; - final Drawable[] drawables = mDrawables; - for (int i = 0; i < N; i++) { - if (drawables[i] != null) { - drawables[i].applyTheme(theme); + if (theme != null) { + createAllFutures(); + + final int N = mNumChildren; + final Drawable[] drawables = mDrawables; + for (int i = 0; i < N; i++) { + if (drawables[i] != null && drawables[i].canApplyTheme()) { + drawables[i].applyTheme(theme); + } } } - - mTheme = theme; } @Override @@ -840,6 +847,18 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { mMutated = true; } + final void clearMutated() { + final int N = mNumChildren; + final Drawable[] drawables = mDrawables; + for (int i = 0; i < N; i++) { + if (drawables[i] != null) { + drawables[i].clearMutated(); + } + } + + mMutated = false; + } + /** * A boolean value indicating whether to use the maximum padding value * of all frames in the set (false), or to use the padding value of the @@ -1047,10 +1066,8 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { final Drawable result; if (state.mRes == null) { result = mConstantState.newDrawable(); - } else if (state.mTheme == null) { - result = mConstantState.newDrawable(state.mRes); } else { - result = mConstantState.newDrawable(state.mRes, state.mTheme); + result = mConstantState.newDrawable(state.mRes); } result.setLayoutDirection(state.mLayoutDirection); result.setCallback(state.mOwner); diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index cd6297b5284f..14582385e9b5 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -29,6 +29,8 @@ import android.graphics.Outline; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.RadialGradient; import android.graphics.Rect; import android.graphics.RectF; @@ -134,6 +136,7 @@ public class GradientDrawable extends Drawable { private Rect mPadding; private Paint mStrokePaint; // optional, set by the caller private ColorFilter mColorFilter; // optional, set by the caller + private PorterDuffColorFilter mTintFilter; private int mAlpha = 0xFF; // modified by the caller private final Path mPath = new Path(); @@ -171,7 +174,7 @@ public class GradientDrawable extends Drawable { } public GradientDrawable() { - this(new GradientState(Orientation.TOP_BOTTOM, null), null); + this(new GradientState(Orientation.TOP_BOTTOM, null)); } /** @@ -179,7 +182,7 @@ public class GradientDrawable extends Drawable { * of colors for the gradient. */ public GradientDrawable(Orientation orientation, int[] colors) { - this(new GradientState(orientation, colors), null); + this(new GradientState(orientation, colors)); } @Override @@ -523,13 +526,15 @@ public class GradientDrawable extends Drawable { mStrokePaint.getStrokeWidth() > 0; final boolean haveFill = currFillAlpha > 0; final GradientState st = mGradientState; + final ColorFilter colorFilter = mColorFilter != null ? mColorFilter : mTintFilter; + /* we need a layer iff we're drawing both a fill and stroke, and the stroke is non-opaque, and our shapetype actually supports fill+stroke. Otherwise we can just draw the stroke (if any) on top of the fill (if any) without worrying about blending artifacts. */ - final boolean useLayer = haveStroke && haveFill && st.mShape != LINE && - currStrokeAlpha < 255 && (mAlpha < 255 || mColorFilter != null); + final boolean useLayer = haveStroke && haveFill && st.mShape != LINE && + currStrokeAlpha < 255 && (mAlpha < 255 || colorFilter != null); /* Drawing with a layer is slower than direct drawing, but it allows us to apply paint effects like alpha and colorfilter to @@ -544,7 +549,7 @@ public class GradientDrawable extends Drawable { } mLayerPaint.setDither(st.mDither); mLayerPaint.setAlpha(mAlpha); - mLayerPaint.setColorFilter(mColorFilter); + mLayerPaint.setColorFilter(colorFilter); float rad = mStrokePaint.getStrokeWidth(); canvas.saveLayer(mRect.left - rad, mRect.top - rad, @@ -561,14 +566,14 @@ public class GradientDrawable extends Drawable { */ mFillPaint.setAlpha(currFillAlpha); mFillPaint.setDither(st.mDither); - mFillPaint.setColorFilter(mColorFilter); - if (mColorFilter != null && st.mColorStateList == null) { + mFillPaint.setColorFilter(colorFilter); + if (colorFilter != null && st.mColorStateList == null) { mFillPaint.setColor(mAlpha << 24); } if (haveStroke) { mStrokePaint.setAlpha(currStrokeAlpha); mStrokePaint.setDither(st.mDither); - mStrokePaint.setColorFilter(mColorFilter); + mStrokePaint.setColorFilter(colorFilter); } } @@ -593,7 +598,7 @@ public class GradientDrawable extends Drawable { canvas.drawRoundRect(mRect, rad, rad, mStrokePaint); } } else { - if (mFillPaint.getColor() != 0 || mColorFilter != null || + if (mFillPaint.getColor() != 0 || colorFilter != null || mFillPaint.getShader() != null) { canvas.drawRect(mRect, mFillPaint); } @@ -768,6 +773,11 @@ public class GradientDrawable extends Drawable { } } + if (s.mTint != null && s.mTintMode != null) { + mTintFilter = updateTintFilter(mTintFilter, s.mTint, s.mTintMode); + invalidateSelf = true; + } + if (invalidateSelf) { invalidateSelf(); return true; @@ -781,7 +791,8 @@ public class GradientDrawable extends Drawable { final GradientState s = mGradientState; return super.isStateful() || (s.mColorStateList != null && s.mColorStateList.isStateful()) - || (s.mStrokeColorStateList != null && s.mStrokeColorStateList.isStateful()); + || (s.mStrokeColorStateList != null && s.mStrokeColorStateList.isStateful()) + || (s.mTint != null && s.mTint.isStateful()); } @Override @@ -824,6 +835,20 @@ public class GradientDrawable extends Drawable { } @Override + public void setTintList(ColorStateList tint) { + mGradientState.mTint = tint; + mTintFilter = updateTintFilter(mTintFilter, tint, mGradientState.mTintMode); + invalidateSelf(); + } + + @Override + public void setTintMode(PorterDuff.Mode tintMode) { + mGradientState.mTintMode = tintMode; + mTintFilter = updateTintFilter(mTintFilter, mGradientState.mTint, tintMode); + invalidateSelf(); + } + + @Override public int getOpacity() { return (mAlpha == 255 && mGradientState.mOpaqueOverBounds && isOpaqueForState()) ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT; @@ -997,13 +1022,16 @@ public class GradientDrawable extends Drawable { super.applyTheme(t); final GradientState state = mGradientState; - if (state == null || state.mThemeAttrs == null) { + if (state == null) { return; } - final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.GradientDrawable); - updateStateFromTypedArray(a); - a.recycle(); + if (state.mThemeAttrs != null) { + final TypedArray a = t.resolveAttributes( + state.mThemeAttrs, R.styleable.GradientDrawable); + updateStateFromTypedArray(a); + a.recycle(); + } applyThemeChildElements(t); @@ -1045,15 +1073,23 @@ public class GradientDrawable extends Drawable { state.mUseLevelForShape = a.getBoolean( R.styleable.GradientDrawable_useLevel, state.mUseLevelForShape); } + + final int tintMode = a.getInt(R.styleable.GradientDrawable_tintMode, -1); + if (tintMode != -1) { + state.mTintMode = Drawable.parseTintMode(tintMode, PorterDuff.Mode.SRC_IN); + } + + final ColorStateList tint = a.getColorStateList(R.styleable.GradientDrawable_tint); + if (tint != null) { + state.mTint = tint; + } + + mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); } @Override public boolean canApplyTheme() { - final GradientState st = mGradientState; - return st != null && (st.mThemeAttrs != null || st.mAttrSize != null - || st.mAttrGradient != null || st.mAttrSolid != null - || st.mAttrStroke != null || st.mAttrCorners != null - || st.mAttrPadding != null); + return (mGradientState != null && mGradientState.canApplyTheme()) || super.canApplyTheme(); } private void applyThemeChildElements(Theme t) { @@ -1359,9 +1395,12 @@ public class GradientDrawable extends Drawable { } else { radiusType = RADIUS_TYPE_FRACTION; } - } else { + } else if (tv.type == TypedValue.TYPE_DIMENSION) { radius = tv.getDimension(r.getDisplayMetrics()); radiusType = RADIUS_TYPE_PIXELS; + } else { + radius = tv.getFloat(); + radiusType = RADIUS_TYPE_PIXELS; } st.mGradientRadius = radius; @@ -1479,6 +1518,14 @@ public class GradientDrawable extends Drawable { return this; } + /** + * @hide + */ + public void clearMutated() { + super.clearMutated(); + mMutated = false; + } + final static class GradientState extends ConstantState { public int mChangingConfigurations; public int mShape = RECTANGLE; @@ -1505,14 +1552,18 @@ public class GradientDrawable extends Drawable { public int mThickness = -1; public boolean mDither = false; - private float mCenterX = 0.5f; - private float mCenterY = 0.5f; - private float mGradientRadius = 0.5f; - private int mGradientRadiusType = RADIUS_TYPE_PIXELS; - private boolean mUseLevel; - private boolean mUseLevelForShape; - private boolean mOpaqueOverBounds; - private boolean mOpaqueOverShape; + float mCenterX = 0.5f; + float mCenterY = 0.5f; + float mGradientRadius = 0.5f; + int mGradientRadiusType = RADIUS_TYPE_PIXELS; + boolean mUseLevel = false; + boolean mUseLevelForShape = true; + + boolean mOpaqueOverBounds; + boolean mOpaqueOverShape; + + ColorStateList mTint = null; + PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE; int[] mThemeAttrs; int[] mAttrSize; @@ -1566,6 +1617,8 @@ public class GradientDrawable extends Drawable { mUseLevelForShape = state.mUseLevelForShape; mOpaqueOverBounds = state.mOpaqueOverBounds; mOpaqueOverShape = state.mOpaqueOverShape; + mTint = state.mTint; + mTintMode = state.mTintMode; mThemeAttrs = state.mThemeAttrs; mAttrSize = state.mAttrSize; mAttrGradient = state.mAttrGradient; @@ -1577,22 +1630,19 @@ public class GradientDrawable extends Drawable { @Override public boolean canApplyTheme() { - return mThemeAttrs != null; + return mThemeAttrs != null || mAttrSize != null || mAttrGradient != null + || mAttrSolid != null || mAttrStroke != null || mAttrCorners != null + || mAttrPadding != null || super.canApplyTheme(); } @Override public Drawable newDrawable() { - return new GradientDrawable(this, null); + return new GradientDrawable(this); } @Override public Drawable newDrawable(Resources res) { - return new GradientDrawable(this, null); - } - - @Override - public Drawable newDrawable(Resources res, Theme theme) { - return new GradientDrawable(this, theme); + return new GradientDrawable(this); } @Override @@ -1696,18 +1746,11 @@ public class GradientDrawable extends Drawable { * The resulting drawable is guaranteed to have a new constant state. * * @param state Constant state from which the drawable inherits - * @param theme Theme to apply to the drawable */ - private GradientDrawable(GradientState state, Theme theme) { - if (theme != null && state.canApplyTheme()) { - // If we need to apply a theme, implicitly mutate. - mGradientState = new GradientState(state); - applyTheme(theme); - } else { - mGradientState = state; - } + private GradientDrawable(GradientState state) { + mGradientState = state; - initializeWithState(state); + initializeWithState(mGradientState); mGradientIsDirty = true; mMutated = false; diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java index 961d160798c6..b88d9e67b069 100644 --- a/graphics/java/android/graphics/drawable/InsetDrawable.java +++ b/graphics/java/android/graphics/drawable/InsetDrawable.java @@ -55,7 +55,8 @@ import java.io.IOException; public class InsetDrawable extends Drawable implements Drawable.Callback { private final Rect mTmpRect = new Rect(); - private InsetState mInsetState; + private final InsetState mState; + private boolean mMutated; /*package*/ InsetDrawable() { @@ -70,11 +71,11 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { int insetRight, int insetBottom) { this(null, null); - mInsetState.mDrawable = drawable; - mInsetState.mInsetLeft = insetLeft; - mInsetState.mInsetTop = insetTop; - mInsetState.mInsetRight = insetRight; - mInsetState.mInsetBottom = insetBottom; + mState.mDrawable = drawable; + mState.mInsetLeft = insetLeft; + mState.mInsetTop = insetTop; + mState.mInsetRight = insetRight; + mState.mInsetBottom = insetBottom; if (drawable != null) { drawable.setCallback(this); @@ -87,11 +88,20 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.InsetDrawable); super.inflateWithAttributes(r, parser, a, R.styleable.InsetDrawable_visible); - mInsetState.mDrawable = null; + // Reset mDrawable to preserve old multiple-inflate behavior. This is + // silly, but we have CTS tests that rely on it. + mState.mDrawable = null; + updateStateFromTypedArray(a); + inflateChildElements(r, parser, attrs, theme); + verifyRequiredAttributes(a); + a.recycle(); + } + private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs, + Theme theme) throws XmlPullParserException, IOException { // Load inner XML elements. - if (mInsetState.mDrawable == null) { + if (mState.mDrawable == null) { int type; while ((type=parser.next()) == XmlPullParser.TEXT) { } @@ -102,26 +112,23 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { + "child tag defining a drawable"); } final Drawable dr = Drawable.createFromXmlInner(r, parser, attrs, theme); - mInsetState.mDrawable = dr; + mState.mDrawable = dr; dr.setCallback(this); } - - verifyRequiredAttributes(a); - a.recycle(); } private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException { // If we're not waiting on a theme, verify required attributes. - if (mInsetState.mDrawable == null && (mInsetState.mThemeAttrs == null - || mInsetState.mThemeAttrs[R.styleable.InsetDrawable_drawable] == 0)) { - throw new XmlPullParserException(a.getPositionDescription() + - ": <inset> tag requires a 'drawable' attribute or " + if (mState.mDrawable == null && (mState.mThemeAttrs == null + || mState.mThemeAttrs[R.styleable.InsetDrawable_drawable] == 0)) { + throw new XmlPullParserException(a.getPositionDescription() + + ": <inset> tag requires a 'drawable' attribute or " + "child tag defining a drawable"); } } private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException { - final InsetState state = mInsetState; + final InsetState state = mState; // Account for any configuration changes. state.mChangingConfigurations |= a.getChangingConfigurations(); @@ -169,25 +176,31 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { public void applyTheme(Theme t) { super.applyTheme(t); - final InsetState state = mInsetState; - if (state == null || state.mThemeAttrs == null) { + final InsetState state = mState; + if (state == null) { return; } - final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.InsetDrawable); - try { - updateStateFromTypedArray(a); - verifyRequiredAttributes(a); - } catch (XmlPullParserException e) { - throw new RuntimeException(e); - } finally { - a.recycle(); + if (state.mThemeAttrs != null) { + final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.InsetDrawable); + try { + updateStateFromTypedArray(a); + verifyRequiredAttributes(a); + } catch (XmlPullParserException e) { + throw new RuntimeException(e); + } finally { + a.recycle(); + } + } + + if (state.mDrawable != null && state.mDrawable.canApplyTheme()) { + state.mDrawable.applyTheme(t); } } @Override public boolean canApplyTheme() { - return mInsetState != null && mInsetState.mThemeAttrs != null; + return (mState != null && mState.canApplyTheme()) || super.canApplyTheme(); } @Override @@ -216,112 +229,112 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { @Override public void draw(Canvas canvas) { - mInsetState.mDrawable.draw(canvas); + mState.mDrawable.draw(canvas); } @Override public int getChangingConfigurations() { return super.getChangingConfigurations() - | mInsetState.mChangingConfigurations - | mInsetState.mDrawable.getChangingConfigurations(); + | mState.mChangingConfigurations + | mState.mDrawable.getChangingConfigurations(); } @Override public boolean getPadding(Rect padding) { - boolean pad = mInsetState.mDrawable.getPadding(padding); + boolean pad = mState.mDrawable.getPadding(padding); - padding.left += mInsetState.mInsetLeft; - padding.right += mInsetState.mInsetRight; - padding.top += mInsetState.mInsetTop; - padding.bottom += mInsetState.mInsetBottom; + padding.left += mState.mInsetLeft; + padding.right += mState.mInsetRight; + padding.top += mState.mInsetTop; + padding.bottom += mState.mInsetBottom; - return pad || (mInsetState.mInsetLeft | mInsetState.mInsetRight | - mInsetState.mInsetTop | mInsetState.mInsetBottom) != 0; + return pad || (mState.mInsetLeft | mState.mInsetRight | + mState.mInsetTop | mState.mInsetBottom) != 0; } /** @hide */ @Override public Insets getOpticalInsets() { final Insets contentInsets = super.getOpticalInsets(); - return Insets.of(contentInsets.left + mInsetState.mInsetLeft, - contentInsets.top + mInsetState.mInsetTop, - contentInsets.right + mInsetState.mInsetRight, - contentInsets.bottom + mInsetState.mInsetBottom); + return Insets.of(contentInsets.left + mState.mInsetLeft, + contentInsets.top + mState.mInsetTop, + contentInsets.right + mState.mInsetRight, + contentInsets.bottom + mState.mInsetBottom); } @Override public void setHotspot(float x, float y) { - mInsetState.mDrawable.setHotspot(x, y); + mState.mDrawable.setHotspot(x, y); } @Override public void setHotspotBounds(int left, int top, int right, int bottom) { - mInsetState.mDrawable.setHotspotBounds(left, top, right, bottom); + mState.mDrawable.setHotspotBounds(left, top, right, bottom); } /** @hide */ @Override public void getHotspotBounds(Rect outRect) { - mInsetState.mDrawable.getHotspotBounds(outRect); + mState.mDrawable.getHotspotBounds(outRect); } @Override public boolean setVisible(boolean visible, boolean restart) { - mInsetState.mDrawable.setVisible(visible, restart); + mState.mDrawable.setVisible(visible, restart); return super.setVisible(visible, restart); } @Override public void setAlpha(int alpha) { - mInsetState.mDrawable.setAlpha(alpha); + mState.mDrawable.setAlpha(alpha); } @Override public int getAlpha() { - return mInsetState.mDrawable.getAlpha(); + return mState.mDrawable.getAlpha(); } @Override public void setColorFilter(ColorFilter cf) { - mInsetState.mDrawable.setColorFilter(cf); + mState.mDrawable.setColorFilter(cf); } @Override public void setTintList(ColorStateList tint) { - mInsetState.mDrawable.setTintList(tint); + mState.mDrawable.setTintList(tint); } @Override public void setTintMode(Mode tintMode) { - mInsetState.mDrawable.setTintMode(tintMode); + mState.mDrawable.setTintMode(tintMode); } /** {@hide} */ @Override public void setLayoutDirection(int layoutDirection) { - mInsetState.mDrawable.setLayoutDirection(layoutDirection); + mState.mDrawable.setLayoutDirection(layoutDirection); } @Override public int getOpacity() { - return mInsetState.mDrawable.getOpacity(); + return mState.mDrawable.getOpacity(); } @Override public boolean isStateful() { - return mInsetState.mDrawable.isStateful(); + return mState.mDrawable.isStateful(); } @Override protected boolean onStateChange(int[] state) { - boolean changed = mInsetState.mDrawable.setState(state); + boolean changed = mState.mDrawable.setState(state); onBoundsChange(getBounds()); return changed; } @Override protected boolean onLevelChange(int level) { - return mInsetState.mDrawable.setLevel(level); + return mState.mDrawable.setLevel(level); } @Override @@ -329,34 +342,36 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { final Rect r = mTmpRect; r.set(bounds); - r.left += mInsetState.mInsetLeft; - r.top += mInsetState.mInsetTop; - r.right -= mInsetState.mInsetRight; - r.bottom -= mInsetState.mInsetBottom; + r.left += mState.mInsetLeft; + r.top += mState.mInsetTop; + r.right -= mState.mInsetRight; + r.bottom -= mState.mInsetBottom; - mInsetState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom); + mState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom); } @Override public int getIntrinsicWidth() { - return mInsetState.mDrawable.getIntrinsicWidth(); + return mState.mDrawable.getIntrinsicWidth() + + mState.mInsetLeft + mState.mInsetRight; } @Override public int getIntrinsicHeight() { - return mInsetState.mDrawable.getIntrinsicHeight(); + return mState.mDrawable.getIntrinsicHeight() + + mState.mInsetTop + mState.mInsetBottom; } @Override public void getOutline(@NonNull Outline outline) { - mInsetState.mDrawable.getOutline(outline); + mState.mDrawable.getOutline(outline); } @Override public ConstantState getConstantState() { - if (mInsetState.canConstantState()) { - mInsetState.mChangingConfigurations = getChangingConfigurations(); - return mInsetState; + if (mState.canConstantState()) { + mState.mChangingConfigurations = getChangingConfigurations(); + return mState; } return null; } @@ -364,17 +379,26 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { @Override public Drawable mutate() { if (!mMutated && super.mutate() == this) { - mInsetState.mDrawable.mutate(); + mState.mDrawable.mutate(); mMutated = true; } return this; } /** + * @hide + */ + public void clearMutated() { + super.clearMutated(); + mState.mDrawable.clearMutated(); + mMutated = false; + } + + /** * Returns the drawable wrapped by this InsetDrawable. May be null. */ public Drawable getDrawable() { - return mInsetState.mDrawable; + return mState.mDrawable; } final static class InsetState extends ConstantState { @@ -383,13 +407,13 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { Drawable mDrawable; - int mInsetLeft; - int mInsetTop; - int mInsetRight; - int mInsetBottom; + int mInsetLeft = 0; + int mInsetTop = 0; + int mInsetRight = 0; + int mInsetBottom = 0; - boolean mCheckedConstantState; - boolean mCanConstantState; + private boolean mCheckedConstantState; + private boolean mCanConstantState; InsetState(InsetState orig, InsetDrawable owner, Resources res) { if (orig != null) { @@ -413,6 +437,12 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { } @Override + public boolean canApplyTheme() { + return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme()) + || super.canApplyTheme(); + } + + @Override public Drawable newDrawable() { return new InsetDrawable(this, null); } @@ -438,7 +468,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { } private InsetDrawable(InsetState state, Resources res) { - mInsetState = new InsetState(state, this, res); + mState = new InsetState(state, this, res); } } diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java index 001ed8860761..689d225fad30 100644 --- a/graphics/java/android/graphics/drawable/LayerDrawable.java +++ b/graphics/java/android/graphics/drawable/LayerDrawable.java @@ -100,10 +100,10 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { * @param state The constant drawable state. */ LayerDrawable(Drawable[] layers, LayerState state) { - this(state, null, null); - int length = layers.length; - ChildDrawable[] r = new ChildDrawable[length]; + this(state, null); + final int length = layers.length; + final ChildDrawable[] r = new ChildDrawable[length]; for (int i = 0; i < length; i++) { r[i] = new ChildDrawable(); r[i].mDrawable = layers[i]; @@ -117,18 +117,14 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { } LayerDrawable() { - this((LayerState) null, null, null); + this((LayerState) null, null); } - LayerDrawable(LayerState state, Resources res, Theme theme) { - final LayerState as = createConstantState(state, res); - mLayerState = as; - if (as.mNum > 0) { + LayerDrawable(LayerState state, Resources res) { + mLayerState = createConstantState(state, res); + if (mLayerState.mNum > 0) { ensurePadding(); } - if (theme != null && canApplyTheme()) { - applyTheme(theme); - } } LayerState createConstantState(LayerState state, Resources res) { @@ -256,8 +252,8 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { a.recycle(); } - final ChildDrawable[] array = mLayerState.mChildren; - final int N = mLayerState.mNum; + final ChildDrawable[] array = state.mChildren; + final int N = state.mNum; for (int i = 0; i < N; i++) { final ChildDrawable layer = array[i]; if (layer.mThemeAttrs != null) { @@ -279,25 +275,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { @Override public boolean canApplyTheme() { - final LayerState state = mLayerState; - if (state == null) { - return false; - } - - if (state.mThemeAttrs != null) { - return true; - } - - final ChildDrawable[] array = state.mChildren; - final int N = state.mNum; - for (int i = 0; i < N; i++) { - final ChildDrawable layer = array[i]; - if (layer.mThemeAttrs != null || layer.mDrawable.canApplyTheme()) { - return true; - } - } - - return false; + return (mLayerState != null && mLayerState.canApplyTheme()) || super.canApplyTheme(); } /** @@ -940,6 +918,19 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { return this; } + /** + * @hide + */ + public void clearMutated() { + super.clearMutated(); + final ChildDrawable[] array = mLayerState.mChildren; + final int N = mLayerState.mNum; + for (int i = 0; i < N; i++) { + array[i].mDrawable.clearMutated(); + } + mMutated = false; + } + /** @hide */ @Override public void setLayoutDirection(int layoutDirection) { @@ -1029,22 +1020,30 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { @Override public boolean canApplyTheme() { - return mThemeAttrs != null; + if (mThemeAttrs != null || super.canApplyTheme()) { + return true; + } + + final ChildDrawable[] array = mChildren; + final int N = mNum; + for (int i = 0; i < N; i++) { + final ChildDrawable layer = array[i]; + if (layer.mThemeAttrs != null || layer.mDrawable.canApplyTheme()) { + return true; + } + } + + return false; } @Override public Drawable newDrawable() { - return new LayerDrawable(this, null, null); + return new LayerDrawable(this, null); } @Override public Drawable newDrawable(Resources res) { - return new LayerDrawable(this, res, null); - } - - @Override - public Drawable newDrawable(Resources res, Theme theme) { - return new LayerDrawable(this, res, theme); + return new LayerDrawable(this, res); } @Override diff --git a/graphics/java/android/graphics/drawable/LevelListDrawable.java b/graphics/java/android/graphics/drawable/LevelListDrawable.java index bc1c61df403a..9e918f6bccda 100644 --- a/graphics/java/android/graphics/drawable/LevelListDrawable.java +++ b/graphics/java/android/graphics/drawable/LevelListDrawable.java @@ -153,6 +153,14 @@ public class LevelListDrawable extends DrawableContainer { return this; } + /** + * @hide + */ + public void clearMutated() { + super.clearMutated(); + mMutated = false; + } + private final static class LevelListState extends DrawableContainerState { private int[] mLows; private int[] mHighs; diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java index 6c62ccf59b7e..d821224a2518 100644 --- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java +++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java @@ -90,7 +90,7 @@ public class NinePatchDrawable extends Drawable { */ @Deprecated public NinePatchDrawable(Bitmap bitmap, byte[] chunk, Rect padding, String srcName) { - this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding), null, null); + this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding), null); } /** @@ -99,7 +99,7 @@ public class NinePatchDrawable extends Drawable { */ public NinePatchDrawable(Resources res, Bitmap bitmap, byte[] chunk, Rect padding, String srcName) { - this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding), res, null); + this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding), res); mNinePatchState.mTargetDensity = mTargetDensity; } @@ -112,7 +112,7 @@ public class NinePatchDrawable extends Drawable { public NinePatchDrawable(Resources res, Bitmap bitmap, byte[] chunk, Rect padding, Rect opticalInsets, String srcName) { this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding, opticalInsets), - res, null); + res); mNinePatchState.mTargetDensity = mTargetDensity; } @@ -123,7 +123,7 @@ public class NinePatchDrawable extends Drawable { */ @Deprecated public NinePatchDrawable(NinePatch patch) { - this(new NinePatchState(patch, new Rect()), null, null); + this(new NinePatchState(patch, new Rect()), null); } /** @@ -131,7 +131,7 @@ public class NinePatchDrawable extends Drawable { * based on the display metrics of the resources. */ public NinePatchDrawable(Resources res, NinePatch patch) { - this(new NinePatchState(patch, new Rect()), res, null); + this(new NinePatchState(patch, new Rect()), res); mNinePatchState.mTargetDensity = mTargetDensity; } @@ -563,6 +563,14 @@ public class NinePatchDrawable extends Drawable { return this; } + /** + * @hide + */ + public void clearMutated() { + super.clearMutated(); + mMutated = false; + } + @Override protected boolean onStateChange(int[] stateSet) { final NinePatchState state = mNinePatchState; @@ -646,17 +654,12 @@ public class NinePatchDrawable extends Drawable { @Override public Drawable newDrawable() { - return new NinePatchDrawable(this, null, null); + return new NinePatchDrawable(this, null); } @Override public Drawable newDrawable(Resources res) { - return new NinePatchDrawable(this, res, null); - } - - @Override - public Drawable newDrawable(Resources res, Theme theme) { - return new NinePatchDrawable(this, res, theme); + return new NinePatchDrawable(this, res); } @Override @@ -669,16 +672,10 @@ public class NinePatchDrawable extends Drawable { * The one constructor to rule them all. This is called by all public * constructors to set the state and initialize local properties. */ - private NinePatchDrawable(NinePatchState state, Resources res, Theme theme) { - if (theme != null && state.canApplyTheme()) { - // If we need to apply a theme, implicitly mutate. - mNinePatchState = new NinePatchState(state); - applyTheme(theme); - } else { - mNinePatchState = state; - } + private NinePatchDrawable(NinePatchState state, Resources res) { + mNinePatchState = state; - initializeWithState(state, res); + initializeWithState(mNinePatchState, res); } /** diff --git a/graphics/java/android/graphics/drawable/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java index faa89bfa0e80..21d865f1420e 100644 --- a/graphics/java/android/graphics/drawable/RippleBackground.java +++ b/graphics/java/android/graphics/drawable/RippleBackground.java @@ -43,10 +43,12 @@ class RippleBackground { private static final float WAVE_OPACITY_DECAY_VELOCITY = 3.0f / GLOBAL_SPEED; private static final float WAVE_OUTER_OPACITY_EXIT_VELOCITY_MAX = 4.5f * GLOBAL_SPEED; private static final float WAVE_OUTER_OPACITY_EXIT_VELOCITY_MIN = 1.5f * GLOBAL_SPEED; - private static final float WAVE_OUTER_OPACITY_ENTER_VELOCITY = 10.0f * GLOBAL_SPEED; private static final float WAVE_OUTER_SIZE_INFLUENCE_MAX = 200f; private static final float WAVE_OUTER_SIZE_INFLUENCE_MIN = 40f; + private static final int ENTER_DURATION = 667; + private static final int ENTER_DURATION_FAST = 100; + // Hardware animators. private final ArrayList<RenderNodeAnimator> mRunningAnimations = new ArrayList<RenderNodeAnimator>(); @@ -224,21 +226,20 @@ class RippleBackground { /** * Starts the enter animation. */ - public void enter() { + public void enter(boolean fast) { cancel(); - final int outerDuration = (int) (1000 * 1.0f / WAVE_OUTER_OPACITY_ENTER_VELOCITY); - final ObjectAnimator outer = ObjectAnimator.ofFloat(this, "outerOpacity", 0, 1); - outer.setAutoCancel(true); - outer.setDuration(outerDuration); - outer.setInterpolator(LINEAR_INTERPOLATOR); + final ObjectAnimator opacity = ObjectAnimator.ofFloat(this, "outerOpacity", 0, 1); + opacity.setAutoCancel(true); + opacity.setDuration(fast ? ENTER_DURATION_FAST : ENTER_DURATION); + opacity.setInterpolator(LINEAR_INTERPOLATOR); - mAnimOuterOpacity = outer; + mAnimOuterOpacity = opacity; // Enter animations always run on the UI thread, since it's unlikely // that anything interesting is happening until the user lifts their // finger. - outer.start(); + opacity.start(); } /** diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java index c7aa98ea21aa..e658279ec0dd 100644 --- a/graphics/java/android/graphics/drawable/RippleDrawable.java +++ b/graphics/java/android/graphics/drawable/RippleDrawable.java @@ -167,7 +167,7 @@ public class RippleDrawable extends LayerDrawable { * Constructor used for drawable inflation. */ RippleDrawable() { - this(new RippleState(null, null, null), null, null); + this(new RippleState(null, null, null), null); } /** @@ -180,7 +180,7 @@ public class RippleDrawable extends LayerDrawable { */ public RippleDrawable(@NonNull ColorStateList color, @Nullable Drawable content, @Nullable Drawable mask) { - this(new RippleState(null, null, null), null, null); + this(new RippleState(null, null, null), null); if (color == null) { throw new IllegalArgumentException("RippleDrawable requires a non-null color"); @@ -280,7 +280,7 @@ public class RippleDrawable extends LayerDrawable { } setRippleActive(enabled && pressed); - setBackgroundActive(focused || (enabled && pressed)); + setBackgroundActive(focused || (enabled && pressed), focused); return changed; } @@ -296,11 +296,11 @@ public class RippleDrawable extends LayerDrawable { } } - private void setBackgroundActive(boolean active) { + private void setBackgroundActive(boolean active, boolean focused) { if (mBackgroundActive != active) { mBackgroundActive = active; if (active) { - tryBackgroundEnter(); + tryBackgroundEnter(focused); } else { tryBackgroundExit(); } @@ -333,8 +333,11 @@ public class RippleDrawable extends LayerDrawable { } if (mBackgroundActive) { - tryBackgroundEnter(); + tryBackgroundEnter(false); } + + // Skip animations, just show the correct final states. + jumpToCurrentState(); } return changed; @@ -470,7 +473,7 @@ public class RippleDrawable extends LayerDrawable { @Override public boolean canApplyTheme() { - return super.canApplyTheme() || mState != null && mState.mTouchThemeAttrs != null; + return (mState != null && mState.canApplyTheme()) || super.canApplyTheme(); } @Override @@ -489,14 +492,14 @@ public class RippleDrawable extends LayerDrawable { /** * Creates an active hotspot at the specified location. */ - private void tryBackgroundEnter() { + private void tryBackgroundEnter(boolean focused) { if (mBackground == null) { mBackground = new RippleBackground(this, mHotspotBounds); } final int color = mState.mColor.getColorForState(getState(), Color.TRANSPARENT); mBackground.setup(mState.mMaxRadius, color, mDensity); - mBackground.enter(); + mBackground.enter(focused); } private void tryBackgroundExit() { @@ -715,10 +718,12 @@ public class RippleDrawable extends LayerDrawable { final ChildDrawable[] array = mLayerState.mChildren; final int count = mLayerState.mNum; - // We don't need a layer if we don't expect to draw any ripples, we have - // an explicit mask, or if the non-mask content is all opaque. + // We don't need a layer if we don't expect to draw any ripples or + // a background, we have an explicit mask, or if the non-mask content + // is all opaque. boolean needsLayer = false; - if ((mExitingRipplesCount > 0 || mBackground != null) && mMask == null) { + if ((mExitingRipplesCount > 0 || (mBackground != null && mBackground.shouldDraw())) + && mMask == null) { for (int i = 0; i < count; i++) { if (array[i].mId != R.id.mask && array[i].mDrawable.getOpacity() != PixelFormat.OPAQUE) { @@ -924,17 +929,12 @@ public class RippleDrawable extends LayerDrawable { @Override public Drawable newDrawable() { - return new RippleDrawable(this, null, null); + return new RippleDrawable(this, null); } @Override public Drawable newDrawable(Resources res) { - return new RippleDrawable(this, res, null); - } - - @Override - public Drawable newDrawable(Resources res, Theme theme) { - return new RippleDrawable(this, res, theme); + return new RippleDrawable(this, res); } } @@ -968,37 +968,18 @@ public class RippleDrawable extends LayerDrawable { return mState.mMaxRadius; } - private RippleDrawable(RippleState state, Resources res, Theme theme) { - boolean needsTheme = false; + private RippleDrawable(RippleState state, Resources res) { + mState = new RippleState(state, this, res); + mLayerState = mState; - final RippleState ns; - if (theme != null && state != null && state.canApplyTheme()) { - ns = new RippleState(state, this, res); - needsTheme = true; - } else if (state == null) { - ns = new RippleState(null, this, res); - } else { - // We always need a new state since child drawables contain local - // state but live within the parent's constant state. - // TODO: Move child drawables into local state. - ns = new RippleState(state, this, res); + if (mState.mNum > 0) { + ensurePadding(); } if (res != null) { mDensity = res.getDisplayMetrics().density; } - mState = ns; - mLayerState = ns; - - if (ns.mNum > 0) { - ensurePadding(); - } - - if (needsTheme) { - applyTheme(theme); - } - initializeFromState(); } diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java index 55c96371cb20..3304b335ac45 100644 --- a/graphics/java/android/graphics/drawable/RotateDrawable.java +++ b/graphics/java/android/graphics/drawable/RotateDrawable.java @@ -16,6 +16,8 @@ package android.graphics.drawable; +import com.android.internal.R; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -29,7 +31,6 @@ import android.content.res.TypedArray; import android.content.res.Resources.Theme; import android.util.TypedValue; import android.util.AttributeSet; -import android.util.Log; import java.io.IOException; @@ -312,6 +313,11 @@ public class RotateDrawable extends Drawable implements Drawable.Callback { } @Override + public boolean canApplyTheme() { + return (mState != null && mState.canApplyTheme()) || super.canApplyTheme(); + } + + @Override public void invalidateDrawable(Drawable who) { final Callback callback = getCallback(); if (callback != null) { @@ -399,79 +405,103 @@ public class RotateDrawable extends Drawable implements Drawable.Callback { @Override public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme) throws XmlPullParserException, IOException { - final TypedArray a = obtainAttributes(r, theme, attrs, - com.android.internal.R.styleable.RotateDrawable); - - super.inflateWithAttributes(r, parser, a, - com.android.internal.R.styleable.RotateDrawable_visible); - - TypedValue tv = a.peekValue(com.android.internal.R.styleable.RotateDrawable_pivotX); - final boolean pivotXRel; - final float pivotX; - if (tv == null) { - pivotXRel = true; - pivotX = 0.5f; - } else { - pivotXRel = tv.type == TypedValue.TYPE_FRACTION; - pivotX = pivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); - } + final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.RotateDrawable); + super.inflateWithAttributes(r, parser, a, R.styleable.RotateDrawable_visible); + + // Reset mDrawable to preserve old multiple-inflate behavior. This is + // silly, but we have CTS tests that rely on it. + mState.mDrawable = null; + + updateStateFromTypedArray(a); + inflateChildElements(r, parser, attrs, theme); + verifyRequiredAttributes(a); + a.recycle(); + } + + @Override + public void applyTheme(Theme t) { + super.applyTheme(t); - tv = a.peekValue(com.android.internal.R.styleable.RotateDrawable_pivotY); - final boolean pivotYRel; - final float pivotY; - if (tv == null) { - pivotYRel = true; - pivotY = 0.5f; - } else { - pivotYRel = tv.type == TypedValue.TYPE_FRACTION; - pivotY = pivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); + final RotateState state = mState; + if (state == null) { + return; } - final float fromDegrees = a.getFloat( - com.android.internal.R.styleable.RotateDrawable_fromDegrees, 0.0f); - final float toDegrees = a.getFloat( - com.android.internal.R.styleable.RotateDrawable_toDegrees, 360.0f); + if (state.mThemeAttrs != null) { + final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.RotateDrawable); + try { + updateStateFromTypedArray(a); + verifyRequiredAttributes(a); + } catch (XmlPullParserException e) { + throw new RuntimeException(e); + } finally { + a.recycle(); + } + } - final int res = a.getResourceId( - com.android.internal.R.styleable.RotateDrawable_drawable, 0); - Drawable drawable = null; - if (res > 0) { - drawable = r.getDrawable(res, theme); + if (state.mDrawable != null && state.mDrawable.canApplyTheme()) { + state.mDrawable.applyTheme(t); } - a.recycle(); + } - final int outerDepth = parser.getDepth(); + private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs, + Theme theme) throws XmlPullParserException, IOException { + Drawable dr = null; int type; - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && - (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { - + final int outerDepth = parser.getDepth(); + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { if (type != XmlPullParser.START_TAG) { continue; } + dr = Drawable.createFromXmlInner(r, parser, attrs, theme); + } - if ((drawable = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) { - Log.w("drawable", "Bad element under <rotate>: " - + parser .getName()); - } + if (dr != null) { + mState.mDrawable = dr; + dr.setCallback(this); + } + } + + private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException { + // If we're not waiting on a theme, verify required attributes. + if (mState.mDrawable == null && (mState.mThemeAttrs == null + || mState.mThemeAttrs[R.styleable.ScaleDrawable_drawable] == 0)) { + throw new XmlPullParserException(a.getPositionDescription() + + ": <rotate> tag requires a 'drawable' attribute or " + + "child tag defining a drawable"); } + } + + private void updateStateFromTypedArray(TypedArray a) { + final RotateState state = mState; - if (drawable == null) { - Log.w("drawable", "No drawable specified for <rotate>"); + // Account for any configuration changes. + state.mChangingConfigurations |= a.getChangingConfigurations(); + + // Extract the theme attributes, if any. + state.mThemeAttrs = a.extractThemeAttrs(); + + if (a.hasValue(R.styleable.RotateDrawable_pivotX)) { + final TypedValue tv = a.peekValue(R.styleable.RotateDrawable_pivotX); + state.mPivotXRel = tv.type == TypedValue.TYPE_FRACTION; + state.mPivotX = state.mPivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); } - final RotateState st = mState; - st.mDrawable = drawable; - st.mPivotXRel = pivotXRel; - st.mPivotX = pivotX; - st.mPivotYRel = pivotYRel; - st.mPivotY = pivotY; - st.mFromDegrees = fromDegrees; - st.mCurrentDegrees = fromDegrees; - st.mToDegrees = toDegrees; - - if (drawable != null) { - drawable.setCallback(this); + if (a.hasValue(R.styleable.RotateDrawable_pivotY)) { + final TypedValue tv = a.peekValue(R.styleable.RotateDrawable_pivotY); + state.mPivotYRel = tv.type == TypedValue.TYPE_FRACTION; + state.mPivotY = state.mPivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); + } + + state.mFromDegrees = a.getFloat(R.styleable.RotateDrawable_fromDegrees, state.mFromDegrees); + state.mToDegrees = a.getFloat(R.styleable.RotateDrawable_toDegrees, state.mToDegrees); + + final Drawable dr = a.getDrawable(R.styleable.RotateDrawable_drawable); + if (dr != null) { + state.mDrawable = dr; + dr.setCallback(this); } } @@ -485,30 +515,42 @@ public class RotateDrawable extends Drawable implements Drawable.Callback { } /** + * @hide + */ + public void clearMutated() { + super.clearMutated(); + mState.mDrawable.clearMutated(); + mMutated = false; + } + + /** * Represents the state of a rotation for a given drawable. The same * rotate drawable can be invoked with different states to drive several * rotations at the same time. */ final static class RotateState extends Drawable.ConstantState { - Drawable mDrawable; - + int[] mThemeAttrs; int mChangingConfigurations; - boolean mPivotXRel; - float mPivotX; - boolean mPivotYRel; - float mPivotY; + Drawable mDrawable; - float mFromDegrees; - float mToDegrees; + boolean mPivotXRel = true; + float mPivotX = 0.5f; + boolean mPivotYRel = true; + float mPivotY = 0.5f; - float mCurrentDegrees; + float mFromDegrees = 0.0f; + float mToDegrees = 360.0f; + + float mCurrentDegrees = 0.0f; - private boolean mCanConstantState; private boolean mCheckedConstantState; + private boolean mCanConstantState; - public RotateState(RotateState orig, RotateDrawable owner, Resources res) { + RotateState(RotateState orig, RotateDrawable owner, Resources res) { if (orig != null) { + mThemeAttrs = orig.mThemeAttrs; + mChangingConfigurations = orig.mChangingConfigurations; if (res != null) { mDrawable = orig.mDrawable.getConstantState().newDrawable(res); } else { @@ -522,13 +564,20 @@ public class RotateDrawable extends Drawable implements Drawable.Callback { mPivotX = orig.mPivotX; mPivotYRel = orig.mPivotYRel; mPivotY = orig.mPivotY; - mFromDegrees = mCurrentDegrees = orig.mFromDegrees; + mFromDegrees = orig.mFromDegrees; mToDegrees = orig.mToDegrees; - mCanConstantState = mCheckedConstantState = true; + mCurrentDegrees = orig.mCurrentDegrees; + mCheckedConstantState = mCanConstantState = true; } } @Override + public boolean canApplyTheme() { + return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme()) + || super.canApplyTheme(); + } + + @Override public Drawable newDrawable() { return new RotateDrawable(this, null); } diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java index b9902491609d..35ef76f81d0b 100644 --- a/graphics/java/android/graphics/drawable/ScaleDrawable.java +++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java @@ -16,6 +16,8 @@ package android.graphics.drawable; +import com.android.internal.R; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -47,7 +49,7 @@ import java.io.IOException; * @attr ref android.R.styleable#ScaleDrawable_drawable */ public class ScaleDrawable extends Drawable implements Drawable.Callback { - private ScaleState mScaleState; + private ScaleState mState; private boolean mMutated; private final Rect mTmpRect = new Rect(); @@ -58,10 +60,10 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { public ScaleDrawable(Drawable drawable, int gravity, float scaleWidth, float scaleHeight) { this(null, null); - mScaleState.mDrawable = drawable; - mScaleState.mGravity = gravity; - mScaleState.mScaleWidth = scaleWidth; - mScaleState.mScaleHeight = scaleHeight; + mState.mDrawable = drawable; + mState.mGravity = gravity; + mState.mScaleWidth = scaleWidth; + mState.mScaleHeight = scaleHeight; if (drawable != null) { drawable.setCallback(this); @@ -72,18 +74,18 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { * Returns the drawable scaled by this ScaleDrawable. */ public Drawable getDrawable() { - return mScaleState.mDrawable; + return mState.mDrawable; } - private static float getPercent(TypedArray a, int name) { - String s = a.getString(name); + private static float getPercent(TypedArray a, int name, float defaultValue) { + final String s = a.getString(name); if (s != null) { if (s.endsWith("%")) { String f = s.substring(0, s.length() - 1); return Float.parseFloat(f) / 100.0f; } } - return -1; + return defaultValue; } @Override @@ -91,20 +93,48 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { throws XmlPullParserException, IOException { super.inflate(r, parser, attrs, theme); - int type; - - TypedArray a = obtainAttributes( - r, theme, attrs, com.android.internal.R.styleable.ScaleDrawable); + final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.ScaleDrawable); - float sw = getPercent(a, com.android.internal.R.styleable.ScaleDrawable_scaleWidth); - float sh = getPercent(a, com.android.internal.R.styleable.ScaleDrawable_scaleHeight); - int g = a.getInt(com.android.internal.R.styleable.ScaleDrawable_scaleGravity, Gravity.LEFT); - boolean min = a.getBoolean( - com.android.internal.R.styleable.ScaleDrawable_useIntrinsicSizeAsMinimum, false); - Drawable dr = a.getDrawable(com.android.internal.R.styleable.ScaleDrawable_drawable); + // Reset mDrawable to preserve old multiple-inflate behavior. This is + // silly, but we have CTS tests that rely on it. + mState.mDrawable = null; + updateStateFromTypedArray(a); + inflateChildElements(r, parser, attrs, theme); + verifyRequiredAttributes(a); a.recycle(); + } + + @Override + public void applyTheme(Theme t) { + super.applyTheme(t); + + final ScaleState state = mState; + if (state == null) { + return; + } + + if (state.mThemeAttrs != null) { + final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ScaleDrawable); + try { + updateStateFromTypedArray(a); + verifyRequiredAttributes(a); + } catch (XmlPullParserException e) { + throw new RuntimeException(e); + } finally { + a.recycle(); + } + } + if (state.mDrawable != null && state.mDrawable.canApplyTheme()) { + state.mDrawable.applyTheme(t); + } + } + + private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs, + Theme theme) throws XmlPullParserException, IOException { + Drawable dr = null; + int type; final int outerDepth = parser.getDepth(); while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { @@ -114,20 +144,51 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { dr = Drawable.createFromXmlInner(r, parser, attrs, theme); } - if (dr == null) { - throw new IllegalArgumentException("No drawable specified for <scale>"); + if (dr != null) { + mState.mDrawable = dr; + dr.setCallback(this); } + } - mScaleState.mDrawable = dr; - mScaleState.mScaleWidth = sw; - mScaleState.mScaleHeight = sh; - mScaleState.mGravity = g; - mScaleState.mUseIntrinsicSizeAsMin = min; + private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException { + // If we're not waiting on a theme, verify required attributes. + if (mState.mDrawable == null && (mState.mThemeAttrs == null + || mState.mThemeAttrs[R.styleable.ScaleDrawable_drawable] == 0)) { + throw new XmlPullParserException(a.getPositionDescription() + + ": <scale> tag requires a 'drawable' attribute or " + + "child tag defining a drawable"); + } + } + + private void updateStateFromTypedArray(TypedArray a) { + final ScaleState state = mState; + + // Account for any configuration changes. + state.mChangingConfigurations |= a.getChangingConfigurations(); + + // Extract the theme attributes, if any. + state.mThemeAttrs = a.extractThemeAttrs(); + + state.mScaleWidth = getPercent( + a, R.styleable.ScaleDrawable_scaleWidth, state.mScaleWidth); + state.mScaleHeight = getPercent( + a, R.styleable.ScaleDrawable_scaleHeight, state.mScaleHeight); + state.mGravity = a.getInt(R.styleable.ScaleDrawable_scaleGravity, Gravity.LEFT); + state.mUseIntrinsicSizeAsMin = a.getBoolean( + R.styleable.ScaleDrawable_useIntrinsicSizeAsMinimum, false); + + final Drawable dr = a.getDrawable(R.styleable.ScaleDrawable_drawable); if (dr != null) { + state.mDrawable = dr; dr.setCallback(this); } } + @Override + public boolean canApplyTheme() { + return (mState != null && mState.canApplyTheme()) || super.canApplyTheme(); + } + // overrides from Drawable.Callback public void invalidateDrawable(Drawable who) { @@ -152,74 +213,74 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { @Override public void draw(Canvas canvas) { - if (mScaleState.mDrawable.getLevel() != 0) - mScaleState.mDrawable.draw(canvas); + if (mState.mDrawable.getLevel() != 0) + mState.mDrawable.draw(canvas); } @Override public int getChangingConfigurations() { return super.getChangingConfigurations() - | mScaleState.mChangingConfigurations - | mScaleState.mDrawable.getChangingConfigurations(); + | mState.mChangingConfigurations + | mState.mDrawable.getChangingConfigurations(); } @Override public boolean getPadding(Rect padding) { // XXX need to adjust padding! - return mScaleState.mDrawable.getPadding(padding); + return mState.mDrawable.getPadding(padding); } @Override public boolean setVisible(boolean visible, boolean restart) { - mScaleState.mDrawable.setVisible(visible, restart); + mState.mDrawable.setVisible(visible, restart); return super.setVisible(visible, restart); } @Override public void setAlpha(int alpha) { - mScaleState.mDrawable.setAlpha(alpha); + mState.mDrawable.setAlpha(alpha); } @Override public int getAlpha() { - return mScaleState.mDrawable.getAlpha(); + return mState.mDrawable.getAlpha(); } @Override public void setColorFilter(ColorFilter cf) { - mScaleState.mDrawable.setColorFilter(cf); + mState.mDrawable.setColorFilter(cf); } @Override public void setTintList(ColorStateList tint) { - mScaleState.mDrawable.setTintList(tint); + mState.mDrawable.setTintList(tint); } @Override public void setTintMode(Mode tintMode) { - mScaleState.mDrawable.setTintMode(tintMode); + mState.mDrawable.setTintMode(tintMode); } @Override public int getOpacity() { - return mScaleState.mDrawable.getOpacity(); + return mState.mDrawable.getOpacity(); } @Override public boolean isStateful() { - return mScaleState.mDrawable.isStateful(); + return mState.mDrawable.isStateful(); } @Override protected boolean onStateChange(int[] state) { - boolean changed = mScaleState.mDrawable.setState(state); + boolean changed = mState.mDrawable.setState(state); onBoundsChange(getBounds()); return changed; } @Override protected boolean onLevelChange(int level) { - mScaleState.mDrawable.setLevel(level); + mState.mDrawable.setLevel(level); onBoundsChange(getBounds()); invalidateSelf(); return true; @@ -228,41 +289,41 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { @Override protected void onBoundsChange(Rect bounds) { final Rect r = mTmpRect; - final boolean min = mScaleState.mUseIntrinsicSizeAsMin; + final boolean min = mState.mUseIntrinsicSizeAsMin; int level = getLevel(); int w = bounds.width(); - if (mScaleState.mScaleWidth > 0) { - final int iw = min ? mScaleState.mDrawable.getIntrinsicWidth() : 0; - w -= (int) ((w - iw) * (10000 - level) * mScaleState.mScaleWidth / 10000); + if (mState.mScaleWidth > 0) { + final int iw = min ? mState.mDrawable.getIntrinsicWidth() : 0; + w -= (int) ((w - iw) * (10000 - level) * mState.mScaleWidth / 10000); } int h = bounds.height(); - if (mScaleState.mScaleHeight > 0) { - final int ih = min ? mScaleState.mDrawable.getIntrinsicHeight() : 0; - h -= (int) ((h - ih) * (10000 - level) * mScaleState.mScaleHeight / 10000); + if (mState.mScaleHeight > 0) { + final int ih = min ? mState.mDrawable.getIntrinsicHeight() : 0; + h -= (int) ((h - ih) * (10000 - level) * mState.mScaleHeight / 10000); } final int layoutDirection = getLayoutDirection(); - Gravity.apply(mScaleState.mGravity, w, h, bounds, r, layoutDirection); + Gravity.apply(mState.mGravity, w, h, bounds, r, layoutDirection); if (w > 0 && h > 0) { - mScaleState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom); + mState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom); } } @Override public int getIntrinsicWidth() { - return mScaleState.mDrawable.getIntrinsicWidth(); + return mState.mDrawable.getIntrinsicWidth(); } @Override public int getIntrinsicHeight() { - return mScaleState.mDrawable.getIntrinsicHeight(); + return mState.mDrawable.getIntrinsicHeight(); } @Override public ConstantState getConstantState() { - if (mScaleState.canConstantState()) { - mScaleState.mChangingConfigurations = getChangingConfigurations(); - return mScaleState; + if (mState.canConstantState()) { + mState.mChangingConfigurations = getChangingConfigurations(); + return mState; } return null; } @@ -270,25 +331,39 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { @Override public Drawable mutate() { if (!mMutated && super.mutate() == this) { - mScaleState.mDrawable.mutate(); + mState.mDrawable.mutate(); mMutated = true; } return this; } + /** + * @hide + */ + public void clearMutated() { + super.clearMutated(); + mState.mDrawable.clearMutated(); + mMutated = false; + } + final static class ScaleState extends ConstantState { - Drawable mDrawable; + int[] mThemeAttrs; int mChangingConfigurations; - float mScaleWidth; - float mScaleHeight; - int mGravity; - boolean mUseIntrinsicSizeAsMin; + + Drawable mDrawable; + + float mScaleWidth = 1.0f; + float mScaleHeight = 1.0f; + int mGravity = Gravity.LEFT; + boolean mUseIntrinsicSizeAsMin = false; private boolean mCheckedConstantState; private boolean mCanConstantState; ScaleState(ScaleState orig, ScaleDrawable owner, Resources res) { if (orig != null) { + mThemeAttrs = orig.mThemeAttrs; + mChangingConfigurations = orig.mChangingConfigurations; if (res != null) { mDrawable = orig.mDrawable.getConstantState().newDrawable(res); } else { @@ -307,6 +382,12 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { } @Override + public boolean canApplyTheme() { + return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme()) + || super.canApplyTheme(); + } + + @Override public Drawable newDrawable() { return new ScaleDrawable(this, null); } @@ -332,7 +413,7 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { } private ScaleDrawable(ScaleState state, Resources res) { - mScaleState = new ScaleState(state, this, res); + mState = new ScaleState(state, this, res); } } diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java index bd69d76867b5..a3d8c9236a74 100644 --- a/graphics/java/android/graphics/drawable/ShapeDrawable.java +++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java @@ -76,7 +76,7 @@ public class ShapeDrawable extends Drawable { * ShapeDrawable constructor. */ public ShapeDrawable() { - this(new ShapeState(null), null, null); + this(new ShapeState(null), null); } /** @@ -85,7 +85,7 @@ public class ShapeDrawable extends Drawable { * @param s the Shape that this ShapeDrawable should be */ public ShapeDrawable(Shape s) { - this(new ShapeState(null), null, null); + this(new ShapeState(null), null); mShapeState.mShape = s; } @@ -508,6 +508,14 @@ public class ShapeDrawable extends Drawable { } /** + * @hide + */ + public void clearMutated() { + super.clearMutated(); + mMutated = false; + } + + /** * Defines the intrinsic properties of this ShapeDrawable's Shape. */ final static class ShapeState extends ConstantState { @@ -547,17 +555,12 @@ public class ShapeDrawable extends Drawable { @Override public Drawable newDrawable() { - return new ShapeDrawable(this, null, null); + return new ShapeDrawable(this, null); } @Override public Drawable newDrawable(Resources res) { - return new ShapeDrawable(this, res, null); - } - - @Override - public Drawable newDrawable(Resources res, Theme theme) { - return new ShapeDrawable(this, res, theme); + return new ShapeDrawable(this, res); } @Override @@ -570,13 +573,8 @@ public class ShapeDrawable extends Drawable { * The one constructor to rule them all. This is called by all public * constructors to set the state and initialize local properties. */ - private ShapeDrawable(ShapeState state, Resources res, Theme theme) { - if (theme != null && state.canApplyTheme()) { - mShapeState = new ShapeState(state); - applyTheme(theme); - } else { - mShapeState = state; - } + private ShapeDrawable(ShapeState state, Resources res) { + mShapeState = state; initializeWithState(state, res); } diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java index 2eb8a8020624..963943b5fa5d 100644 --- a/graphics/java/android/graphics/drawable/StateListDrawable.java +++ b/graphics/java/android/graphics/drawable/StateListDrawable.java @@ -117,26 +117,48 @@ public class StateListDrawable extends DrawableContainer { @Override public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme) throws XmlPullParserException, IOException { - final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.StateListDrawable); + super.inflateWithAttributes(r, parser, a, R.styleable.StateListDrawable_visible); + updateStateFromTypedArray(a); + a.recycle(); - super.inflateWithAttributes(r, parser, a, - R.styleable.StateListDrawable_visible); - - mStateListState.setVariablePadding(a.getBoolean( - R.styleable.StateListDrawable_variablePadding, false)); - mStateListState.setConstantSize(a.getBoolean( - R.styleable.StateListDrawable_constantSize, false)); - mStateListState.setEnterFadeDuration(a.getInt( - R.styleable.StateListDrawable_enterFadeDuration, 0)); - mStateListState.setExitFadeDuration(a.getInt( - R.styleable.StateListDrawable_exitFadeDuration, 0)); + inflateChildElements(r, parser, attrs, theme); - setDither(a.getBoolean(R.styleable.StateListDrawable_dither, DEFAULT_DITHER)); - setAutoMirrored(a.getBoolean(R.styleable.StateListDrawable_autoMirrored, false)); + onStateChange(getState()); + } - a.recycle(); + /** + * Updates the constant state from the values in the typed array. + */ + private void updateStateFromTypedArray(TypedArray a) { + final StateListState state = mStateListState; + + // Account for any configuration changes. + state.mChangingConfigurations |= a.getChangingConfigurations(); + + // Extract the theme attributes, if any. + state.mThemeAttrs = a.extractThemeAttrs(); + + state.mVariablePadding = a.getBoolean( + R.styleable.StateListDrawable_variablePadding, state.mVariablePadding); + state.mConstantSize = a.getBoolean( + R.styleable.StateListDrawable_constantSize, state.mConstantSize); + state.mEnterFadeDuration = a.getInt( + R.styleable.StateListDrawable_enterFadeDuration, state.mEnterFadeDuration); + state.mExitFadeDuration = a.getInt( + R.styleable.StateListDrawable_exitFadeDuration, state.mExitFadeDuration); + state.mDither = a.getBoolean( + R.styleable.StateListDrawable_dither, state.mDither); + state.mAutoMirrored = a.getBoolean( + R.styleable.StateListDrawable_autoMirrored, state.mAutoMirrored); + } + /** + * Inflates child elements from XML. + */ + private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs, + Theme theme) throws XmlPullParserException, IOException { + final StateListState state = mStateListState; final int innerDepth = parser.getDepth() + 1; int type; int depth; @@ -185,10 +207,8 @@ public class StateListDrawable extends DrawableContainer { dr = Drawable.createFromXmlInner(r, parser, attrs, theme); } - mStateListState.addStateSet(states, dr); + state.addStateSet(states, dr); } - - onStateChange(getState()); } StateListState getStateListState() { @@ -263,6 +283,14 @@ public class StateListDrawable extends DrawableContainer { return this; } + /** + * @hide + */ + public void clearMutated() { + super.clearMutated(); + mMutated = false; + } + /** @hide */ @Override public void setLayoutDirection(int layoutDirection) { @@ -274,14 +302,28 @@ public class StateListDrawable extends DrawableContainer { } static class StateListState extends DrawableContainerState { + int[] mThemeAttrs; int[][] mStateSets; StateListState(StateListState orig, StateListDrawable owner, Resources res) { super(orig, owner, res); if (orig != null) { + // Perform a deep copy. + final int[][] sets = orig.mStateSets; + final int count = sets.length; + mStateSets = new int[count][]; + for (int i = 0; i < count; i++) { + final int[] set = sets[i]; + if (set != null) { + mStateSets[i] = set.clone(); + } + } + + mThemeAttrs = orig.mThemeAttrs; mStateSets = Arrays.copyOf(orig.mStateSets, orig.mStateSets.length); } else { + mThemeAttrs = null; mStateSets = new int[getCapacity()][]; } } @@ -314,6 +356,11 @@ public class StateListDrawable extends DrawableContainer { } @Override + public boolean canApplyTheme() { + return mThemeAttrs != null || super.canApplyTheme(); + } + + @Override public void growArray(int oldSize, int newSize) { super.growArray(oldSize, newSize); final int[][] newStateSets = new int[newSize][]; @@ -322,6 +369,13 @@ public class StateListDrawable extends DrawableContainer { } } + @Override + public void applyTheme(Theme theme) { + super.applyTheme(theme); + + onStateChange(getState()); + } + void setConstantState(StateListState state) { super.setConstantState(state); diff --git a/graphics/java/android/graphics/drawable/TransitionDrawable.java b/graphics/java/android/graphics/drawable/TransitionDrawable.java index 4380ca4e8145..e5c235efaba5 100644 --- a/graphics/java/android/graphics/drawable/TransitionDrawable.java +++ b/graphics/java/android/graphics/drawable/TransitionDrawable.java @@ -17,7 +17,6 @@ package android.graphics.drawable; import android.content.res.Resources; -import android.content.res.Resources.Theme; import android.graphics.Canvas; import android.os.SystemClock; @@ -86,11 +85,11 @@ public class TransitionDrawable extends LayerDrawable implements Drawable.Callba * @see #TransitionDrawable(Drawable[]) */ TransitionDrawable() { - this(new TransitionState(null, null, null), null, null); + this(new TransitionState(null, null, null), (Resources) null); } - private TransitionDrawable(TransitionState state, Resources res, Theme theme) { - super(state, res, theme); + private TransitionDrawable(TransitionState state, Resources res) { + super(state, res); } private TransitionDrawable(TransitionState state, Drawable[] layers) { @@ -245,24 +244,18 @@ public class TransitionDrawable extends LayerDrawable implements Drawable.Callba } static class TransitionState extends LayerState { - TransitionState(TransitionState orig, TransitionDrawable owner, - Resources res) { + TransitionState(TransitionState orig, TransitionDrawable owner, Resources res) { super(orig, owner, res); } @Override public Drawable newDrawable() { - return new TransitionDrawable(this, null, null); + return new TransitionDrawable(this, (Resources) null); } @Override public Drawable newDrawable(Resources res) { - return new TransitionDrawable(this, res, null); - } - - @Override - public Drawable newDrawable(Resources res, Theme theme) { - return new TransitionDrawable(this, res, theme); + return new TransitionDrawable(this, res); } @Override diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index db0c94f01f26..8b0f635482e0 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -14,6 +14,7 @@ package android.graphics.drawable; +import android.annotation.NonNull; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; @@ -212,15 +213,8 @@ public class VectorDrawable extends Drawable { mVectorState = new VectorDrawableState(); } - private VectorDrawable(VectorDrawableState state, Resources res, Theme theme) { - if (theme != null && state.canApplyTheme()) { - // If we need to apply a theme, implicitly mutate. - mVectorState = new VectorDrawableState(state); - applyTheme(theme); - } else { - mVectorState = state; - } - + private VectorDrawable(@NonNull VectorDrawableState state) { + mVectorState = state; mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); } @@ -233,6 +227,14 @@ public class VectorDrawable extends Drawable { return this; } + /** + * @hide + */ + public void clearMutated() { + super.clearMutated(); + mMutated = false; + } + Object getTargetByName(String name) { return mVectorState.mVPathRenderer.mVGTargetsMap.get(name); } @@ -359,7 +361,7 @@ public class VectorDrawable extends Drawable { @Override public boolean canApplyTheme() { - return super.canApplyTheme() || mVectorState != null && mVectorState.canApplyTheme(); + return (mVectorState != null && mVectorState.canApplyTheme()) || super.canApplyTheme(); } @Override @@ -748,8 +750,8 @@ public class VectorDrawable extends Drawable { @Override public boolean canApplyTheme() { - return super.canApplyTheme() || mThemeAttrs != null - || (mVPathRenderer != null && mVPathRenderer.canApplyTheme()); + return mThemeAttrs != null || (mVPathRenderer != null && mVPathRenderer.canApplyTheme()) + || super.canApplyTheme(); } public VectorDrawableState() { @@ -758,17 +760,12 @@ public class VectorDrawable extends Drawable { @Override public Drawable newDrawable() { - return new VectorDrawable(this, null, null); + return new VectorDrawable(this); } @Override public Drawable newDrawable(Resources res) { - return new VectorDrawable(this, res, null); - } - - @Override - public Drawable newDrawable(Resources res, Theme theme) { - return new VectorDrawable(this, res, theme); + return new VectorDrawable(this); } @Override diff --git a/graphics/java/android/graphics/pdf/PdfEditor.java b/graphics/java/android/graphics/pdf/PdfEditor.java index 9837139bbe0d..2b70b6a45f82 100644 --- a/graphics/java/android/graphics/pdf/PdfEditor.java +++ b/graphics/java/android/graphics/pdf/PdfEditor.java @@ -17,6 +17,10 @@ package android.graphics.pdf; import android.annotation.NonNull; +import android.annotation.Nullable; +import android.graphics.Matrix; +import android.graphics.Point; +import android.graphics.Rect; import android.os.ParcelFileDescriptor; import android.system.ErrnoException; import android.system.OsConstants; @@ -55,6 +59,10 @@ public final class PdfEditor { * * @param input Seekable file descriptor to read from. * + * @throws java.io.IOException If an error occurs while reading the file. + * @throws java.lang.SecurityException If the file requires a password or + * the security scheme is not supported. + * * @see #close() */ public PdfEditor(@NonNull ParcelFileDescriptor input) throws IOException { @@ -98,6 +106,109 @@ public final class PdfEditor { } /** + * Sets a transformation and clip for a given page. The transformation matrix if + * non-null must be affine as per {@link android.graphics.Matrix#isAffine()}. If + * the clip is null, then no clipping is performed. + * + * @param pageIndex The page whose transform to set. + * @param transform The transformation to apply. + * @param clip The clip to apply. + */ + public void setTransformAndClip(int pageIndex, @Nullable Matrix transform, + @Nullable Rect clip) { + throwIfClosed(); + throwIfPageNotInDocument(pageIndex); + throwIfNotNullAndNotAfine(transform); + if (transform == null) { + transform = Matrix.IDENTITY_MATRIX; + } + if (clip == null) { + Point size = new Point(); + getPageSize(pageIndex, size); + nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.native_instance, + 0, 0, size.x, size.y); + } else { + nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.native_instance, + clip.left, clip.top, clip.right, clip.bottom); + } + } + + /** + * Gets the size of a given page in mils (1/72"). + * + * @param pageIndex The page index. + * @param outSize The size output. + */ + public void getPageSize(int pageIndex, @NonNull Point outSize) { + throwIfClosed(); + throwIfOutSizeNull(outSize); + throwIfPageNotInDocument(pageIndex); + nativeGetPageSize(mNativeDocument, pageIndex, outSize); + } + + /** + * Gets the media box of a given page in mils (1/72"). + * + * @param pageIndex The page index. + * @param outMediaBox The media box output. + */ + public boolean getPageMediaBox(int pageIndex, @NonNull Rect outMediaBox) { + throwIfClosed(); + throwIfOutMediaBoxNull(outMediaBox); + throwIfPageNotInDocument(pageIndex); + return nativeGetPageMediaBox(mNativeDocument, pageIndex, outMediaBox); + } + + /** + * Sets the media box of a given page in mils (1/72"). + * + * @param pageIndex The page index. + * @param mediaBox The media box. + */ + public void setPageMediaBox(int pageIndex, @NonNull Rect mediaBox) { + throwIfClosed(); + throwIfMediaBoxNull(mediaBox); + throwIfPageNotInDocument(pageIndex); + nativeSetPageMediaBox(mNativeDocument, pageIndex, mediaBox); + } + + /** + * Gets the crop box of a given page in mils (1/72"). + * + * @param pageIndex The page index. + * @param outCropBox The crop box output. + */ + public boolean getPageCropBox(int pageIndex, @NonNull Rect outCropBox) { + throwIfClosed(); + throwIfOutCropBoxNull(outCropBox); + throwIfPageNotInDocument(pageIndex); + return nativeGetPageCropBox(mNativeDocument, pageIndex, outCropBox); + } + + /** + * Sets the crop box of a given page in mils (1/72"). + * + * @param pageIndex The page index. + * @param cropBox The crop box. + */ + public void setPageCropBox(int pageIndex, @NonNull Rect cropBox) { + throwIfClosed(); + throwIfCropBoxNull(cropBox); + throwIfPageNotInDocument(pageIndex); + nativeSetPageCropBox(mNativeDocument, pageIndex, cropBox); + } + + /** + * Gets whether the document prefers to be scaled for printing. + * + * @return Whether to scale the document. + */ + public boolean shouldScaleForPrinting() { + throwIfClosed(); + return nativeScaleForPrinting(mNativeDocument); + } + + /** * Writes the PDF file to the provided destination. * <p> * <strong>Note:</strong> This method takes ownership of the passed in file @@ -154,9 +265,57 @@ public final class PdfEditor { } } + private void throwIfNotNullAndNotAfine(Matrix matrix) { + if (matrix != null && !matrix.isAffine()) { + throw new IllegalStateException("Matrix must be afine"); + } + } + + private void throwIfOutSizeNull(Point outSize) { + if (outSize == null) { + throw new NullPointerException("outSize cannot be null"); + } + } + + private void throwIfOutMediaBoxNull(Rect outMediaBox) { + if (outMediaBox == null) { + throw new NullPointerException("outMediaBox cannot be null"); + } + } + + private void throwIfMediaBoxNull(Rect mediaBox) { + if (mediaBox == null) { + throw new NullPointerException("mediaBox cannot be null"); + } + } + + private void throwIfOutCropBoxNull(Rect outCropBox) { + if (outCropBox == null) { + throw new NullPointerException("outCropBox cannot be null"); + } + } + + private void throwIfCropBoxNull(Rect cropBox) { + if (cropBox == null) { + throw new NullPointerException("cropBox cannot be null"); + } + } + private static native long nativeOpen(int fd, long size); private static native void nativeClose(long documentPtr); private static native int nativeGetPageCount(long documentPtr); private static native int nativeRemovePage(long documentPtr, int pageIndex); private static native void nativeWrite(long documentPtr, int fd); + private static native void nativeSetTransformAndClip(long documentPtr, int pageIndex, + long transformPtr, int clipLeft, int clipTop, int clipRight, int clipBottom); + private static native void nativeGetPageSize(long documentPtr, int pageIndex, Point outSize); + private static native boolean nativeGetPageMediaBox(long documentPtr, int pageIndex, + Rect outMediaBox); + private static native void nativeSetPageMediaBox(long documentPtr, int pageIndex, + Rect mediaBox); + private static native boolean nativeGetPageCropBox(long documentPtr, int pageIndex, + Rect outMediaBox); + private static native void nativeSetPageCropBox(long documentPtr, int pageIndex, + Rect mediaBox); + private static native boolean nativeScaleForPrinting(long documentPtr); } diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java index 359c29480d03..79934da09aa1 100644 --- a/graphics/java/android/graphics/pdf/PdfRenderer.java +++ b/graphics/java/android/graphics/pdf/PdfRenderer.java @@ -131,6 +131,10 @@ public final class PdfRenderer implements AutoCloseable { * </p> * * @param input Seekable file descriptor to read from. + * + * @throws java.io.IOException If an error occurs while reading the file. + * @throws java.lang.SecurityException If the file requires a password or + * the security scheme is not supported. */ public PdfRenderer(@NonNull ParcelFileDescriptor input) throws IOException { if (input == null) { diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h index ac5eca08a4ff..85e442da0184 100644 --- a/include/androidfw/ResourceTypes.h +++ b/include/androidfw/ResourceTypes.h @@ -253,7 +253,8 @@ struct Res_value // Type of the data value. enum { - // Contains no data. + // The 'data' is either 0 or 1, specifying this resource is either + // undefined or empty, respectively. TYPE_NULL = 0x00, // The 'data' holds a ResTable_ref, a reference to another resource // table entry. @@ -351,6 +352,14 @@ struct Res_value COMPLEX_MANTISSA_MASK = 0xffffff }; + // Possible data values for TYPE_NULL. + enum { + // The value is not defined. + DATA_NULL_UNDEFINED = 0, + // The value is explicitly defined as empty. + DATA_NULL_EMPTY = 1 + }; + // The data for this item, as interpreted according to dataType. uint32_t data; diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index b5d2885e3f37..3bbca1a0165e 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -4639,8 +4639,15 @@ bool ResTable::stringToValue(Res_value* outValue, String16* outString, // It's a reference! if (len == 5 && s[1]=='n' && s[2]=='u' && s[3]=='l' && s[4]=='l') { + // Special case @null as undefined. This will be converted by + // AssetManager to TYPE_NULL with data DATA_NULL_UNDEFINED. outValue->data = 0; return true; + } else if (len == 6 && s[1]=='e' && s[2]=='m' && s[3]=='p' && s[4]=='t' && s[5]=='y') { + // Special case @empty as explicitly defined empty value. + outValue->dataType = Res_value::TYPE_NULL; + outValue->data = Res_value::DATA_NULL_EMPTY; + return true; } else { bool createIfNotFound = false; const char16_t* resourceRefName; @@ -6251,7 +6258,14 @@ String8 ResTable::normalizeForOutput( const char *input ) void ResTable::print_value(const Package* pkg, const Res_value& value) const { if (value.dataType == Res_value::TYPE_NULL) { - printf("(null)\n"); + if (value.data == Res_value::DATA_NULL_UNDEFINED) { + printf("(null)\n"); + } else if (value.data == Res_value::DATA_NULL_EMPTY) { + printf("(null empty)\n"); + } else { + // This should never happen. + printf("(null) 0x%08x\n", value.data); + } } else if (value.dataType == Res_value::TYPE_REFERENCE) { printf("(reference) 0x%08x\n", value.data); } else if (value.dataType == Res_value::TYPE_DYNAMIC_REFERENCE) { diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk index 5808d201643e..b2e465c55e47 100644 --- a/libs/androidfw/tests/Android.mk +++ b/libs/androidfw/tests/Android.mk @@ -26,6 +26,7 @@ testFiles := \ Idmap_test.cpp \ ResTable_test.cpp \ Split_test.cpp \ + TestHelpers.cpp \ Theme_test.cpp \ TypeWrappers_test.cpp \ ZipUtils_test.cpp @@ -50,6 +51,7 @@ include $(BUILD_HOST_NATIVE_TEST) # ========================================================== # Build the device tests: libandroidfw_tests # ========================================================== +ifneq ($(SDK_ONLY),true) include $(CLEAR_VARS) LOCAL_MODULE := libandroidfw_tests @@ -66,3 +68,5 @@ LOCAL_SHARED_LIBRARIES := \ libstlport include $(BUILD_NATIVE_TEST) +endif # Not SDK_ONLY + diff --git a/libs/androidfw/tests/ResTable_test.cpp b/libs/androidfw/tests/ResTable_test.cpp index 89d271d0bcd6..6a9314e5ffb8 100644 --- a/libs/androidfw/tests/ResTable_test.cpp +++ b/libs/androidfw/tests/ResTable_test.cpp @@ -37,8 +37,6 @@ namespace { #include "data/lib/lib_arsc.h" -enum { MAY_NOT_BE_BAG = false }; - TEST(ResTableTest, shouldLoadSuccessfully) { ResTable table; ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len)); @@ -48,15 +46,7 @@ TEST(ResTableTest, simpleTypeIsRetrievedCorrectly) { ResTable table; ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len)); - Res_value val; - ssize_t block = table.getResource(base::R::string::test1, &val, MAY_NOT_BE_BAG); - - ASSERT_GE(block, 0); - ASSERT_EQ(Res_value::TYPE_STRING, val.dataType); - - const ResStringPool* pool = table.getTableStringBlock(block); - ASSERT_TRUE(NULL != pool); - ASSERT_EQ(String8("test1"), pool->string8ObjectAt(val.data)); + EXPECT_TRUE(IsStringEqual(table, base::R::string::test1, "test1")); } TEST(ResTableTest, resourceNameIsResolved) { diff --git a/libs/androidfw/tests/Split_test.cpp b/libs/androidfw/tests/Split_test.cpp index f63f566fa444..b69d68572e6a 100644 --- a/libs/androidfw/tests/Split_test.cpp +++ b/libs/androidfw/tests/Split_test.cpp @@ -42,6 +42,9 @@ namespace { * Package: com.android.test.basic */ #include "data/basic/split_de_fr_arsc.h" +#include "data/basic/split_hdpi_v4_arsc.h" +#include "data/basic/split_xhdpi_v4_arsc.h" +#include "data/basic/split_xxhdpi_v4_arsc.h" /** * Include a binary resource table. This table @@ -163,6 +166,33 @@ TEST(SplitTest, TypeEntrySpecFlagsAreUpdated) { EXPECT_EQ(ResTable_config::CONFIG_LOCALE, frSpecFlags); } +TEST(SplitTest, SelectBestDensity) { + ResTable_config baseConfig; + memset(&baseConfig, 0, sizeof(baseConfig)); + baseConfig.density = ResTable_config::DENSITY_XHIGH; + baseConfig.sdkVersion = 21; + + ResTable table; + table.setParameters(&baseConfig); + ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len)); + ASSERT_EQ(NO_ERROR, table.add(split_hdpi_v4_arsc, split_hdpi_v4_arsc_len)); + + EXPECT_TRUE(IsStringEqual(table, base::R::string::density, "hdpi")); + + ASSERT_EQ(NO_ERROR, table.add(split_xhdpi_v4_arsc, split_xhdpi_v4_arsc_len)); + + EXPECT_TRUE(IsStringEqual(table, base::R::string::density, "xhdpi")); + + ASSERT_EQ(NO_ERROR, table.add(split_xxhdpi_v4_arsc, split_xxhdpi_v4_arsc_len)); + + EXPECT_TRUE(IsStringEqual(table, base::R::string::density, "xhdpi")); + + baseConfig.density = ResTable_config::DENSITY_XXHIGH; + table.setParameters(&baseConfig); + + EXPECT_TRUE(IsStringEqual(table, base::R::string::density, "xxhdpi")); +} + TEST(SplitFeatureTest, TestNewResourceIsAccessible) { ResTable table; ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len)); @@ -188,7 +218,7 @@ TEST(SplitFeatureTest, TestNewResourceNameHasCorrectName) { ASSERT_EQ(NO_ERROR, table.add(feature_arsc, feature_arsc_len)); - EXPECT_TRUE(table.getResourceName(base::R::string::test3, false, &name)); + ASSERT_TRUE(table.getResourceName(base::R::string::test3, false, &name)); EXPECT_EQ(String16("com.android.test.basic"), String16(name.package, name.packageLen)); diff --git a/libs/androidfw/tests/TestHelpers.cpp b/libs/androidfw/tests/TestHelpers.cpp new file mode 100644 index 000000000000..41a19a7f2b24 --- /dev/null +++ b/libs/androidfw/tests/TestHelpers.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2014 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. + */ + +#include "TestHelpers.h" + +#include <androidfw/ResourceTypes.h> +#include <utils/String8.h> +#include <gtest/gtest.h> + +namespace android { + +::testing::AssertionResult IsStringEqual(const ResTable& table, uint32_t resourceId, const char* expectedStr) { + Res_value val; + ssize_t block = table.getResource(resourceId, &val, MAY_NOT_BE_BAG); + if (block < 0) { + return ::testing::AssertionFailure() << "could not find resource"; + } + + if (val.dataType != Res_value::TYPE_STRING) { + return ::testing::AssertionFailure() << "resource is not a string"; + } + + const ResStringPool* pool = table.getTableStringBlock(block); + if (pool == NULL) { + return ::testing::AssertionFailure() << "table has no string pool for block " << block; + } + + const String8 actual = pool->string8ObjectAt(val.data); + if (String8(expectedStr) != actual) { + return ::testing::AssertionFailure() << actual.string(); + } + return ::testing::AssertionSuccess() << actual.string(); +} + +} // namespace android diff --git a/libs/androidfw/tests/TestHelpers.h b/libs/androidfw/tests/TestHelpers.h index fe2e5ce29eff..ac80d8868090 100644 --- a/libs/androidfw/tests/TestHelpers.h +++ b/libs/androidfw/tests/TestHelpers.h @@ -6,6 +6,7 @@ #include <androidfw/ResourceTypes.h> #include <utils/String8.h> #include <utils/String16.h> +#include <gtest/gtest.h> static inline ::std::ostream& operator<<(::std::ostream& out, const android::String8& str) { return out << str.string(); @@ -17,6 +18,8 @@ static inline ::std::ostream& operator<<(::std::ostream& out, const android::Str namespace android { +enum { MAY_NOT_BE_BAG = false }; + static inline bool operator==(const android::ResTable_config& a, const android::ResTable_config& b) { return memcmp(&a, &b, sizeof(a)) == 0; } @@ -25,6 +28,8 @@ static inline ::std::ostream& operator<<(::std::ostream& out, const android::Res return out << c.toString().string(); } +::testing::AssertionResult IsStringEqual(const ResTable& table, uint32_t resourceId, const char* expectedStr); + } // namespace android #endif // __TEST_HELPERS_H diff --git a/libs/androidfw/tests/data/app/R.h b/libs/androidfw/tests/data/app/R.h index 780a11610ef5..23e68e3e80dc 100644 --- a/libs/androidfw/tests/data/app/R.h +++ b/libs/androidfw/tests/data/app/R.h @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2014 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. + */ + #ifndef __APP_R_H #define __APP_R_H diff --git a/libs/androidfw/tests/data/app/build b/libs/androidfw/tests/data/app/build index 89c464120ea3..62257bc26d4b 100755 --- a/libs/androidfw/tests/data/app/build +++ b/libs/androidfw/tests/data/app/build @@ -1,4 +1,19 @@ #!/bin/bash +# +# Copyright (C) 2014 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. +# aapt package -v -I ../system/bundle.apk -M AndroidManifest.xml -S res -F bundle.apk -f && \ unzip bundle.apk resources.arsc && \ diff --git a/libs/androidfw/tests/data/app/res/values/values.xml b/libs/androidfw/tests/data/app/res/values/values.xml index b0ead387b0a8..c1cf64c247a3 100644 --- a/libs/androidfw/tests/data/app/res/values/values.xml +++ b/libs/androidfw/tests/data/app/res/values/values.xml @@ -1,4 +1,19 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + <resources> <attr name="number" format="integer"/> <style name="Theme.One" parent="@android:style/Theme.One"> diff --git a/libs/androidfw/tests/data/basic/R.h b/libs/androidfw/tests/data/basic/R.h index 363dcb9e170c..aaac74059f58 100644 --- a/libs/androidfw/tests/data/basic/R.h +++ b/libs/androidfw/tests/data/basic/R.h @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2014 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. + */ + #ifndef __BASE_R_H #define __BASE_R_H @@ -21,9 +37,10 @@ namespace string { enum { test1 = 0x7f030000, // default test2 = 0x7f030001, // default + density = 0x7f030002, // default - test3 = 0x7f070000, // default (in feature) - test4 = 0x7f070001, // default (in feature) + test3 = 0x7f080000, // default (in feature) + test4 = 0x7f080001, // default (in feature) }; } @@ -32,7 +49,7 @@ namespace integer { number1 = 0x7f040000, // default, sv number2 = 0x7f040001, // default - test3 = 0x7f080000, // default (in feature) + test3 = 0x7f090000, // default (in feature) }; } diff --git a/libs/androidfw/tests/data/basic/basic_arsc.h b/libs/androidfw/tests/data/basic/basic_arsc.h index 61cb94c65828..13ab4fa0d0ea 100644 --- a/libs/androidfw/tests/data/basic/basic_arsc.h +++ b/libs/androidfw/tests/data/basic/basic_arsc.h @@ -1,5 +1,5 @@ unsigned char basic_arsc[] = { - 0x02, 0x00, 0x0c, 0x00, 0x60, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x0c, 0x00, 0x68, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, @@ -16,7 +16,7 @@ unsigned char basic_arsc[] = { 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x31, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, - 0x98, 0x06, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, + 0xa0, 0x06, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, @@ -101,61 +101,61 @@ unsigned char basic_arsc[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, - 0x6c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x02, 0x44, 0x00, 0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, - 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, - 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, + 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x6c, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, - 0xc8, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x7f, 0x01, 0x02, 0x44, 0x00, - 0x5c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x73, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, - 0x90, 0x01, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x90, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0xc8, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x06, 0x7f, 0x01, 0x02, 0x44, 0x00, 0x5c, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x76, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x90, 0x01, 0x00, 0x00, + 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x02, 0x44, 0x00, 0x90, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x10, 0x64, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x7f, - 0x10, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x7f, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x10, - 0x2c, 0x01, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x02, 0x44, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7f, + 0x08, 0x00, 0x00, 0x10, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7f, + 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x7f, 0x10, 0x00, 0x01, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x7f, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x10, 0x2c, 0x01, 0x00, 0x00, + 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, + 0x7c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10, - 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10, - 0x03, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x00 }; -unsigned int basic_arsc_len = 1888; +unsigned int basic_arsc_len = 1896; diff --git a/libs/androidfw/tests/data/basic/build b/libs/androidfw/tests/data/basic/build index 036e46828189..fd289fad62b1 100755 --- a/libs/androidfw/tests/data/basic/build +++ b/libs/androidfw/tests/data/basic/build @@ -1,11 +1,39 @@ #!/bin/bash +# +# Copyright (C) 2014 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. +# PATH_TO_FRAMEWORK_RES=$(gettop)/prebuilts/sdk/current/android.jar -aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES --split fr,de -F bundle.apk -f && \ +aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES --split hdpi --split xhdpi --split xxhdpi --split fr,de -F bundle.apk -f && \ unzip bundle.apk resources.arsc && \ mv resources.arsc basic.arsc && \ xxd -i basic.arsc > basic_arsc.h && \ +\ unzip bundle_de_fr.apk resources.arsc && \ mv resources.arsc split_de_fr.arsc && \ -xxd -i split_de_fr.arsc > split_de_fr_arsc.h +xxd -i split_de_fr.arsc > split_de_fr_arsc.h && \ +\ +unzip bundle_hdpi-v4.apk resources.arsc && \ +mv resources.arsc split_hdpi_v4.arsc && \ +xxd -i split_hdpi_v4.arsc > split_hdpi_v4_arsc.h && \ +\ +unzip bundle_xhdpi-v4.apk resources.arsc && \ +mv resources.arsc split_xhdpi_v4.arsc && \ +xxd -i split_xhdpi_v4.arsc > split_xhdpi_v4_arsc.h && \ +\ +unzip bundle_xxhdpi-v4.apk resources.arsc && \ +mv resources.arsc split_xxhdpi_v4.arsc && \ +xxd -i split_xxhdpi_v4.arsc > split_xxhdpi_v4_arsc.h \ diff --git a/libs/androidfw/tests/data/basic/res/layout-fr-sw600dp/main.xml b/libs/androidfw/tests/data/basic/res/layout-fr-sw600dp/main.xml index 05ffd5856487..0dcf7e092577 100644 --- a/libs/androidfw/tests/data/basic/res/layout-fr-sw600dp/main.xml +++ b/libs/androidfw/tests/data/basic/res/layout-fr-sw600dp/main.xml @@ -1,3 +1,18 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + <merge> </merge> diff --git a/libs/androidfw/tests/data/basic/res/layout/main.xml b/libs/androidfw/tests/data/basic/res/layout/main.xml index 05ffd5856487..0dcf7e092577 100644 --- a/libs/androidfw/tests/data/basic/res/layout/main.xml +++ b/libs/androidfw/tests/data/basic/res/layout/main.xml @@ -1,3 +1,18 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + <merge> </merge> diff --git a/libs/androidfw/tests/data/basic/res/values-de/values.xml b/libs/androidfw/tests/data/basic/res/values-de/values.xml index 103c6a3643c4..2683a7eee68c 100644 --- a/libs/androidfw/tests/data/basic/res/values-de/values.xml +++ b/libs/androidfw/tests/data/basic/res/values-de/values.xml @@ -1,4 +1,19 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + <resources> <string name="test1">versuch 1</string> <string name="test2">versuch 2</string> diff --git a/libs/androidfw/tests/data/basic/res/values-fr/values.xml b/libs/androidfw/tests/data/basic/res/values-fr/values.xml index 1806a2dc12a9..7d3bed3f220f 100644 --- a/libs/androidfw/tests/data/basic/res/values-fr/values.xml +++ b/libs/androidfw/tests/data/basic/res/values-fr/values.xml @@ -1,4 +1,19 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + <resources> <string name="test1">essai 1</string> <string name="test2">essai 2</string> diff --git a/libs/androidfw/tests/data/basic/res/values-hdpi/values.xml b/libs/androidfw/tests/data/basic/res/values-hdpi/values.xml new file mode 100644 index 000000000000..04bf943f7fe4 --- /dev/null +++ b/libs/androidfw/tests/data/basic/res/values-hdpi/values.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<resources> + <string name="density">hdpi</string> +</resources> diff --git a/libs/androidfw/tests/data/basic/res/values-sv/values.xml b/libs/androidfw/tests/data/basic/res/values-sv/values.xml index 9d523071dd07..7351b4989c92 100644 --- a/libs/androidfw/tests/data/basic/res/values-sv/values.xml +++ b/libs/androidfw/tests/data/basic/res/values-sv/values.xml @@ -1,4 +1,19 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + <resources> <integer name="number1">400</integer> </resources> diff --git a/libs/androidfw/tests/data/basic/res/values-xhdpi/values.xml b/libs/androidfw/tests/data/basic/res/values-xhdpi/values.xml new file mode 100644 index 000000000000..845e9a02e9b0 --- /dev/null +++ b/libs/androidfw/tests/data/basic/res/values-xhdpi/values.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<resources> + <string name="density">xhdpi</string> +</resources> diff --git a/libs/androidfw/tests/data/basic/res/values-xxhdpi/values.xml b/libs/androidfw/tests/data/basic/res/values-xxhdpi/values.xml new file mode 100644 index 000000000000..964da020d847 --- /dev/null +++ b/libs/androidfw/tests/data/basic/res/values-xxhdpi/values.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<resources> + <string name="density">xxhdpi</string> +</resources> diff --git a/libs/androidfw/tests/data/basic/res/values/values.xml b/libs/androidfw/tests/data/basic/res/values/values.xml index 662eda6a4ed5..a010cca182ee 100644 --- a/libs/androidfw/tests/data/basic/res/values/values.xml +++ b/libs/androidfw/tests/data/basic/res/values/values.xml @@ -1,4 +1,19 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + <resources> <attr name="attr1" format="reference|integer" /> <attr name="attr2" format="reference|integer" /> diff --git a/libs/androidfw/tests/data/basic/split_de_fr_arsc.h b/libs/androidfw/tests/data/basic/split_de_fr_arsc.h index a8eaf0b2f69d..b742d2811487 100644 --- a/libs/androidfw/tests/data/basic/split_de_fr_arsc.h +++ b/libs/androidfw/tests/data/basic/split_de_fr_arsc.h @@ -1,5 +1,5 @@ unsigned char split_de_fr_arsc[] = { - 0x02, 0x00, 0x0c, 0x00, 0xd8, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x0c, 0x00, 0xe4, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, @@ -10,7 +10,7 @@ unsigned char split_de_fr_arsc[] = { 0x32, 0x00, 0x00, 0x00, 0x07, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, 0x07, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x20, 0x00, - 0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x50, 0x03, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x5c, 0x03, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, @@ -55,24 +55,25 @@ unsigned char split_de_fr_arsc[] = { 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x6c, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, + 0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x64, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x6c, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x72, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x02, 0x44, 0x00, 0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, @@ -82,4 +83,4 @@ unsigned char split_de_fr_arsc[] = { 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -unsigned int split_de_fr_arsc_len = 984; +unsigned int split_de_fr_arsc_len = 996; diff --git a/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h b/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h new file mode 100644 index 000000000000..e9fb7ea47b75 --- /dev/null +++ b/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h @@ -0,0 +1,68 @@ +unsigned char split_hdpi_v4_arsc[] = { + 0x02, 0x00, 0x0c, 0x00, 0x08, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x1c, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x68, 0x00, + 0x64, 0x00, 0x70, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, + 0xd0, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, + 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, + 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, + 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, + 0x69, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, + 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, + 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00, 0x6f, 0x00, 0x75, 0x00, + 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, + 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00, 0x07, 0x00, 0x69, 0x00, + 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00, 0x79, 0x00, 0x6c, 0x00, + 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00, + 0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6e, 0x00, + 0x73, 0x00, 0x69, 0x00, 0x74, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x02, 0x44, 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +unsigned int split_hdpi_v4_arsc_len = 776; diff --git a/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h b/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h new file mode 100644 index 000000000000..7835f71419f2 --- /dev/null +++ b/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h @@ -0,0 +1,68 @@ +unsigned char split_xhdpi_v4_arsc[] = { + 0x02, 0x00, 0x0c, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x1c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x78, 0x00, + 0x68, 0x00, 0x64, 0x00, 0x70, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x20, 0x01, 0xd0, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, + 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00, + 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00, + 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00, + 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x1c, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, + 0x4c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00, + 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00, + 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, + 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00, + 0x79, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, + 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x1c, 0x00, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x64, 0x00, + 0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x69, 0x00, 0x74, 0x00, 0x79, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +unsigned int split_xhdpi_v4_arsc_len = 780; diff --git a/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h b/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h new file mode 100644 index 000000000000..f805db1b009e --- /dev/null +++ b/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h @@ -0,0 +1,68 @@ +unsigned char split_xxhdpi_v4_arsc[] = { + 0x02, 0x00, 0x0c, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x1c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x78, 0x00, + 0x78, 0x00, 0x68, 0x00, 0x64, 0x00, 0x70, 0x00, 0x69, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x20, 0x01, 0xd0, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, + 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00, + 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00, + 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00, + 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x1c, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, + 0x4c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00, + 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00, + 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, + 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00, + 0x79, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, + 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x1c, 0x00, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x64, 0x00, + 0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x69, 0x00, 0x74, 0x00, 0x79, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +unsigned int split_xxhdpi_v4_arsc_len = 780; diff --git a/libs/androidfw/tests/data/feature/build b/libs/androidfw/tests/data/feature/build index b547dc215595..0f3307f518ec 100755 --- a/libs/androidfw/tests/data/feature/build +++ b/libs/androidfw/tests/data/feature/build @@ -1,4 +1,19 @@ #!/bin/bash +# +# Copyright (C) 2014 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. +# aapt package -M AndroidManifest.xml -S res --feature-of ../basic/bundle.apk -F bundle.apk -f && \ unzip bundle.apk resources.arsc && \ diff --git a/libs/androidfw/tests/data/feature/feature_arsc.h b/libs/androidfw/tests/data/feature/feature_arsc.h index cf7647d71b05..cd299102e8f6 100644 --- a/libs/androidfw/tests/data/feature/feature_arsc.h +++ b/libs/androidfw/tests/data/feature/feature_arsc.h @@ -1,11 +1,11 @@ unsigned char feature_arsc[] = { - 0x02, 0x00, 0x0c, 0x00, 0x40, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x0c, 0x00, 0x44, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x33, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, - 0x34, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xf4, 0x02, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xf8, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, @@ -28,46 +28,46 @@ unsigned char feature_arsc[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x7c, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, - 0x2e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x3c, 0x00, 0x65, 0x00, 0x6d, 0x00, - 0x70, 0x00, 0x74, 0x00, 0x79, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x04, 0x00, - 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, - 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, - 0x00, 0x00, 0x07, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, - 0x67, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, - 0x58, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x33, 0x00, - 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, - 0x34, 0x00, 0x00, 0x00, 0x07, 0x00, 0x6e, 0x00, 0x75, 0x00, 0x6d, 0x00, - 0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x6c, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x3c, 0x00, + 0x65, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x74, 0x00, 0x79, 0x00, 0x3e, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, + 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00, 0x07, 0x00, 0x69, 0x00, 0x6e, 0x00, + 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x1c, 0x00, 0x58, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, + 0x74, 0x00, 0x33, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, + 0x73, 0x00, 0x74, 0x00, 0x34, 0x00, 0x00, 0x00, 0x07, 0x00, 0x6e, 0x00, + 0x75, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x33, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, + 0x6c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, - 0xc8, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x10, 0xc8, 0x00, 0x00, 0x00 }; -unsigned int feature_arsc_len = 832; +unsigned int feature_arsc_len = 836; diff --git a/libs/androidfw/tests/data/feature/res/values/values.xml b/libs/androidfw/tests/data/feature/res/values/values.xml index d03445a33d72..343fd6c8389f 100644 --- a/libs/androidfw/tests/data/feature/res/values/values.xml +++ b/libs/androidfw/tests/data/feature/res/values/values.xml @@ -1,4 +1,19 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + <resources> <string name="test3">test3</string> <string name="test4">test4</string> diff --git a/libs/androidfw/tests/data/lib/R.h b/libs/androidfw/tests/data/lib/R.h index 13bf09528c90..ff311208d61a 100644 --- a/libs/androidfw/tests/data/lib/R.h +++ b/libs/androidfw/tests/data/lib/R.h @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2014 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. + */ + #ifndef __LIB_R_H #define __LIB_R_H diff --git a/libs/androidfw/tests/data/lib/build b/libs/androidfw/tests/data/lib/build index 8e6e70cdc553..41029031028c 100755 --- a/libs/androidfw/tests/data/lib/build +++ b/libs/androidfw/tests/data/lib/build @@ -1,4 +1,19 @@ #!/bin/bash +# +# Copyright (C) 2014 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. +# aapt package -M AndroidManifest.xml -S res -F bundle.apk -f --shared-lib && \ unzip bundle.apk resources.arsc && \ diff --git a/libs/androidfw/tests/data/lib/lib_arsc.h b/libs/androidfw/tests/data/lib/lib_arsc.h index d670c5be18a3..dd3dad5d5f3d 100644 --- a/libs/androidfw/tests/data/lib/lib_arsc.h +++ b/libs/androidfw/tests/data/lib/lib_arsc.h @@ -1,8 +1,8 @@ unsigned char lib_arsc[] = { - 0x02, 0x00, 0x0c, 0x00, 0xc8, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x0c, 0x00, 0xb8, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xa0, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x90, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, @@ -37,48 +37,25 @@ unsigned char lib_arsc[] = { 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x00, 0x00, 0x05, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, - 0x03, 0x02, 0x0c, 0x00, 0x10, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00, - 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00, - 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, - 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x64, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x08, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x64, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00, + 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x08, 0x00, 0x00, 0x10, 0xbc, 0x02, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x10, 0xbc, 0x02, 0x00, 0x00 }; -unsigned int lib_arsc_len = 968; +unsigned int lib_arsc_len = 696; diff --git a/libs/androidfw/tests/data/lib/res/values/values.xml b/libs/androidfw/tests/data/lib/res/values/values.xml index a77f0c79b74b..3ec79b1c7663 100644 --- a/libs/androidfw/tests/data/lib/res/values/values.xml +++ b/libs/androidfw/tests/data/lib/res/values/values.xml @@ -1,4 +1,19 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + <resources> <attr name="attr1" format="integer" /> diff --git a/libs/androidfw/tests/data/overlay/build b/libs/androidfw/tests/data/overlay/build index 87cf6de4c933..f73767749274 100755 --- a/libs/androidfw/tests/data/overlay/build +++ b/libs/androidfw/tests/data/overlay/build @@ -1,4 +1,19 @@ #!/bin/bash +# +# Copyright (C) 2014 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. +# aapt package -M AndroidManifest.xml -S res -F bundle.apk -f && \ unzip bundle.apk resources.arsc && \ diff --git a/libs/androidfw/tests/data/overlay/res/values/values.xml b/libs/androidfw/tests/data/overlay/res/values/values.xml index 227e88973cc7..3e1af9878429 100644 --- a/libs/androidfw/tests/data/overlay/res/values/values.xml +++ b/libs/androidfw/tests/data/overlay/res/values/values.xml @@ -1,4 +1,19 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + <resources> <string name="test2">test2-overlay</string> <integer-array name="integerArray1"> diff --git a/libs/androidfw/tests/data/system/R.h b/libs/androidfw/tests/data/system/R.h index 7a9d3db95586..27f25fec0d01 100644 --- a/libs/androidfw/tests/data/system/R.h +++ b/libs/androidfw/tests/data/system/R.h @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2014 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. + */ + #ifndef __ANDROID_R_H #define __ANDROID_R_H diff --git a/libs/androidfw/tests/data/system/build b/libs/androidfw/tests/data/system/build index 2a3ac0b9f7d4..1a70e84114b0 100755 --- a/libs/androidfw/tests/data/system/build +++ b/libs/androidfw/tests/data/system/build @@ -1,4 +1,19 @@ #!/bin/bash +# +# Copyright (C) 2014 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. +# aapt package -x -M AndroidManifest.xml -S res -F bundle.apk -f && \ unzip bundle.apk resources.arsc && \ diff --git a/libs/androidfw/tests/data/system/res/values/themes.xml b/libs/androidfw/tests/data/system/res/values/themes.xml index b29848efd023..35d43c77fc7a 100644 --- a/libs/androidfw/tests/data/system/res/values/themes.xml +++ b/libs/androidfw/tests/data/system/res/values/themes.xml @@ -1,4 +1,19 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + <resources> <public name="background" type="attr" id="0x01010000"/> <public name="foreground" type="attr" id="0x01010001"/> diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index f0bf7b22ff01..ad50894ee073 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -265,14 +265,27 @@ void Caches::dumpMemoryUsage() { } void Caches::dumpMemoryUsage(String8 &log) { + uint32_t total = 0; log.appendFormat("Current memory usage / total memory usage (bytes):\n"); log.appendFormat(" TextureCache %8d / %8d\n", textureCache.getSize(), textureCache.getMaxSize()); log.appendFormat(" LayerCache %8d / %8d (numLayers = %zu)\n", layerCache.getSize(), layerCache.getMaxSize(), layerCache.getCount()); - log.appendFormat(" Garbage layers %8zu\n", mLayerGarbage.size()); - log.appendFormat(" Active layers %8zu\n", - mRenderState ? mRenderState->mActiveLayers.size() : 0); + if (mRenderState) { + int memused = 0; + for (std::set<const Layer*>::iterator it = mRenderState->mActiveLayers.begin(); + it != mRenderState->mActiveLayers.end(); it++) { + const Layer* layer = *it; + log.appendFormat(" Layer size %dx%d; isTextureLayer()=%d; texid=%u fbo=%u; refs=%d\n", + layer->getWidth(), layer->getHeight(), + layer->isTextureLayer(), layer->getTexture(), + layer->getFbo(), layer->getStrongCount()); + memused = layer->getWidth() * layer->getHeight() * 4; + } + log.appendFormat(" Layers total %8d (numLayers = %zu)\n", + memused, mRenderState->mActiveLayers.size()); + total += memused; + } log.appendFormat(" RenderBufferCache %8d / %8d\n", renderBufferCache.getSize(), renderBufferCache.getMaxSize()); log.appendFormat(" GradientCache %8d / %8d\n", @@ -297,9 +310,7 @@ void Caches::dumpMemoryUsage(String8 &log) { log.appendFormat(" FboCache %8d / %8d\n", fboCache.getSize(), fboCache.getMaxSize()); - uint32_t total = 0; total += textureCache.getSize(); - total += layerCache.getSize(); total += renderBufferCache.getSize(); total += gradientCache.getSize(); total += pathCache.getSize(); @@ -323,27 +334,6 @@ void Caches::clearGarbage() { textureCache.clearGarbage(); pathCache.clearGarbage(); patchCache.clearGarbage(); - - Vector<Layer*> layers; - - { // scope for the lock - Mutex::Autolock _l(mGarbageLock); - layers = mLayerGarbage; - mLayerGarbage.clear(); - } - - size_t count = layers.size(); - for (size_t i = 0; i < count; i++) { - Layer* layer = layers.itemAt(i); - delete layer; - } - layers.clear(); -} - -void Caches::deleteLayerDeferred(Layer* layer) { - Mutex::Autolock _l(mGarbageLock); - layer->state = Layer::kState_InGarbageList; - mLayerGarbage.push(layer); } void Caches::flush(FlushMode mode) { diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp index a998594747d0..fab4a1ae39da 100644 --- a/libs/hwui/DeferredDisplayList.cpp +++ b/libs/hwui/DeferredDisplayList.cpp @@ -525,7 +525,7 @@ void DeferredDisplayList::addDrawOp(OpenGLRenderer& renderer, DrawOp* op) { deferInfo.mergeable &= !recordingComplexClip(); deferInfo.opaqueOverBounds &= !recordingComplexClip() && mSaveStack.isEmpty(); - if (CC_LIKELY(mAvoidOverdraw) && mBatches.size() && + if (mBatches.size() && state->mClipSideFlags != kClipSide_ConservativeFull && deferInfo.opaqueOverBounds && state->mBounds.contains(mBounds)) { // avoid overdraw by resetting drawing state + discarding drawing ops @@ -677,13 +677,12 @@ status_t DeferredDisplayList::flush(OpenGLRenderer& renderer, Rect& dirty) { DrawModifiers restoreDrawModifiers = renderer.getDrawModifiers(); renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); - if (CC_LIKELY(mAvoidOverdraw)) { - for (unsigned int i = 1; i < mBatches.size(); i++) { - if (mBatches[i] && mBatches[i]->coversBounds(mBounds)) { - discardDrawingBatches(i - 1); - } + for (unsigned int i = 1; i < mBatches.size(); i++) { + if (mBatches[i] && mBatches[i]->coversBounds(mBounds)) { + discardDrawingBatches(i - 1); } } + // NOTE: depth of the save stack at this point, before playback, should be reflected in // FLUSH_SAVE_STACK_DEPTH, so that save/restores match up correctly status |= replayBatchList(mBatches, renderer, dirty); diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h index 8a015b21cb47..885b411d3ba2 100644 --- a/libs/hwui/DeferredDisplayList.h +++ b/libs/hwui/DeferredDisplayList.h @@ -81,8 +81,8 @@ public: class DeferredDisplayList { friend class DeferStateStruct; // used to give access to allocator public: - DeferredDisplayList(const Rect& bounds, bool avoidOverdraw = true) : - mBounds(bounds), mAvoidOverdraw(avoidOverdraw) { + DeferredDisplayList(const Rect& bounds) : + mBounds(bounds) { clear(); } ~DeferredDisplayList() { clear(); } @@ -150,7 +150,6 @@ private: // layer space bounds of rendering Rect mBounds; - const bool mAvoidOverdraw; /** * At defer time, stores the *defer time* savecount of save/saveLayer ops that were deferred, so diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp index a6d7e78b87bf..d02455c8fc1d 100644 --- a/libs/hwui/DeferredLayerUpdater.cpp +++ b/libs/hwui/DeferredLayerUpdater.cpp @@ -24,25 +24,6 @@ namespace android { namespace uirenderer { -class DeleteLayerTask : public renderthread::RenderTask { -public: - DeleteLayerTask(renderthread::EglManager& eglManager, Layer* layer) - : mEglManager(eglManager) - , mLayer(layer) - {} - - virtual void run() { - mEglManager.requireGlContext(); - LayerRenderer::destroyLayer(mLayer); - mLayer = 0; - delete this; - } - -private: - renderthread::EglManager& mEglManager; - Layer* mLayer; -}; - DeferredLayerUpdater::DeferredLayerUpdater(renderthread::RenderThread& thread, Layer* layer) : mSurfaceTexture(0) , mTransform(0) @@ -62,7 +43,7 @@ DeferredLayerUpdater::DeferredLayerUpdater(renderthread::RenderThread& thread, L DeferredLayerUpdater::~DeferredLayerUpdater() { SkSafeUnref(mColorFilter); setTransform(0); - mRenderThread.queue(new DeleteLayerTask(mRenderThread.eglManager(), mLayer)); + mLayer->postDecStrong(); mLayer = 0; } diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp index d8932ce4631e..4a927cfc6399 100644 --- a/libs/hwui/DisplayList.cpp +++ b/libs/hwui/DisplayList.cpp @@ -61,10 +61,6 @@ void DisplayListData::cleanupResources() { caches.resourceCache.decrementRefcountLocked(sourcePaths.itemAt(i)); } - for (size_t i = 0; i < layers.size(); i++) { - caches.resourceCache.decrementRefcountLocked(layers.itemAt(i)); - } - caches.resourceCache.unlock(); for (size_t i = 0; i < paints.size(); i++) { @@ -86,7 +82,6 @@ void DisplayListData::cleanupResources() { paints.clear(); regions.clear(); paths.clear(); - layers.clear(); } size_t DisplayListData::addChild(DrawRenderNodeOp* op) { diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h index dea109cd57b7..cb8a8d1cbc88 100644 --- a/libs/hwui/DisplayList.h +++ b/libs/hwui/DisplayList.h @@ -147,7 +147,6 @@ public: Vector<const SkPath*> paths; SortedVector<const SkPath*> sourcePaths; Vector<const SkRegion*> regions; - Vector<Layer*> layers; Vector<Functor*> functors; const Vector<Chunk>& getChunks() const { @@ -157,11 +156,7 @@ public: size_t addChild(DrawRenderNodeOp* childOp); const Vector<DrawRenderNodeOp*>& children() { return mChildren; } - void refProperty(CanvasPropertyPrimitive* prop) { - mReferenceHolders.push(prop); - } - - void refProperty(CanvasPropertyPaint* prop) { + void ref(VirtualLightRefBase* prop) { mReferenceHolders.push(prop); } diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h index cb3ef9b962a1..d78c1cb33f67 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -212,10 +212,13 @@ protected: // check state/paint for transparency if (mPaint) { + if (mPaint->getAlpha() != 0xFF) { + return false; + } if (mPaint->getShader() && !mPaint->getShader()->isOpaque()) { return false; } - if (mPaint->getAlpha() != 0xFF) { + if (Renderer::isBlendedColorFilter(mPaint->getColorFilter())) { return false; } } diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 1f7092147686..c17dd098d4e6 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -189,7 +189,7 @@ status_t DisplayListRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty } status_t DisplayListRenderer::drawLayer(Layer* layer, float x, float y) { - layer = refLayer(layer); + mDisplayListData->ref(layer); addDrawOp(new (alloc()) DrawLayerOp(layer, x, y)); return DrawGlInfo::kStatusDone; } @@ -280,13 +280,13 @@ status_t DisplayListRenderer::drawRoundRect( CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom, CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry, CanvasPropertyPaint* paint) { - mDisplayListData->refProperty(left); - mDisplayListData->refProperty(top); - mDisplayListData->refProperty(right); - mDisplayListData->refProperty(bottom); - mDisplayListData->refProperty(rx); - mDisplayListData->refProperty(ry); - mDisplayListData->refProperty(paint); + mDisplayListData->ref(left); + mDisplayListData->ref(top); + mDisplayListData->ref(right); + mDisplayListData->ref(bottom); + mDisplayListData->ref(rx); + mDisplayListData->ref(ry); + mDisplayListData->ref(paint); addDrawOp(new (alloc()) DrawRoundRectPropsOp(&left->value, &top->value, &right->value, &bottom->value, &rx->value, &ry->value, &paint->value)); return DrawGlInfo::kStatusDone; @@ -300,10 +300,10 @@ status_t DisplayListRenderer::drawCircle(float x, float y, float radius, const S status_t DisplayListRenderer::drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y, CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) { - mDisplayListData->refProperty(x); - mDisplayListData->refProperty(y); - mDisplayListData->refProperty(radius); - mDisplayListData->refProperty(paint); + mDisplayListData->ref(x); + mDisplayListData->ref(y); + mDisplayListData->ref(radius); + mDisplayListData->ref(paint); addDrawOp(new (alloc()) DrawCirclePropsOp(&x->value, &y->value, &radius->value, &paint->value)); return DrawGlInfo::kStatusDone; diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 3a3fc3af9f0f..901e8f02fa7a 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -267,12 +267,6 @@ private: return regionCopy; } - inline Layer* refLayer(Layer* layer) { - mDisplayListData->layers.add(layer); - mCaches.resourceCache.incrementRefcount(layer); - return layer; - } - inline const SkBitmap* refBitmap(const SkBitmap* bitmap) { // Note that this assumes the bitmap is immutable. There are cases this won't handle // correctly, such as creating the bitmap from scratch, drawing with it, changing its diff --git a/libs/hwui/DrawProfiler.cpp b/libs/hwui/DrawProfiler.cpp index 2409554e14b0..e59064294c5e 100644 --- a/libs/hwui/DrawProfiler.cpp +++ b/libs/hwui/DrawProfiler.cpp @@ -22,7 +22,8 @@ #define DEFAULT_MAX_FRAMES 128 -#define RETURN_IF_DISABLED() if (CC_LIKELY(mType == kNone)) return +#define RETURN_IF_PROFILING_DISABLED() if (CC_LIKELY(mType == kNone)) return +#define RETURN_IF_DISABLED() if (CC_LIKELY(mType == kNone && !mShowDirtyRegions)) return #define NANOS_TO_MILLIS_FLOAT(nanos) ((nanos) * 0.000001f) @@ -64,7 +65,9 @@ DrawProfiler::DrawProfiler() , mPreviousTime(0) , mVerticalUnit(0) , mHorizontalUnit(0) - , mThresholdStroke(0) { + , mThresholdStroke(0) + , mShowDirtyRegions(false) + , mFlashToggle(false) { setDensity(1); } @@ -82,27 +85,27 @@ void DrawProfiler::setDensity(float density) { } void DrawProfiler::startFrame(nsecs_t recordDurationNanos) { - RETURN_IF_DISABLED(); + RETURN_IF_PROFILING_DISABLED(); mData[mCurrentFrame].record = NANOS_TO_MILLIS_FLOAT(recordDurationNanos); mPreviousTime = systemTime(CLOCK_MONOTONIC); } void DrawProfiler::markPlaybackStart() { - RETURN_IF_DISABLED(); + RETURN_IF_PROFILING_DISABLED(); nsecs_t now = systemTime(CLOCK_MONOTONIC); mData[mCurrentFrame].prepare = NANOS_TO_MILLIS_FLOAT(now - mPreviousTime); mPreviousTime = now; } void DrawProfiler::markPlaybackEnd() { - RETURN_IF_DISABLED(); + RETURN_IF_PROFILING_DISABLED(); nsecs_t now = systemTime(CLOCK_MONOTONIC); mData[mCurrentFrame].playback = NANOS_TO_MILLIS_FLOAT(now - mPreviousTime); mPreviousTime = now; } void DrawProfiler::finishFrame() { - RETURN_IF_DISABLED(); + RETURN_IF_PROFILING_DISABLED(); nsecs_t now = systemTime(CLOCK_MONOTONIC); mData[mCurrentFrame].swapBuffers = NANOS_TO_MILLIS_FLOAT(now - mPreviousTime); mPreviousTime = now; @@ -114,19 +117,30 @@ void DrawProfiler::unionDirty(SkRect* dirty) { // Not worth worrying about minimizing the dirty region for debugging, so just // dirty the entire viewport. if (dirty) { + mDirtyRegion = *dirty; dirty->setEmpty(); } } void DrawProfiler::draw(OpenGLRenderer* canvas) { - if (CC_LIKELY(mType != kBars)) { - return; + RETURN_IF_DISABLED(); + + if (mShowDirtyRegions) { + mFlashToggle = !mFlashToggle; + if (mFlashToggle) { + SkPaint paint; + paint.setColor(0x7fff0000); + canvas->drawRect(mDirtyRegion.fLeft, mDirtyRegion.fTop, + mDirtyRegion.fRight, mDirtyRegion.fBottom, &paint); + } } - prepareShapes(canvas->getViewportHeight()); - drawGraph(canvas); - drawCurrentFrame(canvas); - drawThreshold(canvas); + if (mType == kBars) { + prepareShapes(canvas->getViewportHeight()); + drawGraph(canvas); + drawCurrentFrame(canvas); + drawThreshold(canvas); + } } void DrawProfiler::createData() { @@ -217,6 +231,7 @@ DrawProfiler::ProfileType DrawProfiler::loadRequestedProfileType() { } bool DrawProfiler::loadSystemProperties() { + bool changed = false; ProfileType newType = loadRequestedProfileType(); if (newType != mType) { mType = newType; @@ -225,13 +240,18 @@ bool DrawProfiler::loadSystemProperties() { } else { createData(); } - return true; + changed = true; } - return false; + bool showDirty = property_get_bool(PROPERTY_DEBUG_SHOW_DIRTY_REGIONS, false); + if (showDirty != mShowDirtyRegions) { + mShowDirtyRegions = showDirty; + changed = true; + } + return changed; } void DrawProfiler::dumpData(int fd) { - RETURN_IF_DISABLED(); + RETURN_IF_PROFILING_DISABLED(); // This method logs the last N frames (where N is <= mDataSize) since the // last call to dumpData(). In other words if there's a dumpData(), draw frame, diff --git a/libs/hwui/DrawProfiler.h b/libs/hwui/DrawProfiler.h index 7c06e5dd111a..de64088bc11f 100644 --- a/libs/hwui/DrawProfiler.h +++ b/libs/hwui/DrawProfiler.h @@ -88,6 +88,10 @@ private: * information. */ float** mRects; + + bool mShowDirtyRegions; + SkRect mDirtyRegion; + bool mFlashToggle; }; } /* namespace uirenderer */ diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp index b5089aa79ff3..b95636bbf7db 100644 --- a/libs/hwui/Layer.cpp +++ b/libs/hwui/Layer.cpp @@ -35,6 +35,9 @@ Layer::Layer(Type layerType, RenderState& renderState, const uint32_t layerWidth , renderState(renderState) , texture(caches) , type(layerType) { + // TODO: This is a violation of Android's typical ref counting, but it + // preserves the old inc/dec ref locations. This should be changed... + incStrong(0); mesh = NULL; meshElementCount = 0; cacheable = true; @@ -53,20 +56,14 @@ Layer::Layer(Type layerType, RenderState& renderState, const uint32_t layerWidth forceFilter = false; deferredList = NULL; convexMask = NULL; - caches.resourceCache.incrementRefcount(this); rendererLightPosDirty = true; wasBuildLayered = false; - if (!isTextureLayer()) { - // track only non-texture layer lifecycles in renderstate, - // because texture layers are destroyed via finalizer - renderState.registerLayer(this); - } + renderState.registerLayer(this); } Layer::~Layer() { - if (!isTextureLayer()) { - renderState.unregisterLayer(this); - } + renderState.requireGLContext(); + renderState.unregisterLayer(this); SkSafeUnref(colorFilter); removeFbo(); deleteTexture(); @@ -292,5 +289,9 @@ void Layer::render(const OpenGLRenderer& rootRenderer) { renderNode = NULL; } +void Layer::postDecStrong() { + renderState.postDecStrong(this); +} + }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index a8e1c2671064..64d1d1226ffb 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -52,7 +52,7 @@ class DeferStateStruct; /** * A layer has dimensions and is backed by an OpenGL texture or FBO. */ -class Layer { +class Layer : public VirtualLightRefBase { public: enum Type { kType_Texture, @@ -280,6 +280,12 @@ public: void render(const OpenGLRenderer& rootRenderer); /** + * Posts a decStrong call to the appropriate thread. + * Thread-safe. + */ + void postDecStrong(); + + /** * Bounds of the layer. */ Rect layer; diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp index 833f64bc96e7..3033dc689c22 100644 --- a/libs/hwui/LayerCache.cpp +++ b/libs/hwui/LayerCache.cpp @@ -84,7 +84,7 @@ void LayerCache::deleteLayer(Layer* layer) { layer->getFbo()); mSize -= layer->getWidth() * layer->getHeight() * 4; layer->state = Layer::kState_DeletedFromCache; - Caches::getInstance().resourceCache.decrementRefcount(layer); + layer->decStrong(0); } } diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index 103c84324627..394c64795aee 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -212,7 +212,7 @@ Layer* LayerRenderer::createRenderLayer(RenderState& renderState, uint32_t width // Creating a new layer always increment its refcount by 1, this allows // us to destroy the layer object if one was created for us - Caches::getInstance().resourceCache.decrementRefcount(layer); + layer->decStrong(0); return NULL; } @@ -240,7 +240,7 @@ Layer* LayerRenderer::createRenderLayer(RenderState& renderState, uint32_t width if (glGetError() != GL_NO_ERROR) { ALOGE("Could not allocate texture for layer (fbo=%d %dx%d)", fbo, width, height); renderState.bindFramebuffer(previousFbo); - caches.resourceCache.decrementRefcount(layer); + layer->decStrong(0); return NULL; } } @@ -316,7 +316,7 @@ void LayerRenderer::destroyLayer(Layer* layer) { if (!Caches::getInstance().layerCache.put(layer)) { LAYER_RENDERER_LOGD(" Destroyed!"); - Caches::getInstance().resourceCache.decrementRefcount(layer); + layer->decStrong(0); } else { LAYER_RENDERER_LOGD(" Cached!"); #if DEBUG_LAYER_RENDERER @@ -328,14 +328,6 @@ void LayerRenderer::destroyLayer(Layer* layer) { } } -void LayerRenderer::destroyLayerDeferred(Layer* layer) { - if (layer) { - LAYER_RENDERER_LOGD("Deferring layer destruction, fbo = %d", layer->getFbo()); - - Caches::getInstance().deleteLayerDeferred(layer); - } -} - void LayerRenderer::flushLayer(RenderState& renderState, Layer* layer) { #ifdef GL_EXT_discard_framebuffer if (!layer) return; diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h index bf7828c3c175..4d8620b8a4ea 100644 --- a/libs/hwui/LayerRenderer.h +++ b/libs/hwui/LayerRenderer.h @@ -60,7 +60,6 @@ public: static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height, bool isOpaque, bool forceFilter, GLenum renderTarget, float* textureTransform); static void destroyLayer(Layer* layer); - ANDROID_API static void destroyLayerDeferred(Layer* layer); static bool copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap); static void flushLayer(RenderState& renderState, Layer* layer); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index ce1d09fe149a..d570b0d5bc9c 100755 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -51,6 +51,21 @@ #define EVENT_LOGD(...) #endif +static void atraceFormatBegin(const char* fmt, ...) { + const int BUFFER_SIZE = 256; + va_list ap; + char buf[BUFFER_SIZE]; + + va_start(ap, fmt); + vsnprintf(buf, BUFFER_SIZE, fmt, ap); + va_end(ap); + + ATRACE_BEGIN(buf); +} + +#define ATRACE_FORMAT_BEGIN(fmt, ...) \ + if (CC_UNLIKELY(ATRACE_ENABLED())) atraceFormatBegin(fmt, ##__VA_ARGS__) + namespace android { namespace uirenderer { @@ -136,7 +151,6 @@ OpenGLRenderer::OpenGLRenderer(RenderState& renderState) , mScissorOptimizationDisabled(false) , mSuppressTiling(false) , mFirstFrameAfterResize(true) - , mCountOverdraw(false) , mLightCenter((Vector3){FLT_MIN, FLT_MIN, FLT_MIN}) , mLightRadius(FLT_MIN) , mAmbientShadowAlpha(0) @@ -251,7 +265,7 @@ void OpenGLRenderer::discardFramebuffer(float left, float top, float right, floa } status_t OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) { - if (!opaque || mCountOverdraw) { + if (!opaque) { mCaches.enableScissor(); mCaches.setScissor(left, getViewportHeight() - bottom, right - left, bottom - top); glClear(GL_COLOR_BUFFER_BIT); @@ -332,10 +346,6 @@ void OpenGLRenderer::finish() { #endif } - if (mCountOverdraw) { - countOverdraw(); - } - mFrameStarted = false; } @@ -449,21 +459,6 @@ void OpenGLRenderer::renderOverdraw() { } } -void OpenGLRenderer::countOverdraw() { - size_t count = getWidth() * getHeight(); - uint32_t* buffer = new uint32_t[count]; - glReadPixels(0, 0, getWidth(), getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, &buffer[0]); - - size_t total = 0; - for (size_t i = 0; i < count; i++) { - total += buffer[i] & 0xff; - } - - mOverdraw = total / float(count); - - delete[] buffer; -} - /////////////////////////////////////////////////////////////////////////////// // Layers /////////////////////////////////////////////////////////////////////////////// @@ -514,11 +509,8 @@ void OpenGLRenderer::updateLayers() { // Note: it is very important to update the layers in order for (int i = 0; i < count; i++) { - Layer* layer = mLayerUpdates.itemAt(i); + Layer* layer = mLayerUpdates.itemAt(i).get(); updateLayer(layer, false); - if (CC_UNLIKELY(mCaches.drawDeferDisabled)) { - mCaches.resourceCache.decrementRefcount(layer); - } } if (CC_UNLIKELY(mCaches.drawDeferDisabled)) { @@ -537,16 +529,15 @@ void OpenGLRenderer::flushLayers() { // Note: it is very important to update the layers in order for (int i = 0; i < count; i++) { + Layer* layer = mLayerUpdates.itemAt(i).get(); + sprintf(layerName, "Layer #%d", i); startMark(layerName); + ATRACE_FORMAT_BEGIN("flushLayer %ux%u", layer->getWidth(), layer->getHeight()); - ATRACE_BEGIN("flushLayer"); - Layer* layer = mLayerUpdates.itemAt(i); layer->flush(); - ATRACE_END(); - - mCaches.resourceCache.decrementRefcount(layer); + ATRACE_END(); endMark(); } @@ -569,7 +560,6 @@ void OpenGLRenderer::pushLayerUpdate(Layer* layer) { } } mLayerUpdates.push_back(layer); - mCaches.resourceCache.incrementRefcount(layer); } } @@ -578,25 +568,12 @@ void OpenGLRenderer::cancelLayerUpdate(Layer* layer) { for (int i = mLayerUpdates.size() - 1; i >= 0; i--) { if (mLayerUpdates.itemAt(i) == layer) { mLayerUpdates.removeAt(i); - mCaches.resourceCache.decrementRefcount(layer); break; } } } } -void OpenGLRenderer::clearLayerUpdates() { - size_t count = mLayerUpdates.size(); - if (count > 0) { - mCaches.resourceCache.lock(); - for (size_t i = 0; i < count; i++) { - mCaches.resourceCache.decrementRefcountLocked(mLayerUpdates.itemAt(i)); - } - mCaches.resourceCache.unlock(); - mLayerUpdates.clear(); - } -} - void OpenGLRenderer::flushLayerUpdates() { ATRACE_CALL(); syncState(); @@ -631,6 +608,7 @@ void OpenGLRenderer::onSnapshotRestored(const Snapshot& removed, const Snapshot& if (restoreLayer) { endMark(); // Savelayer + ATRACE_END(); // SaveLayer startMark("ComposeLayer"); composeLayer(removed, restored); endMark(); @@ -814,6 +792,9 @@ bool OpenGLRenderer::createLayer(float left, float top, float right, float botto mSnapshot->flags |= Snapshot::kFlagIsLayer; mSnapshot->layer = layer; + ATRACE_FORMAT_BEGIN("%ssaveLayer %ux%u", + fboLayer ? "" : "unclipped ", + layer->getWidth(), layer->getHeight()); startMark("SaveLayer"); if (fboLayer) { return createFboLayer(layer, bounds, clip); @@ -956,7 +937,7 @@ void OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& resto layer->setConvexMask(NULL); if (!mCaches.layerCache.put(layer)) { LAYER_LOGD("Deleting layer"); - Caches::getInstance().resourceCache.decrementRefcount(layer); + layer->decStrong(0); } } @@ -1627,8 +1608,6 @@ void OpenGLRenderer::setupDraw(bool clearLayer) { mDescription.hasDebugHighlight = !mCaches.debugOverdraw && mCaches.debugStencilClip == Caches::kStencilShowHighlight && mCaches.stencil.isTestEnabled(); - - mDescription.emulateStencil = mCountOverdraw; } void OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) { @@ -1714,13 +1693,6 @@ void OpenGLRenderer::accountForClear(SkXfermode::Mode mode) { } } -static bool isBlendedColorFilter(const SkColorFilter* filter) { - if (filter == NULL) { - return false; - } - return (filter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag) == 0; -} - void OpenGLRenderer::setupDrawBlending(const Layer* layer, bool swapSrcDst) { SkXfermode::Mode mode = layer->getMode(); // When the blending mode is kClear_Mode, we need to use a modulate color @@ -1967,8 +1939,7 @@ status_t OpenGLRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int return status | replayStruct.mDrawGlStatus; } - bool avoidOverdraw = !mCaches.debugOverdraw && !mCountOverdraw; // shh, don't tell devs! - DeferredDisplayList deferredList(*currentClipRect(), avoidOverdraw); + DeferredDisplayList deferredList(*currentClipRect()); DeferStateStruct deferStruct(deferredList, *this, replayFlags); renderNode->defer(deferStruct, 0); @@ -3440,19 +3411,6 @@ void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode, } mSkipOutlineClip = true; - if (mCountOverdraw) { - if (!mCaches.blend) glEnable(GL_BLEND); - if (mCaches.lastSrcMode != GL_ONE || mCaches.lastDstMode != GL_ONE) { - glBlendFunc(GL_ONE, GL_ONE); - } - - mCaches.blend = true; - mCaches.lastSrcMode = GL_ONE; - mCaches.lastDstMode = GL_ONE; - - return; - } - blend = blend || mode != SkXfermode::kSrcOver_Mode; if (blend) { diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 47ef1a9bb703..e1c3d10fc9c9 100755 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -136,19 +136,10 @@ public: virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque); virtual void finish(); - void setCountOverdrawEnabled(bool enabled) { - mCountOverdraw = enabled; - } - - float getOverdraw() { - return mCountOverdraw ? mOverdraw : 0.0f; - } - virtual status_t callDrawGLFunction(Functor* functor, Rect& dirty); void pushLayerUpdate(Layer* layer); void cancelLayerUpdate(Layer* layer); - void clearLayerUpdates(); void flushLayerUpdates(); void markLayersAsBuildLayers(); @@ -990,7 +981,7 @@ private: // List of rectangles to clear after saveLayer() is invoked Vector<Rect*> mLayers; // List of layers to update at the beginning of a frame - Vector<Layer*> mLayerUpdates; + Vector< sp<Layer> > mLayerUpdates; // The following fields are used to setup drawing // Used to describe the shaders to generate @@ -1015,11 +1006,6 @@ private: bool mSuppressTiling; bool mFirstFrameAfterResize; - // If true, this renderer will setup drawing to emulate - // an increment stencil buffer in the color buffer - bool mCountOverdraw; - float mOverdraw; - bool mSkipOutlineClip; // Lighting + shadows diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h index 56773f44f9b5..d05b331909e2 100644 --- a/libs/hwui/Program.h +++ b/libs/hwui/Program.h @@ -84,8 +84,7 @@ namespace uirenderer { #define PROGRAM_HAS_COLORS 42 #define PROGRAM_HAS_DEBUG_HIGHLIGHT 43 -#define PROGRAM_EMULATE_STENCIL 44 -#define PROGRAM_HAS_ROUND_RECT_CLIP 45 +#define PROGRAM_HAS_ROUND_RECT_CLIP 44 /////////////////////////////////////////////////////////////////////////////// // Types @@ -161,7 +160,6 @@ struct ProgramDescription { float gamma; bool hasDebugHighlight; - bool emulateStencil; bool hasRoundRectClip; /** @@ -204,7 +202,6 @@ struct ProgramDescription { gamma = 2.2f; hasDebugHighlight = false; - emulateStencil = false; hasRoundRectClip = false; } @@ -272,7 +269,6 @@ struct ProgramDescription { if (isSimpleGradient) key |= programid(0x1) << PROGRAM_IS_SIMPLE_GRADIENT; if (hasColors) key |= programid(0x1) << PROGRAM_HAS_COLORS; if (hasDebugHighlight) key |= programid(0x1) << PROGRAM_HAS_DEBUG_HIGHLIGHT; - if (emulateStencil) key |= programid(0x1) << PROGRAM_EMULATE_STENCIL; if (hasRoundRectClip) key |= programid(0x1) << PROGRAM_HAS_ROUND_RECT_CLIP; return key; } diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index 06353c096adc..62835e01cb3a 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -347,12 +347,6 @@ const char* gFS_Main_FragColor_HasRoundRectClip = const char* gFS_Main_DebugHighlight = " gl_FragColor.rgb = vec3(0.0, gl_FragColor.a, 0.0);\n"; -const char* gFS_Main_EmulateStencil = - " gl_FragColor.rgba = vec4(1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0, 1.0);\n" - " return;\n" - " /*\n"; -const char* gFS_Footer_EmulateStencil = - " */\n"; const char* gFS_Footer = "}\n\n"; @@ -617,7 +611,6 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti && !description.hasColors && description.colorOp == ProgramDescription::kColorNone && !description.hasDebugHighlight - && !description.emulateStencil && !description.hasRoundRectClip) { bool fast = false; @@ -698,9 +691,6 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti // Begin the shader shader.append(gFS_Main); { - if (description.emulateStencil) { - shader.append(gFS_Main_EmulateStencil); - } // Stores the result in fragColor directly if (description.hasTexture || description.hasExternalTexture) { if (description.hasAlpha8Texture) { @@ -779,9 +769,6 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.append(gFS_Main_DebugHighlight); } } - if (description.emulateStencil) { - shader.append(gFS_Footer_EmulateStencil); - } // End the shader shader.append(gFS_Footer); diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 7eb9a32843e1..befed16a1c9f 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -133,6 +133,15 @@ enum DebugLevel { #define PROPERTY_DEBUG_STENCIL_CLIP "debug.hwui.show_non_rect_clip" /** + * Turn on to draw dirty regions every other frame. + * + * Possible values: + * "true", to enable dirty regions debugging + * "false", to disable dirty regions debugging + */ +#define PROPERTY_DEBUG_SHOW_DIRTY_REGIONS "debug.hwui.show_dirty_regions" + +/** * Disables draw operation deferral if set to "true", forcing draw * commands to be issued to OpenGL in order, and processed in sequence * with state-manipulation canvas commands. diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 254492ff4384..c9ed9a7d780b 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -50,10 +50,13 @@ void RenderNode::outputLogBuffer(int fd) { fprintf(file, "\nRecent DisplayList operations\n"); logBuffer.outputCommands(file); - String8 cachesLog; - Caches::getInstance().dumpMemoryUsage(cachesLog); - fprintf(file, "\nCaches:\n%s", cachesLog.string()); - fprintf(file, "\n"); + if (Caches::hasInstance()) { + String8 cachesLog; + Caches::getInstance().dumpMemoryUsage(cachesLog); + fprintf(file, "\nCaches:\n%s\n", cachesLog.string()); + } else { + fprintf(file, "\nNo caches instance.\n"); + } fflush(file); } @@ -84,7 +87,11 @@ RenderNode::RenderNode() RenderNode::~RenderNode() { deleteDisplayListData(); delete mStagingDisplayListData; - LayerRenderer::destroyLayerDeferred(mLayer); + if (mLayer) { + ALOGW("Memory Warning: Layer %p missed its detachment, held on to for far too long!", mLayer); + mLayer->postDecStrong(); + mLayer = 0; + } } void RenderNode::setStagingDisplayList(DisplayListData* data) { @@ -198,6 +205,7 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { info.damageAccumulator->peekAtDirty(&dirty); if (!mLayer) { + Caches::getInstance().dumpMemoryUsage(); if (info.errorHandler) { std::string msg = "Unable to create layer for "; msg += getName(); @@ -293,6 +301,9 @@ void RenderNode::pushStagingDisplayListChanges(TreeInfo& info) { mStagingDisplayListData->children()[i]->mRenderNode->incParentRefCount(); } } + // Damage with the old display list first then the new one to catch any + // changes in isRenderable or, in the future, bounds + damageSelf(info); deleteDisplayListData(); mDisplayListData = mStagingDisplayListData; mStagingDisplayListData = NULL; diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h index f32928301fc4..2ce7cb7f3034 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -101,7 +101,7 @@ public: kReplayFlag_ClipChildren = 0x1 }; - ANDROID_API static void outputLogBuffer(int fd); + static void outputLogBuffer(int fd); void debugDumpLayers(const char* prefix); ANDROID_API void setStagingDisplayList(DisplayListData* newData); diff --git a/libs/hwui/RenderState.cpp b/libs/hwui/RenderState.cpp index 86bd7dd00ccd..a8cf26f0d5da 100644 --- a/libs/hwui/RenderState.cpp +++ b/libs/hwui/RenderState.cpp @@ -16,15 +16,18 @@ #include "RenderState.h" #include "renderthread/CanvasContext.h" +#include "renderthread/EglManager.h" namespace android { namespace uirenderer { -RenderState::RenderState() - : mCaches(NULL) +RenderState::RenderState(renderthread::RenderThread& thread) + : mRenderThread(thread) + , mCaches(NULL) , mViewportWidth(0) , mViewportHeight(0) , mFramebuffer(0) { + mThreadId = pthread_self(); } RenderState::~RenderState() { @@ -39,7 +42,6 @@ void RenderState::onGLContextCreated() { void RenderState::onGLContextDestroyed() { /* - AutoMutex _lock(mLayerLock); size_t size = mActiveLayers.size(); if (CC_UNLIKELY(size != 0)) { ALOGE("Crashing, have %d contexts and %d layers at context destruction. isempty %d", @@ -146,5 +148,34 @@ void RenderState::debugOverdraw(bool enable, bool clear) { } } +void RenderState::requireGLContext() { + assertOnGLThread(); + mRenderThread.eglManager().requireGlContext(); +} + +void RenderState::assertOnGLThread() { + pthread_t curr = pthread_self(); + LOG_ALWAYS_FATAL_IF(!pthread_equal(mThreadId, curr), "Wrong thread!"); +} + + +class DecStrongTask : public renderthread::RenderTask { +public: + DecStrongTask(VirtualLightRefBase* object) : mObject(object) {} + + virtual void run() { + mObject->decStrong(0); + mObject = 0; + delete this; + } + +private: + VirtualLightRefBase* mObject; +}; + +void RenderState::postDecStrong(VirtualLightRefBase* object) { + mRenderThread.queue(new DecStrongTask(object)); +} + } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/RenderState.h b/libs/hwui/RenderState.h index cbe7cfc3db4e..afeef950d5cd 100644 --- a/libs/hwui/RenderState.h +++ b/libs/hwui/RenderState.h @@ -53,16 +53,10 @@ public: void debugOverdraw(bool enable, bool clear); void registerLayer(const Layer* layer) { - /* - AutoMutex _lock(mLayerLock); mActiveLayers.insert(layer); - */ } void unregisterLayer(const Layer* layer) { - /* - AutoMutex _lock(mLayerLock); mActiveLayers.erase(layer); - */ } void registerCanvasContext(renderthread::CanvasContext* context) { @@ -73,16 +67,24 @@ public: mRegisteredContexts.erase(context); } + void requireGLContext(); + + // TODO: This system is a little clunky feeling, this could use some + // more thinking... + void postDecStrong(VirtualLightRefBase* object); + private: friend class renderthread::RenderThread; friend class Caches; void interruptForFunctorInvoke(); void resumeFromFunctorInvoke(); + void assertOnGLThread(); - RenderState(); + RenderState(renderthread::RenderThread& thread); ~RenderState(); + renderthread::RenderThread& mRenderThread; Caches* mCaches; std::set<const Layer*> mActiveLayers; std::set<renderthread::CanvasContext*> mRegisteredContexts; @@ -90,7 +92,8 @@ private: GLsizei mViewportWidth; GLsizei mViewportHeight; GLuint mFramebuffer; - Mutex mLayerLock; + + pthread_t mThreadId; }; } /* namespace uirenderer */ diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h index 9cedd5aa108b..a2f8c0585144 100644 --- a/libs/hwui/Renderer.h +++ b/libs/hwui/Renderer.h @@ -17,12 +17,13 @@ #ifndef ANDROID_HWUI_RENDERER_H #define ANDROID_HWUI_RENDERER_H +#include <SkColorFilter.h> +#include <SkPaint.h> #include <SkRegion.h> #include <utils/String8.h> #include "AssetAtlas.h" -#include "SkPaint.h" namespace android { @@ -81,6 +82,14 @@ public: && !paint.getColorFilter() && getXfermode(paint.getXfermode()) == SkXfermode::kSrcOver_Mode; } + + static bool isBlendedColorFilter(const SkColorFilter* filter) { + if (filter == NULL) { + return false; + } + return (filter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag) == 0; + } + // ---------------------------------------------------------------------------- // Frame state operations // ---------------------------------------------------------------------------- diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp index 8b553d1383d4..329d92f0be13 100644 --- a/libs/hwui/ResourceCache.cpp +++ b/libs/hwui/ResourceCache.cpp @@ -75,10 +75,6 @@ void ResourceCache::incrementRefcount(const Res_png_9patch* patchResource) { incrementRefcount((void*) patchResource, kNinePatch); } -void ResourceCache::incrementRefcount(Layer* layerResource) { - incrementRefcount((void*) layerResource, kLayer); -} - void ResourceCache::incrementRefcountLocked(void* resource, ResourceType resourceType) { ssize_t index = mCache->indexOfKey(resource); ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL; @@ -103,10 +99,6 @@ void ResourceCache::incrementRefcountLocked(const Res_png_9patch* patchResource) incrementRefcountLocked((void*) patchResource, kNinePatch); } -void ResourceCache::incrementRefcountLocked(Layer* layerResource) { - incrementRefcountLocked((void*) layerResource, kLayer); -} - void ResourceCache::decrementRefcount(void* resource) { Mutex::Autolock _l(mLock); decrementRefcountLocked(resource); @@ -126,10 +118,6 @@ void ResourceCache::decrementRefcount(const Res_png_9patch* patchResource) { decrementRefcount((void*) patchResource); } -void ResourceCache::decrementRefcount(Layer* layerResource) { - decrementRefcount((void*) layerResource); -} - void ResourceCache::decrementRefcountLocked(void* resource) { ssize_t index = mCache->indexOfKey(resource); ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL; @@ -157,10 +145,6 @@ void ResourceCache::decrementRefcountLocked(const Res_png_9patch* patchResource) decrementRefcountLocked((void*) patchResource); } -void ResourceCache::decrementRefcountLocked(Layer* layerResource) { - decrementRefcountLocked((void*) layerResource); -} - void ResourceCache::destructor(SkPath* resource) { Mutex::Autolock _l(mLock); destructorLocked(resource); @@ -274,7 +258,7 @@ void ResourceCache::deleteResourceReferenceLocked(const void* resource, Resource if (ref->recycled && ref->resourceType == kBitmap) { ((SkBitmap*) resource)->setPixels(NULL, NULL); } - if (ref->destroyed || ref->resourceType == kLayer) { + if (ref->destroyed) { switch (ref->resourceType) { case kBitmap: { SkBitmap* bitmap = (SkBitmap*) resource; @@ -305,11 +289,6 @@ void ResourceCache::deleteResourceReferenceLocked(const void* resource, Resource } } break; - case kLayer: { - Layer* layer = (Layer*) resource; - Caches::getInstance().deleteLayerDeferred(layer); - } - break; } } mCache->removeItem(resource); diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h index 3864d4bf2a7d..8539d123b09a 100644 --- a/libs/hwui/ResourceCache.h +++ b/libs/hwui/ResourceCache.h @@ -36,8 +36,7 @@ namespace uirenderer { enum ResourceType { kBitmap, kNinePatch, - kPath, - kLayer + kPath }; class ResourceReference { @@ -69,22 +68,18 @@ public: void incrementRefcount(const SkPath* resource); void incrementRefcount(const SkBitmap* resource); void incrementRefcount(const Res_png_9patch* resource); - void incrementRefcount(Layer* resource); void incrementRefcountLocked(const SkPath* resource); void incrementRefcountLocked(const SkBitmap* resource); void incrementRefcountLocked(const Res_png_9patch* resource); - void incrementRefcountLocked(Layer* resource); void decrementRefcount(const SkBitmap* resource); void decrementRefcount(const SkPath* resource); void decrementRefcount(const Res_png_9patch* resource); - void decrementRefcount(Layer* resource); void decrementRefcountLocked(const SkBitmap* resource); void decrementRefcountLocked(const SkPath* resource); void decrementRefcountLocked(const Res_png_9patch* resource); - void decrementRefcountLocked(Layer* resource); void destructor(SkPath* resource); void destructor(const SkBitmap* resource); diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp index dbedf94a1a83..df28ae8b90ed 100644 --- a/libs/hwui/SpotShadow.cpp +++ b/libs/hwui/SpotShadow.cpp @@ -60,7 +60,7 @@ namespace android { namespace uirenderer { -static const double EPSILON = 1e-7; +static const float EPSILON = 1e-7; /** * For each polygon's vertex, the light center will project it to the receiver @@ -118,17 +118,17 @@ static float rayIntersectPoints(const Vector2& rayOrigin, float dx, float dy, // intersection point should stay on both the ray and the edge of (p1, p2). // solve([p1x+t*(p2x-p1x)=dx*t2+px,p1y+t*(p2y-p1y)=dy*t2+py],[t,t2]); - double divisor = (dx * (p1.y - p2.y) + dy * p2.x - dy * p1.x); + float divisor = (dx * (p1.y - p2.y) + dy * p2.x - dy * p1.x); if (divisor == 0) return -1.0f; // error, invalid divisor #if DEBUG_SHADOW - double interpVal = (dx * (p1.y - rayOrigin.y) + dy * rayOrigin.x - dy * p1.x) / divisor; + float interpVal = (dx * (p1.y - rayOrigin.y) + dy * rayOrigin.x - dy * p1.x) / divisor; if (interpVal < 0 || interpVal > 1) { ALOGW("rayIntersectPoints is hitting outside the segment %f", interpVal); } #endif - double distance = (p1.x * (rayOrigin.y - p2.y) + p2.x * (p1.y - rayOrigin.y) + + float distance = (p1.x * (rayOrigin.y - p2.y) + p2.x * (p1.y - rayOrigin.y) + rayOrigin.x * (p2.y - p1.y)) / divisor; return distance; // may be negative in error cases @@ -217,146 +217,12 @@ int SpotShadow::hull(Vector2* points, int pointsLength, Vector2* retPoly) { * * @return true if a right hand turn */ -bool SpotShadow::ccw(double ax, double ay, double bx, double by, - double cx, double cy) { +bool SpotShadow::ccw(float ax, float ay, float bx, float by, + float cx, float cy) { return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax) > EPSILON; } /** - * Calculates the intersection of poly1 with poly2 and put in poly2. - * Note that both poly1 and poly2 must be in CW order already! - * - * @param poly1 The 1st polygon, as a Vector2 array. - * @param poly1Length The number of vertices of 1st polygon. - * @param poly2 The 2nd and output polygon, as a Vector2 array. - * @param poly2Length The number of vertices of 2nd polygon. - * @return number of vertices in output polygon as poly2. - */ -int SpotShadow::intersection(const Vector2* poly1, int poly1Length, - Vector2* poly2, int poly2Length) { -#if DEBUG_SHADOW - if (!ShadowTessellator::isClockwise(poly1, poly1Length)) { - ALOGW("Poly1 is not clockwise! Intersection is wrong!"); - } - if (!ShadowTessellator::isClockwise(poly2, poly2Length)) { - ALOGW("Poly2 is not clockwise! Intersection is wrong!"); - } -#endif - Vector2 poly[poly1Length * poly2Length + 2]; - int count = 0; - int pcount = 0; - - // If one vertex from one polygon sits inside another polygon, add it and - // count them. - for (int i = 0; i < poly1Length; i++) { - if (testPointInsidePolygon(poly1[i], poly2, poly2Length)) { - poly[count] = poly1[i]; - count++; - pcount++; - - } - } - - int insidePoly2 = pcount; - for (int i = 0; i < poly2Length; i++) { - if (testPointInsidePolygon(poly2[i], poly1, poly1Length)) { - poly[count] = poly2[i]; - count++; - } - } - - int insidePoly1 = count - insidePoly2; - // If all vertices from poly1 are inside poly2, then just return poly1. - if (insidePoly2 == poly1Length) { - memcpy(poly2, poly1, poly1Length * sizeof(Vector2)); - return poly1Length; - } - - // If all vertices from poly2 are inside poly1, then just return poly2. - if (insidePoly1 == poly2Length) { - return poly2Length; - } - - // Since neither polygon fully contain the other one, we need to add all the - // intersection points. - Vector2 intersection = {0, 0}; - for (int i = 0; i < poly2Length; i++) { - for (int j = 0; j < poly1Length; j++) { - int poly2LineStart = i; - int poly2LineEnd = ((i + 1) % poly2Length); - int poly1LineStart = j; - int poly1LineEnd = ((j + 1) % poly1Length); - bool found = lineIntersection( - poly2[poly2LineStart].x, poly2[poly2LineStart].y, - poly2[poly2LineEnd].x, poly2[poly2LineEnd].y, - poly1[poly1LineStart].x, poly1[poly1LineStart].y, - poly1[poly1LineEnd].x, poly1[poly1LineEnd].y, - intersection); - if (found) { - poly[count].x = intersection.x; - poly[count].y = intersection.y; - count++; - } else { - Vector2 delta = poly2[i] - poly1[j]; - if (delta.lengthSquared() < EPSILON) { - poly[count] = poly2[i]; - count++; - } - } - } - } - - if (count == 0) { - return 0; - } - - // Sort the result polygon around the center. - Vector2 center = {0.0f, 0.0f}; - for (int i = 0; i < count; i++) { - center += poly[i]; - } - center /= count; - sort(poly, count, center); - -#if DEBUG_SHADOW - // Since poly2 is overwritten as the result, we need to save a copy to do - // our verification. - Vector2 oldPoly2[poly2Length]; - int oldPoly2Length = poly2Length; - memcpy(oldPoly2, poly2, sizeof(Vector2) * poly2Length); -#endif - - // Filter the result out from poly and put it into poly2. - poly2[0] = poly[0]; - int lastOutputIndex = 0; - for (int i = 1; i < count; i++) { - Vector2 delta = poly[i] - poly2[lastOutputIndex]; - if (delta.lengthSquared() >= EPSILON) { - poly2[++lastOutputIndex] = poly[i]; - } else { - // If the vertices are too close, pick the inner one, because the - // inner one is more likely to be an intersection point. - Vector2 delta1 = poly[i] - center; - Vector2 delta2 = poly2[lastOutputIndex] - center; - if (delta1.lengthSquared() < delta2.lengthSquared()) { - poly2[lastOutputIndex] = poly[i]; - } - } - } - int resultLength = lastOutputIndex + 1; - -#if DEBUG_SHADOW - testConvex(poly2, resultLength, "intersection"); - testConvex(poly1, poly1Length, "input poly1"); - testConvex(oldPoly2, oldPoly2Length, "input poly2"); - - testIntersection(poly1, poly1Length, oldPoly2, oldPoly2Length, poly2, resultLength); -#endif - - return resultLength; -} - -/** * Sort points about a center point * * @param poly The in and out polyogon as a Vector2 array. @@ -441,13 +307,13 @@ void SpotShadow::quicksortX(Vector2* points, int low, int high) { bool SpotShadow::testPointInsidePolygon(const Vector2 testPoint, const Vector2* poly, int len) { bool c = false; - double testx = testPoint.x; - double testy = testPoint.y; + float testx = testPoint.x; + float testy = testPoint.y; for (int i = 0, j = len - 1; i < len; j = i++) { - double startX = poly[j].x; - double startY = poly[j].y; - double endX = poly[i].x; - double endY = poly[i].y; + float startX = poly[j].x; + float startY = poly[j].y; + float endX = poly[i].x; + float endY = poly[i].y; if (((endY > testy) != (startY > testy)) && (testx < (startX - endX) * (testy - endY) @@ -490,46 +356,6 @@ void SpotShadow::reverse(Vector2* polygon, int len) { } /** - * Intersects two lines in parametric form. This function is called in a tight - * loop, and we need double precision to get things right. - * - * @param x1 the x coordinate point 1 of line 1 - * @param y1 the y coordinate point 1 of line 1 - * @param x2 the x coordinate point 2 of line 1 - * @param y2 the y coordinate point 2 of line 1 - * @param x3 the x coordinate point 1 of line 2 - * @param y3 the y coordinate point 1 of line 2 - * @param x4 the x coordinate point 2 of line 2 - * @param y4 the y coordinate point 2 of line 2 - * @param ret the x,y location of the intersection - * @return true if it found an intersection - */ -inline bool SpotShadow::lineIntersection(double x1, double y1, double x2, double y2, - double x3, double y3, double x4, double y4, Vector2& ret) { - double d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); - if (d == 0.0) return false; - - double dx = (x1 * y2 - y1 * x2); - double dy = (x3 * y4 - y3 * x4); - double x = (dx * (x3 - x4) - (x1 - x2) * dy) / d; - double y = (dx * (y3 - y4) - (y1 - y2) * dy) / d; - - // The intersection should be in the middle of the point 1 and point 2, - // likewise point 3 and point 4. - if (((x - x1) * (x - x2) > EPSILON) - || ((x - x3) * (x - x4) > EPSILON) - || ((y - y1) * (y - y2) > EPSILON) - || ((y - y3) * (y - y4) > EPSILON)) { - // Not interesected - return false; - } - ret.x = x; - ret.y = y; - return true; - -} - -/** * Compute a horizontal circular polygon about point (x , y , height) of radius * (size) * @@ -542,7 +368,7 @@ void SpotShadow::computeLightPolygon(int points, const Vector3& lightCenter, float size, Vector3* ret) { // TODO: Caching all the sin / cos values and store them in a look up table. for (int i = 0; i < points; i++) { - double angle = 2 * i * M_PI / points; + float angle = 2 * i * M_PI / points; ret[i].x = cosf(angle) * size + lightCenter.x; ret[i].y = sinf(angle) * size + lightCenter.y; ret[i].z = lightCenter.z; @@ -853,21 +679,6 @@ bool convertPolyToRayDist(const Vector2* poly, int polyLength, const Vector2& po return true; } -int SpotShadow::calculateOccludedUmbra(const Vector2* umbra, int umbraLength, - const Vector3* poly, int polyLength, Vector2* occludedUmbra) { - // Occluded umbra area is computed as the intersection of the projected 2D - // poly and umbra. - for (int i = 0; i < polyLength; i++) { - occludedUmbra[i].x = poly[i].x; - occludedUmbra[i].y = poly[i].y; - } - - // Both umbra and incoming polygon are guaranteed to be CW, so we can call - // intersection() directly. - return intersection(umbra, umbraLength, - occludedUmbra, polyLength); -} - /** * This is only for experimental purpose. * After intersections are calculated, we could smooth the polygon if needed. @@ -1585,8 +1396,8 @@ bool SpotShadow::testConvex(const Vector2* polygon, int polygonLength, Vector2 middle = polygon[(i + 1) % polygonLength]; Vector2 end = polygon[(i + 2) % polygonLength]; - double delta = (double(middle.x) - start.x) * (double(end.y) - start.y) - - (double(middle.y) - start.y) * (double(end.x) - start.x); + float delta = (float(middle.x) - start.x) * (float(end.y) - start.y) - + (float(middle.y) - start.y) * (float(end.x) - start.x); bool isCCWOrCoLinear = (delta >= EPSILON); if (isCCWOrCoLinear) { @@ -1621,8 +1432,8 @@ void SpotShadow::testIntersection(const Vector2* poly1, int poly1Length, bool dumpPoly = false; for (int k = 0; k < TEST_POINT_NUMBER; k++) { // Generate a random point between minX, minY and maxX, maxY. - double randomX = rand() / double(RAND_MAX); - double randomY = rand() / double(RAND_MAX); + float randomX = rand() / float(RAND_MAX); + float randomY = rand() / float(RAND_MAX); Vector2 testPoint; testPoint.x = lowerBound.x + randomX * (upperBound.x - lowerBound.x); diff --git a/libs/hwui/SpotShadow.h b/libs/hwui/SpotShadow.h index 23fdca9d7fa9..6fa2028fd6d0 100644 --- a/libs/hwui/SpotShadow.h +++ b/libs/hwui/SpotShadow.h @@ -35,8 +35,6 @@ private: static float projectCasterToOutline(Vector2& outline, const Vector3& lightCenter, const Vector3& polyVertex); - static int calculateOccludedUmbra(const Vector2* umbra, int umbraLength, - const Vector3* poly, int polyLength, Vector2* occludedUmbra); static int setupAngleList(VertexAngleData* angleDataList, int polyLength, const Vector2* polygon, const Vector2& centroid, @@ -81,8 +79,7 @@ private: static void xsort(Vector2* points, int pointsLength); static int hull(Vector2* points, int pointsLength, Vector2* retPoly); - static bool ccw(double ax, double ay, double bx, double by, double cx, double cy); - static int intersection(const Vector2* poly1, int poly1length, Vector2* poly2, int poly2length); + static bool ccw(float ax, float ay, float bx, float by, float cx, float cy); static void sort(Vector2* poly, int polyLength, const Vector2& center); static void swap(Vector2* points, int i, int j); @@ -92,8 +89,6 @@ private: static bool testPointInsidePolygon(const Vector2 testPoint, const Vector2* poly, int len); static void makeClockwise(Vector2* polygon, int len); static void reverse(Vector2* polygon, int len); - static inline bool lineIntersection(double x1, double y1, double x2, double y2, - double x3, double y3, double x4, double y4, Vector2& ret); static void generateTriangleStrip(bool isCasterOpaque, float shadowStrengthScale, Vector2* penumbra, int penumbraLength, Vector2* umbra, int umbraLength, diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index b50a43378599..b499dd086312 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -42,7 +42,8 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent, : mRenderThread(thread) , mEglManager(thread.eglManager()) , mEglSurface(EGL_NO_SURFACE) - , mDirtyRegionsEnabled(false) + , mBufferPreserved(false) + , mSwapBehavior(kSwap_default) , mOpaque(!translucent) , mCanvas(NULL) , mHaveNewSurface(false) @@ -82,7 +83,8 @@ void CanvasContext::setSurface(ANativeWindow* window) { } if (mEglSurface != EGL_NO_SURFACE) { - mDirtyRegionsEnabled = mEglManager.enableDirtyRegions(mEglSurface); + const bool preserveBuffer = (mSwapBehavior != kSwap_discardBuffer); + mBufferPreserved = mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer); mHaveNewSurface = true; makeCurrent(); } else { @@ -103,6 +105,10 @@ void CanvasContext::requireSurface() { makeCurrent(); } +void CanvasContext::setSwapBehavior(SwapBehavior swapBehavior) { + mSwapBehavior = swapBehavior; +} + bool CanvasContext::initialize(ANativeWindow* window) { setSurface(window); if (mCanvas) return false; @@ -200,7 +206,7 @@ void CanvasContext::draw() { if (width != mCanvas->getViewportWidth() || height != mCanvas->getViewportHeight()) { mCanvas->setViewport(width, height); dirty.setEmpty(); - } else if (!mDirtyRegionsEnabled || mHaveNewSurface) { + } else if (!mBufferPreserved || mHaveNewSurface) { dirty.setEmpty(); } else { if (!dirty.isEmpty() && !dirty.intersect(0, 0, width, height)) { @@ -230,6 +236,8 @@ void CanvasContext::draw() { if (status & DrawGlInfo::kStatusDrew) { swapBuffers(); + } else { + mEglManager.cancelFrame(); } profiler().finishFrame(); @@ -330,6 +338,7 @@ void CanvasContext::trimMemory(RenderThread& thread, int level) { // No context means nothing to free if (!thread.eglManager().hasEglContext()) return; + ATRACE_CALL(); thread.eglManager().requireGlContext(); if (level >= TRIM_MEMORY_COMPLETE) { Caches::getInstance().flush(Caches::kFlushMode_Full); diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index d4282fada940..e20564b26124 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -48,6 +48,11 @@ namespace renderthread { class EglManager; +enum SwapBehavior { + kSwap_default, + kSwap_discardBuffer, +}; + // This per-renderer class manages the bridge between the global EGL context // and the render surface. // TODO: Rename to Renderer or some other per-window, top-level manager @@ -57,6 +62,9 @@ public: IContextFactory* contextFactory); virtual ~CanvasContext(); + // Won't take effect until next EGLSurface creation + void setSwapBehavior(SwapBehavior swapBehavior); + bool initialize(ANativeWindow* window); void updateSurface(ANativeWindow* window); void pauseSurface(ANativeWindow* window); @@ -111,7 +119,8 @@ private: EglManager& mEglManager; sp<ANativeWindow> mNativeWindow; EGLSurface mEglSurface; - bool mDirtyRegionsEnabled; + bool mBufferPreserved; + SwapBehavior mSwapBehavior; bool mOpaque; OpenGLRenderer* mCanvas; diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp index a87834ee0c63..9bd6f41a9614 100644 --- a/libs/hwui/renderthread/EglManager.cpp +++ b/libs/hwui/renderthread/EglManager.cpp @@ -70,12 +70,13 @@ EglManager::EglManager(RenderThread& thread) , mEglConfig(0) , mEglContext(EGL_NO_CONTEXT) , mPBufferSurface(EGL_NO_SURFACE) - , mRequestDirtyRegions(load_dirty_regions_property()) + , mAllowPreserveBuffer(load_dirty_regions_property()) , mCurrentSurface(EGL_NO_SURFACE) , mAtlasMap(NULL) - , mAtlasMapSize(0) { - mCanSetDirtyRegions = mRequestDirtyRegions; - ALOGD("Render dirty regions requested: %s", mRequestDirtyRegions ? "true" : "false"); + , mAtlasMapSize(0) + , mInFrame(false) { + mCanSetPreserveBuffer = mAllowPreserveBuffer; + ALOGD("Use EGL_SWAP_BEHAVIOR_PRESERVED: %s", mAllowPreserveBuffer ? "true" : "false"); } void EglManager::initialize() { @@ -105,15 +106,16 @@ bool EglManager::hasEglContext() { void EglManager::requireGlContext() { LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, "No EGL context"); - // We don't care *WHAT* surface is active, just that one is active to give - // us access to the GL context - if (mCurrentSurface == EGL_NO_SURFACE) { + if (!mInFrame) { + // We can't be certain about the state of the current surface (whether + // or not it is destroyed, for example), so err on the side of using + // the pbuffer surface which we fully control usePBufferSurface(); } } void EglManager::loadConfig() { - EGLint swapBehavior = mCanSetDirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0; + EGLint swapBehavior = mCanSetPreserveBuffer ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0; EGLint attribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_RED_SIZE, 8, @@ -131,10 +133,10 @@ void EglManager::loadConfig() { if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, num_configs, &num_configs) || num_configs != 1) { // Failed to get a valid config - if (mCanSetDirtyRegions) { + if (mCanSetPreserveBuffer) { ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without..."); // Try again without dirty regions enabled - mCanSetDirtyRegions = false; + mCanSetPreserveBuffer = false; loadConfig(); } else { LOG_ALWAYS_FATAL("Failed to choose config, error = %s", egl_error_str()); @@ -252,9 +254,11 @@ void EglManager::beginFrame(EGLSurface surface, EGLint* width, EGLint* height) { eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height); } eglBeginFrame(mEglDisplay, surface); + mInFrame = true; } bool EglManager::swapBuffers(EGLSurface surface) { + mInFrame = false; eglSwapBuffers(mEglDisplay, surface); EGLint err = eglGetError(); if (CC_LIKELY(err == EGL_SUCCESS)) { @@ -273,25 +277,34 @@ bool EglManager::swapBuffers(EGLSurface surface) { return false; } -bool EglManager::enableDirtyRegions(EGLSurface surface) { - if (!mRequestDirtyRegions) return false; +void EglManager::cancelFrame() { + mInFrame = false; +} + +bool EglManager::setPreserveBuffer(EGLSurface surface, bool preserve) { + if (CC_UNLIKELY(!mAllowPreserveBuffer)) return false; - if (mCanSetDirtyRegions) { - if (!eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)) { + bool preserved = false; + if (mCanSetPreserveBuffer) { + preserved = eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, + preserve ? EGL_BUFFER_PRESERVED : EGL_BUFFER_DESTROYED); + if (CC_UNLIKELY(!preserved)) { ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s", (void*) surface, egl_error_str()); - return false; } - return true; } - // Perhaps it is already enabled? - EGLint value; - if (!eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &value)) { - ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p", - (void*) surface, egl_error_str()); - return false; + if (CC_UNLIKELY(!preserved)) { + // Maybe it's already set? + EGLint swapBehavior; + if (eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &swapBehavior)) { + preserved = (swapBehavior == EGL_BUFFER_PRESERVED); + } else { + ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p", + (void*) surface, egl_error_str()); + } } - return value == EGL_BUFFER_PRESERVED; + + return preserved; } } /* namespace renderthread */ diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h index 71213fbf9343..e12db3acbe2f 100644 --- a/libs/hwui/renderthread/EglManager.h +++ b/libs/hwui/renderthread/EglManager.h @@ -48,8 +48,10 @@ public: bool makeCurrent(EGLSurface surface); void beginFrame(EGLSurface surface, EGLint* width, EGLint* height); bool swapBuffers(EGLSurface surface); + void cancelFrame(); - bool enableDirtyRegions(EGLSurface surface); + // Returns true iff the surface is now preserving buffers. + bool setPreserveBuffer(EGLSurface surface, bool preserve); void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize); @@ -71,14 +73,20 @@ private: EGLContext mEglContext; EGLSurface mPBufferSurface; - const bool mRequestDirtyRegions; - bool mCanSetDirtyRegions; + const bool mAllowPreserveBuffer; + bool mCanSetPreserveBuffer; EGLSurface mCurrentSurface; sp<GraphicBuffer> mAtlasBuffer; int64_t* mAtlasMap; size_t mAtlasMapSize; + + // Whether or not we are in the middle of drawing a frame. This is used + // to avoid switching surfaces mid-frame if requireGlContext() is called + // TODO: Need to be better about surface/context management so that this isn't + // necessary + bool mInFrame; }; } /* namespace renderthread */ diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index 047819de239a..5d55ea62af1f 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -103,6 +103,18 @@ void RenderProxy::setFrameInterval(nsecs_t frameIntervalNanos) { post(task); } +CREATE_BRIDGE2(setSwapBehavior, CanvasContext* context, SwapBehavior swapBehavior) { + args->context->setSwapBehavior(args->swapBehavior); + return NULL; +} + +void RenderProxy::setSwapBehavior(SwapBehavior swapBehavior) { + SETUP_TASK(setSwapBehavior); + args->context = mContext; + args->swapBehavior = swapBehavior; + post(task); +} + CREATE_BRIDGE1(loadSystemProperties, CanvasContext* context) { bool needsRedraw = false; if (Caches::hasInstance()) { @@ -223,12 +235,7 @@ void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) { // waitForCompletion = true is expected to be fairly rare and only // happen in destruction. Thus it should be fine to temporarily // create a Mutex - Mutex mutex; - Condition condition; - SignalingRenderTask syncTask(task, &mutex, &condition); - AutoMutex _lock(mutex); - thread.queue(&syncTask); - condition.wait(mutex); + staticPostAndWait(task); } else { thread.queue(task); } @@ -246,17 +253,6 @@ void RenderProxy::runWithGlContext(RenderTask* gltask) { postAndWait(task); } -CREATE_BRIDGE1(destroyLayer, Layer* layer) { - LayerRenderer::destroyLayer(args->layer); - return NULL; -} - -void RenderProxy::enqueueDestroyLayer(Layer* layer) { - SETUP_TASK(destroyLayer); - args->layer = layer; - RenderThread::getInstance().queue(task); -} - CREATE_BRIDGE2(createTextureLayer, RenderThread* thread, CanvasContext* context) { Layer* layer = args->context->createTextureLayer(); if (!layer) return 0; @@ -388,6 +384,17 @@ void RenderProxy::dumpProfileInfo(int fd) { postAndWait(task); } +CREATE_BRIDGE1(outputLogBuffer, int fd) { + RenderNode::outputLogBuffer(args->fd); + return NULL; +} + +void RenderProxy::outputLogBuffer(int fd) { + SETUP_TASK(outputLogBuffer); + args->fd = fd; + staticPostAndWait(task); +} + CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map, size_t size) { CanvasContext::setTextureAtlas(*args->thread, args->buffer, args->map, args->size); args->buffer->decStrong(0); @@ -418,6 +425,19 @@ void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) { return retval; } +void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) { + RenderThread& thread = RenderThread::getInstance(); + void* retval; + task->setReturnPtr(&retval); + Mutex mutex; + Condition condition; + SignalingRenderTask syncTask(task, &mutex, &condition); + AutoMutex _lock(mutex); + thread.queue(&syncTask); + condition.wait(mutex); + return retval; +} + } /* namespace renderthread */ } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index 678e7e261c77..4989b1492838 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -31,6 +31,7 @@ #include "../Caches.h" #include "../IContextFactory.h" +#include "CanvasContext.h" #include "DrawFrameTask.h" namespace android { @@ -44,7 +45,6 @@ class Rect; namespace renderthread { -class CanvasContext; class ErrorChannel; class RenderThread; class RenderProxyBridge; @@ -63,6 +63,8 @@ public: ANDROID_API virtual ~RenderProxy(); ANDROID_API void setFrameInterval(nsecs_t frameIntervalNanos); + // Won't take effect until next EGLSurface creation + ANDROID_API void setSwapBehavior(SwapBehavior swapBehavior); ANDROID_API bool loadSystemProperties(); ANDROID_API bool initialize(const sp<ANativeWindow>& window); @@ -79,7 +81,6 @@ public: ANDROID_API void runWithGlContext(RenderTask* task); - static void enqueueDestroyLayer(Layer* layer); ANDROID_API DeferredLayerUpdater* createTextureLayer(); ANDROID_API void buildLayer(RenderNode* node); ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap); @@ -95,6 +96,7 @@ public: ANDROID_API void notifyFramePending(); ANDROID_API void dumpProfileInfo(int fd); + ANDROID_API static void outputLogBuffer(int fd); ANDROID_API void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size); @@ -112,6 +114,8 @@ private: void post(RenderTask* task); void* postAndWait(MethodInvokeRenderTask* task); + static void* staticPostAndWait(MethodInvokeRenderTask* task); + // Friend class to help with bridging friend class RenderProxyBridge; }; diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index 403e1644bc7b..f887103e28ae 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -168,7 +168,7 @@ void RenderThread::initializeDisplayEventReceiver() { void RenderThread::initThreadLocals() { initializeDisplayEventReceiver(); mEglManager = new EglManager(*this); - mRenderState = new RenderState(); + mRenderState = new RenderState(*this); } int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) { diff --git a/libs/hwui/tests/Android.mk b/libs/hwui/tests/Android.mk new file mode 100644 index 000000000000..9622073024a3 --- /dev/null +++ b/libs/hwui/tests/Android.mk @@ -0,0 +1,55 @@ +# +# Copyright (C) 2014 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. +# + +local_target_dir := $(TARGET_OUT_DATA)/local/tmp +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER -DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES +LOCAL_CFLAGS += -DATRACE_TAG=ATRACE_TAG_VIEW -DLOG_TAG=\"OpenGLRenderer\" + +LOCAL_SRC_FILES:= \ + TestContext.cpp \ + main.cpp + +LOCAL_C_INCLUDES += \ + $(LOCAL_PATH)/.. \ + external/skia/src/core + +LOCAL_SHARED_LIBRARIES := \ + liblog \ + libcutils \ + libutils \ + libskia \ + libgui \ + libui \ + libhwui + +ifeq ($(WITH_MALLOC_LEAK_CHECK),true) + LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK +endif + +LOCAL_MODULE_PATH := $(local_target_dir) +LOCAL_MODULE:= hwuitest +LOCAL_MODULE_TAGS := tests +LOCAL_MULTILIB := both +LOCAL_MODULE_STEM_32 := hwuitest +LOCAL_MODULE_STEM_64 := hwuitest64 + +include external/stlport/libstlport.mk +include $(BUILD_EXECUTABLE) + +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/libs/hwui/tests/TestContext.cpp b/libs/hwui/tests/TestContext.cpp new file mode 100644 index 000000000000..35e402d7ed2e --- /dev/null +++ b/libs/hwui/tests/TestContext.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2014 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. + */ + +#include "TestContext.h" + +#include <gui/ISurfaceComposer.h> +#include <gui/SurfaceComposerClient.h> + +using namespace android; + +DisplayInfo gDisplay; +sp<SurfaceComposerClient> gSession; + +void createTestEnvironment() { + gSession = new SurfaceComposerClient(); + sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay( + ISurfaceComposer::eDisplayIdMain)); + status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &gDisplay); + LOG_ALWAYS_FATAL_IF(status, "Failed to get display info\n"); +} + +sp<SurfaceControl> createWindow(int width, int height) { + sp<SurfaceControl> control = gSession->createSurface(String8("HwuiTest"), + width, height, PIXEL_FORMAT_RGBX_8888); + + SurfaceComposerClient::openGlobalTransaction(); + control->setLayer(0x7FFFFFF); + control->show(); + SurfaceComposerClient::closeGlobalTransaction(); + + return control; +} diff --git a/libs/hwui/tests/TestContext.h b/libs/hwui/tests/TestContext.h new file mode 100644 index 000000000000..8a5d53043283 --- /dev/null +++ b/libs/hwui/tests/TestContext.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2014 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. + */ + +#ifndef TESTCONTEXT_H +#define TESTCONTEXT_H + +#include <ui/DisplayInfo.h> +#include <gui/SurfaceControl.h> + +extern android::DisplayInfo gDisplay; +#define dp(x) ((x) * gDisplay.density) + +// Initializes all the static globals that are shared across all contexts +// such as display info +void createTestEnvironment(); + +// Defaults to fullscreen +android::sp<android::SurfaceControl> createWindow(int width = -1, int height = -1); + +#endif diff --git a/libs/hwui/tests/main.cpp b/libs/hwui/tests/main.cpp new file mode 100644 index 000000000000..2d99e9f7686c --- /dev/null +++ b/libs/hwui/tests/main.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2014 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. + */ + +#include <stdio.h> + +#include <cutils/log.h> +#include <gui/Surface.h> +#include <ui/PixelFormat.h> + +#include <AnimationContext.h> +#include <DisplayListRenderer.h> +#include <RenderNode.h> +#include <renderthread/RenderProxy.h> + +#include "TestContext.h" + +using namespace android; +using namespace android::uirenderer; +using namespace android::uirenderer::renderthread; + +class ContextFactory : public IContextFactory { +public: + virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) { + return new AnimationContext(clock); + } +}; + +static DisplayListRenderer* startRecording(RenderNode* node) { + DisplayListRenderer* renderer = new DisplayListRenderer(); + renderer->setViewport(node->getWidth(), node->getHeight()); + renderer->prepare(false); + return renderer; +} + +static void endRecording(DisplayListRenderer* renderer, RenderNode* node) { + renderer->finish(); + node->setStagingDisplayList(renderer->finishRecording()); + delete renderer; +} + +sp<RenderNode> createCard(int x, int y, int width, int height) { + sp<RenderNode> node = new RenderNode(); + node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height); + node->mutateStagingProperties().setElevation(dp(16)); + node->mutateStagingProperties().mutableOutline().setRoundRect(0, 0, width, height, dp(10), 1); + node->mutateStagingProperties().mutableOutline().setShouldClip(true); + node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y | RenderNode::Z); + + DisplayListRenderer* renderer = startRecording(node.get()); + renderer->drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode); + endRecording(renderer, node.get()); + + return node; +} + +int main(int argc, char* argv[]) { + createTestEnvironment(); + + // create the native surface + const int width = gDisplay.w; + const int height = gDisplay.h; + sp<SurfaceControl> control = createWindow(width, height); + sp<Surface> surface = control->getSurface(); + + RenderNode* rootNode = new RenderNode(); + rootNode->incStrong(0); + rootNode->mutateStagingProperties().setLeftTopRightBottom(0, 0, width, height); + rootNode->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y); + rootNode->mutateStagingProperties().setClipToBounds(false); + rootNode->setPropertyFieldsDirty(RenderNode::GENERIC); + + ContextFactory factory; + RenderProxy* proxy = new RenderProxy(false, rootNode, &factory); + proxy->loadSystemProperties(); + proxy->initialize(surface); + float lightX = width / 2.0; + proxy->setup(width, height, (Vector3){lightX, dp(-200.0f), dp(800.0f)}, + dp(800.0f), 255 * 0.075, 255 * 0.15); + + android::uirenderer::Rect DUMMY; + + std::vector< sp<RenderNode> > cards; + + DisplayListRenderer* renderer = startRecording(rootNode); + renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode); + renderer->insertReorderBarrier(true); + + for (int x = dp(16); x < (width - dp(116)); x += dp(116)) { + for (int y = dp(16); y < (height - dp(116)); y += dp(116)) { + sp<RenderNode> card = createCard(x, y, dp(100), dp(100)); + renderer->drawRenderNode(card.get(), DUMMY, 0); + cards.push_back(card); + } + } + + renderer->insertReorderBarrier(false); + endRecording(renderer, rootNode); + + for (int i = 0; i < 150; i++) { + ATRACE_NAME("UI-Draw Frame"); + for (int ci = 0; ci < cards.size(); ci++) { + cards[ci]->mutateStagingProperties().setTranslationX(i); + cards[ci]->mutateStagingProperties().setTranslationY(i); + cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y); + } + nsecs_t frameTimeNs = systemTime(CLOCK_MONOTONIC); + proxy->syncAndDrawFrame(frameTimeNs, 0, gDisplay.density); + usleep(12000); + } + + sleep(5); + + delete proxy; + rootNode->decStrong(0); + + printf("Success!\n"); + return 0; +} diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java index 17d3251b3a6f..20c4978e779b 100644 --- a/media/java/android/media/AudioAttributes.java +++ b/media/java/android/media/AudioAttributes.java @@ -161,6 +161,12 @@ public final class AudioAttributes implements Parcelable { * Usage value to use when the usage is for game audio. */ public final static int USAGE_GAME = 14; + /** + * @hide + * Usage value to use when feeding audio to the platform and replacing "traditional" audio + * source, such as audio capture devices. + */ + public final static int USAGE_VIRTUAL_SOURCE = 15; /** * Flag defining a behavior where the audibility of the sound will be ensured by the system. @@ -374,6 +380,7 @@ public final class AudioAttributes implements Parcelable { case USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: case USAGE_ASSISTANCE_SONIFICATION: case USAGE_GAME: + case USAGE_VIRTUAL_SOURCE: mUsage = usage; break; default: diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java index 7975e04e49c8..b10736be1756 100644 --- a/media/java/android/media/AudioDevicePort.java +++ b/media/java/android/media/AudioDevicePort.java @@ -16,6 +16,8 @@ package android.media; +import android.media.AudioSystem; + /** * The AudioDevicePort is a specialized type of AudioPort * describing an input (e.g microphone) or output device (e.g speaker) @@ -85,8 +87,11 @@ public class AudioDevicePort extends AudioPort { @Override public String toString() { + String type = (mRole == ROLE_SOURCE ? + AudioSystem.getInputDeviceName(mType) : + AudioSystem.getOutputDeviceName(mType)); return "{" + super.toString() - + ", mType:" + mType + + ", mType: " + type + ", mAddress: " + mAddress + "}"; } diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 69c1142b5cd4..8fc0b8e4a86d 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -353,21 +353,6 @@ public class AudioManager { */ @Deprecated public static final int NUM_STREAMS = AudioSystem.NUM_STREAMS; - - /** @hide Default volume index values for audio streams */ - public static final int[] DEFAULT_STREAM_VOLUME = new int[] { - 4, // STREAM_VOICE_CALL - 7, // STREAM_SYSTEM - 5, // STREAM_RING - 11, // STREAM_MUSIC - 6, // STREAM_ALARM - 5, // STREAM_NOTIFICATION - 7, // STREAM_BLUETOOTH_SCO - 7, // STREAM_SYSTEM_ENFORCED - 11, // STREAM_DTMF - 11 // STREAM_TTS - }; - /** * Increase the ringer volume. * @@ -512,8 +497,11 @@ public class AudioManager { */ public static final int RINGER_MODE_NORMAL = 2; - // maximum valid ringer mode value. Values must start from 0 and be contiguous. - private static final int RINGER_MODE_MAX = RINGER_MODE_NORMAL; + /** + * Maximum valid ringer mode value. Values must start from 0 and be contiguous. + * @hide + */ + public static final int RINGER_MODE_MAX = RINGER_MODE_NORMAL; /** * Vibrate type that corresponds to the ringer. @@ -887,7 +875,13 @@ public class AudioManager { if (ringerMode < 0 || ringerMode > RINGER_MODE_MAX) { return false; } - return true; + IAudioService service = getService(); + try { + return service.isValidRingerMode(ringerMode); + } catch (RemoteException e) { + Log.e(TAG, "Dead object in isValidRingerMode", e); + return false; + } } /** @@ -2669,9 +2663,13 @@ public class AudioManager { } IAudioService service = getService(); try { - if (!service.registerAudioPolicy(policy.getConfig(), policy.token())) { + String regId = service.registerAudioPolicy(policy.getConfig(), policy.token()); + if (regId == null) { return ERROR; + } else { + policy.setRegistration(regId); } + // successful registration } catch (RemoteException e) { Log.e(TAG, "Dead object in registerAudioPolicyAsync()", e); return ERROR; diff --git a/media/java/android/media/AudioPatch.java b/media/java/android/media/AudioPatch.java index 81eceb1e27e9..acadb413e429 100644 --- a/media/java/android/media/AudioPatch.java +++ b/media/java/android/media/AudioPatch.java @@ -52,4 +52,25 @@ public class AudioPatch { public AudioPortConfig[] sinks() { return mSinks; } + + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + s.append("mHandle: "); + s.append(mHandle.toString()); + + s.append(" mSources: {"); + for (AudioPortConfig source : mSources) { + s.append(source.toString()); + s.append(", "); + } + s.append("} mSinks: {"); + for (AudioPortConfig sink : mSinks) { + s.append(sink.toString()); + s.append(", "); + } + s.append("}"); + + return s.toString(); + } } diff --git a/media/java/android/media/AudioPort.java b/media/java/android/media/AudioPort.java index 53212aa85e4e..1ab7e89273e9 100644 --- a/media/java/android/media/AudioPort.java +++ b/media/java/android/media/AudioPort.java @@ -67,7 +67,7 @@ public class AudioPort { AudioHandle mHandle; - private final int mRole; + protected final int mRole; private final int[] mSamplingRates; private final int[] mChannelMasks; private final int[] mFormats; @@ -176,8 +176,20 @@ public class AudioPort { @Override public String toString() { - return "{mHandle:" + mHandle - + ", mRole:" + mRole + String role = Integer.toString(mRole); + switch (mRole) { + case ROLE_NONE: + role = "NONE"; + break; + case ROLE_SOURCE: + role = "SOURCE"; + break; + case ROLE_SINK: + role = "SINK"; + break; + } + return "{mHandle: " + mHandle + + ", mRole: " + role + "}"; } } diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index b0bf4a148d71..2f683828d3b1 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -48,6 +48,7 @@ import android.hardware.hdmi.HdmiTvClient; import android.hardware.usb.UsbManager; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnErrorListener; +import android.media.audiopolicy.AudioMix; import android.media.audiopolicy.AudioPolicyConfig; import android.media.session.MediaSessionLegacyHelper; import android.os.Binder; @@ -118,6 +119,10 @@ public class AudioService extends IAudioService.Stub { /** Debug audio mode */ protected static final boolean DEBUG_MODE = Log.isLoggable(TAG + ".MOD", Log.DEBUG); + + /** Debug audio policy feature */ + protected static final boolean DEBUG_AP = Log.isLoggable(TAG + ".AP", Log.DEBUG); + /** Debug volumes */ protected static final boolean DEBUG_VOL = Log.isLoggable(TAG + ".VOL", Log.DEBUG); @@ -248,7 +253,7 @@ public class AudioService extends IAudioService.Stub { private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2]; /** @hide Maximum volume index values for audio streams */ - private static final int[] MAX_STREAM_VOLUME = new int[] { + private static int[] MAX_STREAM_VOLUME = new int[] { 5, // STREAM_VOICE_CALL 7, // STREAM_SYSTEM 7, // STREAM_RING @@ -260,6 +265,20 @@ public class AudioService extends IAudioService.Stub { 15, // STREAM_DTMF 15 // STREAM_TTS }; + + private static int[] DEFAULT_STREAM_VOLUME = new int[] { + 4, // STREAM_VOICE_CALL + 7, // STREAM_SYSTEM + 5, // STREAM_RING + 11, // STREAM_MUSIC + 6, // STREAM_ALARM + 5, // STREAM_NOTIFICATION + 7, // STREAM_BLUETOOTH_SCO + 7, // STREAM_SYSTEM_ENFORCED + 11, // STREAM_DTMF + 11 // STREAM_TTS + }; + /* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings * of another stream: This avoids multiplying the volume settings for hidden * stream types that follow other stream behavior for volume settings @@ -541,12 +560,18 @@ public class AudioService extends IAudioService.Stub { mHasVibrator = vibrator == null ? false : vibrator.hasVibrator(); // Intialized volume - MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = SystemProperties.getInt( - "ro.config.vc_call_vol_steps", - MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]); - MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = SystemProperties.getInt( - "ro.config.media_vol_steps", - MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]); + int maxVolume = SystemProperties.getInt("ro.config.vc_call_vol_steps", + MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]); + if (maxVolume != MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]) { + MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = maxVolume; + DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = (maxVolume * 3) / 4; + } + maxVolume = SystemProperties.getInt("ro.config.media_vol_steps", + MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]); + if (maxVolume != MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]) { + MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = maxVolume; + DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = (maxVolume * 3) / 4; + } sSoundEffectVolumeDb = context.getResources().getInteger( com.android.internal.R.integer.config_soundEffectVolumeDb); @@ -843,7 +868,7 @@ public class AudioService extends IAudioService.Stub { int ringerMode = ringerModeFromSettings; // sanity check in case the settings are restored from a device with incompatible // ringer modes - if (!AudioManager.isValidRingerMode(ringerMode)) { + if (!isValidRingerMode(ringerMode)) { ringerMode = AudioManager.RINGER_MODE_NORMAL; } if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) { @@ -1625,6 +1650,10 @@ public class AudioService extends IAudioService.Stub { return MAX_STREAM_VOLUME[streamType]; } + public static int getDefaultStreamVolume(int streamType) { + return DEFAULT_STREAM_VOLUME[streamType]; + } + /** @see AudioManager#getStreamVolume(int) */ public int getStreamVolume(int streamType) { ensureValidStreamType(streamType); @@ -1733,17 +1762,22 @@ public class AudioService extends IAudioService.Stub { } private void ensureValidRingerMode(int ringerMode) { - if (!AudioManager.isValidRingerMode(ringerMode)) { + if (!isValidRingerMode(ringerMode)) { throw new IllegalArgumentException("Bad ringer mode " + ringerMode); } } + /** @see AudioManager#isValidRingerMode(int) */ + public boolean isValidRingerMode(int ringerMode) { + return ringerMode >= 0 && ringerMode <= AudioManager.RINGER_MODE_MAX; + } + /** @see AudioManager#setRingerMode(int) */ public void setRingerMode(int ringerMode, boolean checkZen) { if (mUseFixedVolume || isPlatformTelevision()) { return; } - + ensureValidRingerMode(ringerMode); if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) { ringerMode = AudioManager.RINGER_MODE_SILENT; } @@ -2545,13 +2579,17 @@ public class AudioService extends IAudioService.Stub { if (mScoAudioState == SCO_STATE_INACTIVE) { mScoAudioMode = scoAudioMode; if (scoAudioMode == SCO_MODE_UNDEFINED) { - mScoAudioMode = new Integer(Settings.Global.getInt( - mContentResolver, - "bluetooth_sco_channel_"+ - mBluetoothHeadsetDevice.getAddress(), - SCO_MODE_VIRTUAL_CALL)); - if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) { - mScoAudioMode = SCO_MODE_VIRTUAL_CALL; + if (mBluetoothHeadsetDevice != null) { + mScoAudioMode = new Integer(Settings.Global.getInt( + mContentResolver, + "bluetooth_sco_channel_"+ + mBluetoothHeadsetDevice.getAddress(), + SCO_MODE_VIRTUAL_CALL)); + if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) { + mScoAudioMode = SCO_MODE_VIRTUAL_CALL; + } + } else { + mScoAudioMode = SCO_MODE_RAW; } } if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) { @@ -3351,7 +3389,7 @@ public class AudioService extends IAudioService.Stub { // only be stale values if ((mStreamType == AudioSystem.STREAM_SYSTEM) || (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) { - int index = 10 * AudioManager.DEFAULT_STREAM_VOLUME[mStreamType]; + int index = 10 * DEFAULT_STREAM_VOLUME[mStreamType]; synchronized (mCameraSoundForced) { if (mCameraSoundForced) { index = mIndexMax; @@ -3375,7 +3413,7 @@ public class AudioService extends IAudioService.Stub { // if no volume stored for current stream and device, use default volume if default // device, continue otherwise int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ? - AudioManager.DEFAULT_STREAM_VOLUME[mStreamType] : -1; + DEFAULT_STREAM_VOLUME[mStreamType] : -1; int index = Settings.System.getIntForUser( mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT); if (index == -1) { @@ -5601,31 +5639,33 @@ public class AudioService extends IAudioService.Stub { //========================================================================================== // Audio policy management //========================================================================================== - public boolean registerAudioPolicy(AudioPolicyConfig policyConfig, IBinder cb) { + public String registerAudioPolicy(AudioPolicyConfig policyConfig, IBinder cb) { //Log.v(TAG, "registerAudioPolicy for " + cb + " got policy:" + policyConfig); + String regId = null; boolean hasPermissionForPolicy = (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission( android.Manifest.permission.MODIFY_AUDIO_ROUTING)); if (!hasPermissionForPolicy) { Slog.w(TAG, "Can't register audio policy for pid " + Binder.getCallingPid() + " / uid " + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING"); - return false; + return null; } synchronized (mAudioPolicies) { - AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, cb); try { + AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, cb); cb.linkToDeath(app, 0/*flags*/); + regId = app.connectMixes(); mAudioPolicies.put(cb, app); } catch (RemoteException e) { // audio policy owner has already died! Slog.w(TAG, "Audio policy registration failed, could not link to " + cb + " binder death", e); - return false; + return null; } } - // TODO implement registration with native audio policy (including permission check) - return true; + return regId; } + public void unregisterAudioPolicyAsync(IBinder cb) { synchronized (mAudioPolicies) { AudioPolicyProxy app = mAudioPolicies.remove(cb); @@ -5635,27 +5675,59 @@ public class AudioService extends IAudioService.Stub { } else { cb.unlinkToDeath(app, 0/*flags*/); } + app.disconnectMixes(); } - // TODO implement registration with native audio policy + // TODO implement clearing mix attribute matching info in native audio policy } - public class AudioPolicyProxy implements IBinder.DeathRecipient { + /** + * This internal class inherits from AudioPolicyConfig which contains all the mixes and + * their configurations. + */ + public class AudioPolicyProxy extends AudioPolicyConfig implements IBinder.DeathRecipient { private static final String TAG = "AudioPolicyProxy"; AudioPolicyConfig mConfig; IBinder mToken; AudioPolicyProxy(AudioPolicyConfig config, IBinder token) { - mConfig = config; + super(config); + setRegistration(new String(config.toString() + ":ap:" + mAudioPolicyCounter++)); mToken = token; } public void binderDied() { synchronized (mAudioPolicies) { - Log.v(TAG, "audio policy " + mToken + " died"); + Log.i(TAG, "audio policy " + mToken + " died"); mAudioPolicies.remove(mToken); + disconnectMixes(); + } + } + + String connectMixes() { + updateMixes(AudioSystem.DEVICE_STATE_AVAILABLE); + return mRegistrationId; + } + + void disconnectMixes() { + updateMixes(AudioSystem.DEVICE_STATE_UNAVAILABLE); + } + + void updateMixes(int connectionState) { + for (AudioMix mix : mMixes) { + // TODO implement sending the mix attribute matching info to native audio policy + if (DEBUG_AP) { + Log.v(TAG, "AudioPolicyProxy connect mix state=" + connectionState + + " addr=" + mix.getRegistration()); } + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_REMOTE_SUBMIX, + connectionState, + mix.getRegistration()); + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX, + connectionState, + mix.getRegistration()); } } }; private HashMap<IBinder, AudioPolicyProxy> mAudioPolicies = new HashMap<IBinder, AudioPolicyProxy>(); + private int mAudioPolicyCounter = 0; // always accessed synchronized on mAudioPolicies } diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 9a76f9482369..e795fa74fc8b 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -255,6 +255,7 @@ public class AudioSystem public static final int DEVICE_OUT_SPDIF = 0x80000; public static final int DEVICE_OUT_FM = 0x100000; public static final int DEVICE_OUT_AUX_LINE = 0x200000; + public static final int DEVICE_OUT_SPEAKER_SAFE = 0x400000; public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT; @@ -280,6 +281,7 @@ public class AudioSystem DEVICE_OUT_SPDIF | DEVICE_OUT_FM | DEVICE_OUT_AUX_LINE | + DEVICE_OUT_SPEAKER_SAFE | DEVICE_OUT_DEFAULT); public static final int DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | @@ -372,6 +374,27 @@ public class AudioSystem public static final String DEVICE_OUT_SPDIF_NAME = "spdif"; public static final String DEVICE_OUT_FM_NAME = "fm_transmitter"; public static final String DEVICE_OUT_AUX_LINE_NAME = "aux_line"; + public static final String DEVICE_OUT_SPEAKER_SAFE_NAME = "speaker_safe"; + + public static final String DEVICE_IN_COMMUNICATION_NAME = "communication"; + public static final String DEVICE_IN_AMBIENT_NAME = "ambient"; + public static final String DEVICE_IN_BUILTIN_MIC_NAME = "mic"; + public static final String DEVICE_IN_BLUETOOTH_SCO_HEADSET_NAME = "bt_sco_hs"; + public static final String DEVICE_IN_WIRED_HEADSET_NAME = "headset"; + public static final String DEVICE_IN_AUX_DIGITAL_NAME = "aux_digital"; + public static final String DEVICE_IN_TELEPHONY_RX_NAME = "telephony_rx"; + public static final String DEVICE_IN_BACK_MIC_NAME = "back_mic"; + public static final String DEVICE_IN_REMOTE_SUBMIX_NAME = "remote_submix"; + public static final String DEVICE_IN_ANLG_DOCK_HEADSET_NAME = "analog_dock"; + public static final String DEVICE_IN_DGTL_DOCK_HEADSET_NAME = "digital_dock"; + public static final String DEVICE_IN_USB_ACCESSORY_NAME = "usb_accessory"; + public static final String DEVICE_IN_USB_DEVICE_NAME = "usb_device"; + public static final String DEVICE_IN_FM_TUNER_NAME = "fm_tuner"; + public static final String DEVICE_IN_TV_TUNER_NAME = "tv_tuner"; + public static final String DEVICE_IN_LINE_NAME = "line"; + public static final String DEVICE_IN_SPDIF_NAME = "spdif"; + public static final String DEVICE_IN_BLUETOOTH_A2DP_NAME = "bt_a2dp"; + public static final String DEVICE_IN_LOOPBACK_NAME = "loopback"; public static String getOutputDeviceName(int device) { @@ -420,12 +443,60 @@ public class AudioSystem return DEVICE_OUT_FM_NAME; case DEVICE_OUT_AUX_LINE: return DEVICE_OUT_AUX_LINE_NAME; + case DEVICE_OUT_SPEAKER_SAFE: + return DEVICE_OUT_SPEAKER_SAFE_NAME; case DEVICE_OUT_DEFAULT: default: - return ""; + return Integer.toString(device); } } + public static String getInputDeviceName(int device) + { + switch(device) { + case DEVICE_IN_COMMUNICATION: + return DEVICE_IN_COMMUNICATION_NAME; + case DEVICE_IN_AMBIENT: + return DEVICE_IN_AMBIENT_NAME; + case DEVICE_IN_BUILTIN_MIC: + return DEVICE_IN_BUILTIN_MIC_NAME; + case DEVICE_IN_BLUETOOTH_SCO_HEADSET: + return DEVICE_IN_BLUETOOTH_SCO_HEADSET_NAME; + case DEVICE_IN_WIRED_HEADSET: + return DEVICE_IN_WIRED_HEADSET_NAME; + case DEVICE_IN_AUX_DIGITAL: + return DEVICE_IN_AUX_DIGITAL_NAME; + case DEVICE_IN_TELEPHONY_RX: + return DEVICE_IN_TELEPHONY_RX_NAME; + case DEVICE_IN_BACK_MIC: + return DEVICE_IN_BACK_MIC_NAME; + case DEVICE_IN_REMOTE_SUBMIX: + return DEVICE_IN_REMOTE_SUBMIX_NAME; + case DEVICE_IN_ANLG_DOCK_HEADSET: + return DEVICE_IN_ANLG_DOCK_HEADSET_NAME; + case DEVICE_IN_DGTL_DOCK_HEADSET: + return DEVICE_IN_DGTL_DOCK_HEADSET_NAME; + case DEVICE_IN_USB_ACCESSORY: + return DEVICE_IN_USB_ACCESSORY_NAME; + case DEVICE_IN_USB_DEVICE: + return DEVICE_IN_USB_DEVICE_NAME; + case DEVICE_IN_FM_TUNER: + return DEVICE_IN_FM_TUNER_NAME; + case DEVICE_IN_TV_TUNER: + return DEVICE_IN_TV_TUNER_NAME; + case DEVICE_IN_LINE: + return DEVICE_IN_LINE_NAME; + case DEVICE_IN_SPDIF: + return DEVICE_IN_SPDIF_NAME; + case DEVICE_IN_BLUETOOTH_A2DP: + return DEVICE_IN_BLUETOOTH_A2DP_NAME; + case DEVICE_IN_LOOPBACK: + return DEVICE_IN_LOOPBACK_NAME; + case DEVICE_IN_DEFAULT: + default: + return Integer.toString(device); + } + } // phone state, match audio_mode??? public static final int PHONE_STATE_OFFCALL = 0; diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 39b074e6bbf6..317cc212c463 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -80,6 +80,8 @@ interface IAudioService { int getRingerMode(); + boolean isValidRingerMode(int ringerMode); + void setVibrateSetting(int vibrateType, int vibrateSetting); int getVibrateSetting(int vibrateType); @@ -205,6 +207,6 @@ interface IAudioService { boolean isHdmiSystemAudioSupported(); - boolean registerAudioPolicy(in AudioPolicyConfig policyConfig, IBinder cb); + String registerAudioPolicy(in AudioPolicyConfig policyConfig, IBinder cb); oneway void unregisterAudioPolicyAsync(in IBinder cb); } diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java index 522e45d3b411..0d6b91a7046a 100644 --- a/media/java/android/media/Image.java +++ b/media/java/android/media/Image.java @@ -146,8 +146,10 @@ public abstract class Image implements AutoCloseable { * using coordinates in the largest-resolution plane. */ public void setCropRect(Rect cropRect) { - cropRect = new Rect(cropRect); // make a copy - cropRect.intersect(0, 0, getWidth(), getHeight()); + if (cropRect != null) { + cropRect = new Rect(cropRect); // make a copy + cropRect.intersect(0, 0, getWidth(), getHeight()); + } mCropRect = cropRect; } diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index 420510a93369..bdd62f27703b 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -1778,10 +1778,6 @@ final public class MediaCodec { mIsValid = true; mIsReadOnly = buffer.isReadOnly(); mBuffer = buffer.duplicate(); - if (cropRect != null) { - cropRect.offset(-xOffset, -yOffset); - } - super.setCropRect(cropRect); // save offsets and info mXOffset = xOffset; @@ -1833,6 +1829,12 @@ final public class MediaCodec { throw new UnsupportedOperationException( "unsupported info length: " + info.remaining()); } + + if (cropRect == null) { + cropRect = new Rect(0, 0, mWidth, mHeight); + } + cropRect.offset(-xOffset, -yOffset); + super.setCropRect(cropRect); } private class MediaPlane extends Plane { diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java index f7967f1f7d7b..bb5268261d78 100644 --- a/media/java/android/media/audiopolicy/AudioMix.java +++ b/media/java/android/media/audiopolicy/AudioMix.java @@ -24,13 +24,14 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** - * @hide CANDIDATE FOR PUBLIC API + * @hide */ public class AudioMix { private AudioMixingRule mRule; private AudioFormat mFormat; private int mRouteFlags; + private String mRegistrationId; /** * All parameters are guaranteed valid through the Builder. @@ -39,6 +40,7 @@ public class AudioMix { mRule = rule; mFormat = format; mRouteFlags = routeFlags; + mRegistrationId = null; } /** @@ -65,6 +67,15 @@ public class AudioMix { return mRule; } + void setRegistration(String regId) { + mRegistrationId = regId; + } + + /** @hide */ + public String getRegistration() { + return mRegistrationId; + } + /** @hide */ @IntDef(flag = true, value = { ROUTE_FLAG_RENDER, ROUTE_FLAG_LOOP_BACK } ) diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java index ced78817a992..2e06a807624f 100644 --- a/media/java/android/media/audiopolicy/AudioMixingRule.java +++ b/media/java/android/media/audiopolicy/AudioMixingRule.java @@ -23,7 +23,7 @@ import java.util.Iterator; /** - * @hide CANDIDATE FOR PUBLIC API + * @hide * * Here's an example of creating a mixing rule for all media playback: * <pre> diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java index 314eb887d1d1..255d828b4bfa 100644 --- a/media/java/android/media/audiopolicy/AudioPolicy.java +++ b/media/java/android/media/audiopolicy/AudioPolicy.java @@ -17,18 +17,26 @@ package android.media.audiopolicy; import android.annotation.IntDef; +import android.content.Context; +import android.content.pm.PackageManager; +import android.media.AudioAttributes; import android.media.AudioFormat; import android.media.AudioManager; +import android.media.AudioRecord; +import android.media.AudioSystem; +import android.media.AudioTrack; +import android.media.MediaRecorder; import android.os.Binder; import android.os.IBinder; import android.util.Log; +import android.util.Slog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; /** - * @hide CANDIDATE FOR PUBLIC API + * @hide * AudioPolicy provides access to the management of audio routing and audio focus. */ public class AudioPolicy { @@ -49,11 +57,13 @@ public class AudioPolicy { public static final int POLICY_STATUS_REGISTERED = 2; private int mStatus; - private AudioPolicyStatusListener mStatusListener = null; + private String mRegistrationId; + private AudioPolicyStatusListener mStatusListener; private final IBinder mToken = new Binder(); /** @hide */ public IBinder token() { return mToken; } + private Context mContext; private AudioPolicyConfig mConfig; /** @hide */ @@ -62,13 +72,14 @@ public class AudioPolicy { /** * The parameter is guaranteed non-null through the Builder */ - private AudioPolicy(AudioPolicyConfig config) { + private AudioPolicy(AudioPolicyConfig config, Context context) { mConfig = config; if (mConfig.mMixes.isEmpty()) { mStatus = POLICY_STATUS_INVALID; } else { mStatus = POLICY_STATUS_UNREGISTERED; } + mContext = context; } /** @@ -76,12 +87,15 @@ public class AudioPolicy { */ public static class Builder { private ArrayList<AudioMix> mMixes; + private Context mContext; /** * Constructs a new Builder with no audio mixes. + * @param context the context for the policy */ - public Builder() { + public Builder(Context context) { mMixes = new ArrayList<AudioMix>(); + mContext = context; } /** @@ -99,10 +113,115 @@ public class AudioPolicy { } public AudioPolicy build() { - return new AudioPolicy(new AudioPolicyConfig(mMixes)); + return new AudioPolicy(new AudioPolicyConfig(mMixes), mContext); } } + /** @hide */ + public void setRegistration(String regId) { + mRegistrationId = regId; + mConfig.setRegistration(regId); + } + + private boolean policyReadyToUse() { + if (mContext == null) { + Log.e(TAG, "Cannot use AudioPolicy without context"); + return false; + } + if (mRegistrationId == null) { + Log.e(TAG, "Cannot use unregistered AudioPolicy"); + return false; + } + if (!(PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission( + android.Manifest.permission.MODIFY_AUDIO_ROUTING))) { + Slog.w(TAG, "Cannot use AudioPolicy for pid " + Binder.getCallingPid() + " / uid " + + Binder.getCallingUid() + ", needs MODIFY_AUDIO_ROUTING"); + return false; + } + return true; + } + + private void checkMixReadyToUse(AudioMix mix, boolean forTrack) + throws IllegalArgumentException{ + if (mix == null) { + String msg = forTrack ? "Invalid null AudioMix for AudioTrack creation" + : "Invalid null AudioMix for AudioRecord creation"; + throw new IllegalArgumentException(msg); + } + if (!mConfig.mMixes.contains(mix)) { + throw new IllegalArgumentException("Invalid mix: not part of this policy"); + } + if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_LOOP_BACK) != AudioMix.ROUTE_FLAG_LOOP_BACK) + { + throw new IllegalArgumentException("Invalid AudioMix: not defined for loop back"); + } + } + + /** + * @hide + * Create an {@link AudioRecord} instance that is associated with the given {@link AudioMix}. + * Audio buffers recorded through the created instance will contain the mix of the audio + * streams that fed the given mixer. + * @param mix a non-null {@link AudioMix} instance whose routing flags was defined with + * {@link AudioMix#ROUTE_FLAG_LOOP_BACK}, previously added to this policy. + * @return a new {@link AudioRecord} instance whose data format is the one defined in the + * {@link AudioMix}, or null if this policy was not successfully registered + * with {@link AudioManager#registerAudioPolicy(AudioPolicy)}. + * @throws IllegalArgumentException + */ + public AudioRecord createAudioRecordSink(AudioMix mix) throws IllegalArgumentException { + if (!policyReadyToUse()) { + Log.e(TAG, "Cannot create AudioRecord sink for AudioMix"); + return null; + } + checkMixReadyToUse(mix, false/*not for an AudioTrack*/); + // create the AudioRecord, configured for loop back, using the same format as the mix + AudioRecord ar = new AudioRecord( + new AudioAttributes.Builder() + .setInternalCapturePreset(MediaRecorder.AudioSource.REMOTE_SUBMIX) + .addTag(mix.getRegistration()) + .build(), + mix.getFormat(), + AudioRecord.getMinBufferSize(mix.getFormat().getSampleRate(), + // using stereo for buffer size to avoid the current poor support for masks + AudioFormat.CHANNEL_IN_STEREO, mix.getFormat().getEncoding()), + AudioManager.AUDIO_SESSION_ID_GENERATE + ); + return ar; + } + + /** + * @hide + * Create an {@link AudioTrack} instance that is associated with the given {@link AudioMix}. + * Audio buffers played through the created instance will be sent to the given mix + * to be recorded through the recording APIs. + * @param mix a non-null {@link AudioMix} instance whose routing flags was defined with + * {@link AudioMix#ROUTE_FLAG_LOOP_BACK}, previously added to this policy. + * @returna new {@link AudioTrack} instance whose data format is the one defined in the + * {@link AudioMix}, or null if this policy was not successfully registered + * with {@link AudioManager#registerAudioPolicy(AudioPolicy)}. + * @throws IllegalArgumentException + */ + public AudioTrack createAudioTrackSource(AudioMix mix) throws IllegalArgumentException { + if (!policyReadyToUse()) { + Log.e(TAG, "Cannot create AudioTrack source for AudioMix"); + return null; + } + checkMixReadyToUse(mix, true/*for an AudioTrack*/); + // create the AudioTrack, configured for loop back, using the same format as the mix + AudioTrack at = new AudioTrack( + new AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_VIRTUAL_SOURCE) + .addTag(mix.getRegistration()) + .build(), + mix.getFormat(), + AudioTrack.getMinBufferSize(mix.getFormat().getSampleRate(), + mix.getFormat().getChannelMask(), mix.getFormat().getEncoding()), + AudioTrack.MODE_STREAM, + AudioManager.AUDIO_SESSION_ID_GENERATE + ); + return at; + } public int getStatus() { return mStatus; @@ -118,10 +237,9 @@ public class AudioPolicy { } /** @hide */ - @Override - public String toString () { + public String toLogFriendlyString() { String textDump = new String("android.media.audiopolicy.AudioPolicy:\n"); - textDump += "config=" + mConfig.toString(); + textDump += "config=" + mConfig.toLogFriendlyString(); return (textDump); } diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java index 2fc6d58b2e61..a9a4175916ce 100644 --- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java +++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java @@ -36,7 +36,13 @@ public class AudioPolicyConfig implements Parcelable { private static final String TAG = "AudioPolicyConfig"; - ArrayList<AudioMix> mMixes; + protected ArrayList<AudioMix> mMixes; + + protected String mRegistrationId = null; + + protected AudioPolicyConfig(AudioPolicyConfig conf) { + mMixes = conf.mMixes; + } AudioPolicyConfig(ArrayList<AudioMix> mixes) { mMixes = mixes; @@ -117,7 +123,6 @@ public class AudioPolicyConfig implements Parcelable { } } - /** @hide */ public static final Parcelable.Creator<AudioPolicyConfig> CREATOR = new Parcelable.Creator<AudioPolicyConfig>() { /** @@ -133,9 +138,7 @@ public class AudioPolicyConfig implements Parcelable { } }; - /** @hide */ - @Override - public String toString () { + public String toLogFriendlyString () { String textDump = new String("android.media.audiopolicy.AudioPolicyConfig:\n"); textDump += mMixes.size() + " AudioMix:\n"; for(AudioMix mix : mMixes) { @@ -166,4 +169,13 @@ public class AudioPolicyConfig implements Parcelable { } return textDump; } + + public void setRegistration(String regId) { + mRegistrationId = regId; + int mixIndex = 0; + for (AudioMix mix : mMixes) { + mix.setRegistration(mRegistrationId + "mix:" + mixIndex++); + } + } + } diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java index b8cdc4b4d60d..1ac80c14f458 100644 --- a/media/java/android/media/tv/ITvInputSessionWrapper.java +++ b/media/java/android/media/tv/ITvInputSessionWrapper.java @@ -166,6 +166,7 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand @Override public void release() { + mTvInputSessionImpl.scheduleOverlayViewCleanup(); mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_RELEASE)); } diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java index b3890d45f4d5..691df77e9541 100644 --- a/media/java/android/media/tv/TvContract.java +++ b/media/java/android/media/tv/TvContract.java @@ -1052,6 +1052,24 @@ public final class TvContract { /** The genre for Gaming. */ public static final String GAMING = "GAMING"; + /** The genre for Arts. */ + public static final String ARTS = "ARTS"; + + /** The genre for Entertainment. */ + public static final String ENTERTAINMENT = "ENTERTAINMENT"; + + /** The genre for Life Style. */ + public static final String LIFE_STYLE = "LIFE_STYLE"; + + /** The genre for Music. */ + public static final String MUSIC = "MUSIC"; + + /** The genre for Premier. */ + public static final String PREMIER = "PREMIER"; + + /** The genre for Tech/Science. */ + public static final String TECH_SCIENCE = "TECH_SCIENCE"; + private static final ArraySet<String> CANONICAL_GENRES = new ArraySet<String>(); static { CANONICAL_GENRES.add(FAMILY_KIDS); @@ -1065,6 +1083,12 @@ public final class TvContract { CANONICAL_GENRES.add(ANIMAL_WILDLIFE); CANONICAL_GENRES.add(NEWS); CANONICAL_GENRES.add(GAMING); + CANONICAL_GENRES.add(ARTS); + CANONICAL_GENRES.add(ENTERTAINMENT); + CANONICAL_GENRES.add(LIFE_STYLE); + CANONICAL_GENRES.add(MUSIC); + CANONICAL_GENRES.add(PREMIER); + CANONICAL_GENRES.add(TECH_SCIENCE); } private Genres() {} diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java index 54ebc6aad10c..b9e99d2c14a4 100644 --- a/media/java/android/media/tv/TvInputInfo.java +++ b/media/java/android/media/tv/TvInputInfo.java @@ -241,6 +241,9 @@ public final class TvInputInfo implements Parcelable { if (DEBUG) { Log.d(TAG, "Setup activity loaded. [" + input.mSetupActivity + "] for " + si.name); } + if (inputType == TYPE_TUNER && TextUtils.isEmpty(input.mSetupActivity)) { + throw new XmlPullParserException("Setup activity not found in " + si.name); + } input.mSettingsActivity = sa.getString( com.android.internal.R.styleable.TvInputService_settingsActivity); if (DEBUG) { diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index 78714d202649..51bd205dbf2d 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -159,12 +159,12 @@ public final class TvInputManager { private final Object mLock = new Object(); - // @GuardedBy(mLock) + // @GuardedBy("mLock") private final List<TvInputCallbackRecord> mCallbackRecords = new LinkedList<TvInputCallbackRecord>(); // A mapping from TV input ID to the state of corresponding input. - // @GuardedBy(mLock) + // @GuardedBy("mLock") private final Map<String, Integer> mStateMap = new ArrayMap<String, Integer>(); // A mapping from the sequence number of a session to its SessionCallbackRecord. @@ -207,7 +207,7 @@ public final class TvInputManager { /** * This is called when the channel of this session is changed by the underlying TV input - * with out any {@link TvInputManager.Session#tune(Uri)} request. + * without any {@link TvInputManager.Session#tune(Uri)} request. * * @param session A {@link TvInputManager.Session} associated with this callback. * @param channelUri The URI of a channel. @@ -227,7 +227,7 @@ public final class TvInputManager { /** * This is called when a track for a given type is selected. * - * @param session A {@link TvInputManager.Session} associated with this callback + * @param session A {@link TvInputManager.Session} associated with this callback. * @param type The type of the selected track. The type can be * {@link TvTrackInfo#TYPE_AUDIO}, {@link TvTrackInfo#TYPE_VIDEO} or * {@link TvTrackInfo#TYPE_SUBTITLE}. @@ -238,6 +238,18 @@ public final class TvInputManager { } /** + * This is invoked when the video size has been changed. It is also called when the first + * time video size information becomes available after the session is tuned to a specific + * channel. + * + * @param session A {@link TvInputManager.Session} associated with this callback. + * @param width The width of the video. + * @param height The height of the video. + */ + public void onVideoSizeChanged(Session session, int width, int height) { + } + + /** * This is called when the video is available, so the TV input starts the playback. * * @param session A {@link TvInputManager.Session} associated with this callback. @@ -312,13 +324,13 @@ public final class TvInputManager { private final Handler mHandler; private Session mSession; - public SessionCallbackRecord(SessionCallback sessionCallback, + SessionCallbackRecord(SessionCallback sessionCallback, Handler handler) { mSessionCallback = sessionCallback; mHandler = handler; } - public void postSessionCreated(final Session session) { + void postSessionCreated(final Session session) { mSession = session; mHandler.post(new Runnable() { @Override @@ -328,7 +340,7 @@ public final class TvInputManager { }); } - public void postSessionReleased() { + void postSessionReleased() { mHandler.post(new Runnable() { @Override public void run() { @@ -337,7 +349,7 @@ public final class TvInputManager { }); } - public void postChannelRetuned(final Uri channelUri) { + void postChannelRetuned(final Uri channelUri) { mHandler.post(new Runnable() { @Override public void run() { @@ -346,49 +358,34 @@ public final class TvInputManager { }); } - public void postTracksChanged(final List<TvTrackInfo> tracks) { + void postTracksChanged(final List<TvTrackInfo> tracks) { mHandler.post(new Runnable() { @Override public void run() { - mSession.mAudioTracks.clear(); - mSession.mVideoTracks.clear(); - mSession.mSubtitleTracks.clear(); - for (TvTrackInfo track : tracks) { - if (track.getType() == TvTrackInfo.TYPE_AUDIO) { - mSession.mAudioTracks.add(track); - } else if (track.getType() == TvTrackInfo.TYPE_VIDEO) { - mSession.mVideoTracks.add(track); - } else if (track.getType() == TvTrackInfo.TYPE_SUBTITLE) { - mSession.mSubtitleTracks.add(track); - } else { - // Silently ignore. - } - } mSessionCallback.onTracksChanged(mSession, tracks); } }); } - public void postTrackSelected(final int type, final String trackId) { + void postTrackSelected(final int type, final String trackId) { mHandler.post(new Runnable() { @Override public void run() { - if (type == TvTrackInfo.TYPE_AUDIO) { - mSession.mSelectedAudioTrackId = trackId; - } else if (type == TvTrackInfo.TYPE_VIDEO) { - mSession.mSelectedVideoTrackId = trackId; - } else if (type == TvTrackInfo.TYPE_SUBTITLE) { - mSession.mSelectedSubtitleTrackId = trackId; - } else { - // Silently ignore. - return; - } mSessionCallback.onTrackSelected(mSession, type, trackId); } }); } - public void postVideoAvailable() { + void postVideoSizeChanged(final int width, final int height) { + mHandler.post(new Runnable() { + @Override + public void run() { + mSessionCallback.onVideoSizeChanged(mSession, width, height); + } + }); + } + + void postVideoAvailable() { mHandler.post(new Runnable() { @Override public void run() { @@ -397,7 +394,7 @@ public final class TvInputManager { }); } - public void postVideoUnavailable(final int reason) { + void postVideoUnavailable(final int reason) { mHandler.post(new Runnable() { @Override public void run() { @@ -406,7 +403,7 @@ public final class TvInputManager { }); } - public void postContentAllowed() { + void postContentAllowed() { mHandler.post(new Runnable() { @Override public void run() { @@ -415,7 +412,7 @@ public final class TvInputManager { }); } - public void postContentBlocked(final TvContentRating rating) { + void postContentBlocked(final TvContentRating rating) { mHandler.post(new Runnable() { @Override public void run() { @@ -424,7 +421,7 @@ public final class TvInputManager { }); } - public void postLayoutSurface(final int left, final int top, final int right, + void postLayoutSurface(final int left, final int top, final int right, final int bottom) { mHandler.post(new Runnable() { @Override @@ -434,7 +431,7 @@ public final class TvInputManager { }); } - public void postSessionEvent(final String eventType, final Bundle eventArgs) { + void postSessionEvent(final String eventType, final Bundle eventArgs) { mHandler.post(new Runnable() { @Override public void run() { @@ -610,7 +607,10 @@ public final class TvInputManager { Log.e(TAG, "Callback not found for seq " + seq); return; } - record.postTracksChanged(tracks); + if (record.mSession.updateTracks(tracks)) { + record.postTracksChanged(tracks); + postVideoSizeChangedIfNeededLocked(record); + } } } @@ -622,7 +622,17 @@ public final class TvInputManager { Log.e(TAG, "Callback not found for seq " + seq); return; } - record.postTrackSelected(type, trackId); + if (record.mSession.updateTrackSelection(type, trackId)) { + record.postTrackSelected(type, trackId); + postVideoSizeChangedIfNeededLocked(record); + } + } + } + + private void postVideoSizeChangedIfNeededLocked(SessionCallbackRecord record) { + TvTrackInfo track = record.mSession.getVideoTrackToNotify(); + if (track != null) { + record.postVideoSizeChanged(track.getVideoWidth(), track.getVideoHeight()); } } @@ -778,7 +788,7 @@ public final class TvInputManager { } /** - * Returns the state of a given TV input. It retuns one of the following: + * Returns the state of a given TV input. It returns one of the following: * <ul> * <li>{@link #INPUT_STATE_CONNECTED} * <li>{@link #INPUT_STATE_CONNECTED_STANDBY} @@ -1133,12 +1143,24 @@ public final class TvInputManager { private IBinder mToken; private TvInputEventSender mSender; private InputChannel mChannel; + + private final Object mTrackLock = new Object(); + // @GuardedBy("mTrackLock") private final List<TvTrackInfo> mAudioTracks = new ArrayList<TvTrackInfo>(); + // @GuardedBy("mTrackLock") private final List<TvTrackInfo> mVideoTracks = new ArrayList<TvTrackInfo>(); + // @GuardedBy("mTrackLock") private final List<TvTrackInfo> mSubtitleTracks = new ArrayList<TvTrackInfo>(); + // @GuardedBy("mTrackLock") private String mSelectedAudioTrackId; + // @GuardedBy("mTrackLock") private String mSelectedVideoTrackId; + // @GuardedBy("mTrackLock") private String mSelectedSubtitleTrackId; + // @GuardedBy("mTrackLock") + private int mVideoWidth; + // @GuardedBy("mTrackLock") + private int mVideoHeight; private Session(IBinder token, InputChannel channel, ITvInputManager service, int userId, int seq, SparseArray<SessionCallbackRecord> sessionCallbackRecordMap) { @@ -1273,12 +1295,16 @@ public final class TvInputManager { Log.w(TAG, "The session has been already released"); return; } - mAudioTracks.clear(); - mVideoTracks.clear(); - mSubtitleTracks.clear(); - mSelectedAudioTrackId = null; - mSelectedVideoTrackId = null; - mSelectedSubtitleTrackId = null; + synchronized (mTrackLock) { + mAudioTracks.clear(); + mVideoTracks.clear(); + mSubtitleTracks.clear(); + mSelectedAudioTrackId = null; + mSelectedVideoTrackId = null; + mSelectedSubtitleTrackId = null; + mVideoWidth = 0; + mVideoHeight = 0; + } try { mService.tune(mToken, channelUri, params, mUserId); } catch (RemoteException e) { @@ -1314,23 +1340,25 @@ public final class TvInputManager { * @see #getTracks */ public void selectTrack(int type, String trackId) { - if (type == TvTrackInfo.TYPE_AUDIO) { - if (trackId != null && !containsTrack(mAudioTracks, trackId)) { - Log.w(TAG, "Invalid audio trackId: " + trackId); - return; - } - } else if (type == TvTrackInfo.TYPE_VIDEO) { - if (trackId != null && !containsTrack(mVideoTracks, trackId)) { - Log.w(TAG, "Invalid video trackId: " + trackId); - return; - } - } else if (type == TvTrackInfo.TYPE_SUBTITLE) { - if (trackId != null && !containsTrack(mSubtitleTracks, trackId)) { - Log.w(TAG, "Invalid subtitle trackId: " + trackId); - return; + synchronized (mTrackLock) { + if (type == TvTrackInfo.TYPE_AUDIO) { + if (trackId != null && !containsTrack(mAudioTracks, trackId)) { + Log.w(TAG, "Invalid audio trackId: " + trackId); + return; + } + } else if (type == TvTrackInfo.TYPE_VIDEO) { + if (trackId != null && !containsTrack(mVideoTracks, trackId)) { + Log.w(TAG, "Invalid video trackId: " + trackId); + return; + } + } else if (type == TvTrackInfo.TYPE_SUBTITLE) { + if (trackId != null && !containsTrack(mSubtitleTracks, trackId)) { + Log.w(TAG, "Invalid subtitle trackId: " + trackId); + return; + } + } else { + throw new IllegalArgumentException("invalid type: " + type); } - } else { - throw new IllegalArgumentException("invalid type: " + type); } if (mToken == null) { Log.w(TAG, "The session has been already released"); @@ -1361,21 +1389,23 @@ public final class TvInputManager { * @return the list of tracks for the given type. */ public List<TvTrackInfo> getTracks(int type) { - if (type == TvTrackInfo.TYPE_AUDIO) { - if (mAudioTracks == null) { - return null; - } - return mAudioTracks; - } else if (type == TvTrackInfo.TYPE_VIDEO) { - if (mVideoTracks == null) { - return null; - } - return mVideoTracks; - } else if (type == TvTrackInfo.TYPE_SUBTITLE) { - if (mSubtitleTracks == null) { - return null; + synchronized (mTrackLock) { + if (type == TvTrackInfo.TYPE_AUDIO) { + if (mAudioTracks == null) { + return null; + } + return new ArrayList<TvTrackInfo>(mAudioTracks); + } else if (type == TvTrackInfo.TYPE_VIDEO) { + if (mVideoTracks == null) { + return null; + } + return new ArrayList<TvTrackInfo>(mVideoTracks); + } else if (type == TvTrackInfo.TYPE_SUBTITLE) { + if (mSubtitleTracks == null) { + return null; + } + return new ArrayList<TvTrackInfo>(mSubtitleTracks); } - return mSubtitleTracks; } throw new IllegalArgumentException("invalid type: " + type); } @@ -1388,17 +1418,89 @@ public final class TvInputManager { * @see #selectTrack */ public String getSelectedTrack(int type) { - if (type == TvTrackInfo.TYPE_AUDIO) { - return mSelectedAudioTrackId; - } else if (type == TvTrackInfo.TYPE_VIDEO) { - return mSelectedVideoTrackId; - } else if (type == TvTrackInfo.TYPE_SUBTITLE) { - return mSelectedSubtitleTrackId; + synchronized (mTrackLock) { + if (type == TvTrackInfo.TYPE_AUDIO) { + return mSelectedAudioTrackId; + } else if (type == TvTrackInfo.TYPE_VIDEO) { + return mSelectedVideoTrackId; + } else if (type == TvTrackInfo.TYPE_SUBTITLE) { + return mSelectedSubtitleTrackId; + } } throw new IllegalArgumentException("invalid type: " + type); } /** + * Responds to onTracksChanged() and updates the internal track information. Returns true if + * there is an update. + */ + boolean updateTracks(List<TvTrackInfo> tracks) { + synchronized (mTrackLock) { + mAudioTracks.clear(); + mVideoTracks.clear(); + mSubtitleTracks.clear(); + for (TvTrackInfo track : tracks) { + if (track.getType() == TvTrackInfo.TYPE_AUDIO) { + mAudioTracks.add(track); + } else if (track.getType() == TvTrackInfo.TYPE_VIDEO) { + mVideoTracks.add(track); + } else if (track.getType() == TvTrackInfo.TYPE_SUBTITLE) { + mSubtitleTracks.add(track); + } + } + return !mAudioTracks.isEmpty() || !mVideoTracks.isEmpty() + || !mSubtitleTracks.isEmpty(); + } + } + + /** + * Responds to onTrackSelected() and updates the internal track selection information. + * Returns true if there is an update. + */ + boolean updateTrackSelection(int type, String trackId) { + synchronized (mTrackLock) { + if (type == TvTrackInfo.TYPE_AUDIO && trackId != mSelectedAudioTrackId) { + mSelectedAudioTrackId = trackId; + return true; + } else if (type == TvTrackInfo.TYPE_VIDEO && trackId != mSelectedVideoTrackId) { + mSelectedVideoTrackId = trackId; + return true; + } else if (type == TvTrackInfo.TYPE_SUBTITLE + && trackId != mSelectedSubtitleTrackId) { + mSelectedSubtitleTrackId = trackId; + return true; + } + } + return false; + } + + /** + * Returns the new/updated video track that contains new video size information. Returns + * null if there is no video track to notify. Subsequent calls of this method results in a + * non-null video track returned only by the first call and null returned by following + * calls. The caller should immediately notify of the video size change upon receiving the + * track. + */ + TvTrackInfo getVideoTrackToNotify() { + synchronized (mTrackLock) { + if (!mVideoTracks.isEmpty() && mSelectedVideoTrackId != null) { + for (TvTrackInfo track : mVideoTracks) { + if (track.getId().equals(mSelectedVideoTrackId)) { + int videoWidth = track.getVideoWidth(); + int videoHeight = track.getVideoHeight(); + if (mVideoWidth != videoWidth || mVideoHeight != videoHeight) { + mVideoWidth = videoWidth; + mVideoHeight = videoHeight; + return track; + } + } + } + } + } + return null; + } + + /** * Calls {@link TvInputService.Session#appPrivateCommand(String, Bundle) * TvInputService.Session.appPrivateCommand()} on the current TvView. * diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java index 4f8facbbd502..0ca5810f1002 100644 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -25,10 +25,12 @@ import android.graphics.PixelFormat; import android.graphics.Rect; import android.hardware.hdmi.HdmiDeviceInfo; import android.net.Uri; +import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; +import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.text.TextUtils; @@ -44,10 +46,12 @@ import android.view.Surface; import android.view.View; import android.view.WindowManager; import android.view.accessibility.CaptioningManager; +import android.widget.FrameLayout; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.SomeArgs; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -241,16 +245,25 @@ public abstract class TvInputService extends Service { * Base class for derived classes to implement to provide a TV input session. */ public abstract static class Session implements KeyEvent.Callback { + private static final int DETACH_OVERLAY_VIEW_TIMEOUT = 5000; private final KeyEvent.DispatcherState mDispatcherState = new KeyEvent.DispatcherState(); private final WindowManager mWindowManager; final Handler mHandler; private WindowManager.LayoutParams mWindowParams; private Surface mSurface; + private Context mContext; + private FrameLayout mOverlayViewContainer; private View mOverlayView; + private OverlayViewCleanUpTask mOverlayViewCleanUpTask; private boolean mOverlayViewEnabled; private IBinder mWindowToken; private Rect mOverlayFrame; + + private Object mLock = new Object(); + // @GuardedBy("mLock") private ITvInputSessionCallback mSessionCallback; + // @GuardedBy("mLock") + private List<Runnable> mPendingActions = new ArrayList<>(); /** * Creates a new Session. @@ -258,6 +271,7 @@ public abstract class TvInputService extends Service { * @param context The context of the application */ public Session(Context context) { + mContext = context; mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); mHandler = new Handler(context.getMainLooper()); } @@ -295,11 +309,12 @@ public abstract class TvInputService extends Service { * @param eventArgs Optional arguments of the event. * @hide */ + @SystemApi public void notifySessionEvent(final String eventType, final Bundle eventArgs) { if (eventType == null) { throw new IllegalArgumentException("eventType should not be null."); } - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -318,7 +333,7 @@ public abstract class TvInputService extends Service { * @param channelUri The URI of a channel. */ public void notifyChannelRetuned(final Uri channelUri) { - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -332,8 +347,13 @@ public abstract class TvInputService extends Service { } /** - * Sends the change on the track information. This is expected to be called whenever a track - * is added/removed and the metadata of a track is modified. + * Sends the list of all audio/video/subtitle tracks. The is used by the framework to + * maintain the track information for a given session, which in turn is used by + * {@link TvView#getTracks} for the application to retrieve metadata for a given track type. + * The TV input service must call this method as soon as the track information becomes + * available or is updated. Note that in a case where a part of the information for a + * certain track is updated, it is not necessary to create a new {@link TvTrackInfo} object + * with a different track ID. * * @param tracks A list which includes track information. * @throws IllegalArgumentException if {@code tracks} contains redundant tracks. @@ -350,7 +370,7 @@ public abstract class TvInputService extends Service { trackIdSet.clear(); // TODO: Validate the track list. - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -364,8 +384,12 @@ public abstract class TvInputService extends Service { } /** - * Sends the ID of the selected track for a given track type. This is expected to be called - * whenever there is a change on track selection. + * Sends the type and ID of a selected track. This is used to inform the application that a + * specific track is selected. The TV input service must call this method as soon as a track + * is selected either by default or in response to a call to {@link #onSelectTrack}. The + * selected track ID for a given type is maintained in the framework until the next call to + * this method even after the entire track list is updated (but is reset when the session is + * tuned to a new channel), so care must be taken not to result in an obsolete track ID. * * @param type The type of the selected track. The type can be * {@link TvTrackInfo#TYPE_AUDIO}, {@link TvTrackInfo#TYPE_VIDEO} or @@ -374,7 +398,7 @@ public abstract class TvInputService extends Service { * @see #onSelectTrack */ public void notifyTrackSelected(final int type, final String trackId) { - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -395,7 +419,7 @@ public abstract class TvInputService extends Service { * @see #notifyVideoUnavailable */ public void notifyVideoAvailable() { - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -427,7 +451,7 @@ public abstract class TvInputService extends Service { || reason > TvInputManager.VIDEO_UNAVAILABLE_REASON_END) { throw new IllegalArgumentException("Unknown reason: " + reason); } - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -466,7 +490,7 @@ public abstract class TvInputService extends Service { * @see TvInputManager */ public void notifyContentAllowed() { - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -506,7 +530,7 @@ public abstract class TvInputService extends Service { * @see TvInputManager */ public void notifyContentBlocked(final TvContentRating rating) { - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -535,7 +559,7 @@ public abstract class TvInputService extends Service { if (left > right || top > bottm) { throw new IllegalArgumentException("Invalid parameter"); } - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -837,12 +861,18 @@ public abstract class TvInputService extends Service { * session. */ void release() { - removeOverlayView(true); onRelease(); if (mSurface != null) { mSurface.release(); mSurface = null; } + synchronized(mLock) { + mSessionCallback = null; + mPendingActions.clear(); + } + // Removes the overlay view lastly so that any hanging on the main thread can be handled + // in {@link #scheduleOverlayViewCleanup}. + removeOverlayView(true); } /** @@ -927,9 +957,8 @@ public abstract class TvInputService extends Service { * @param frame A position of the overlay view. */ void createOverlayView(IBinder windowToken, Rect frame) { - if (mOverlayView != null) { - mWindowManager.removeView(mOverlayView); - mOverlayView = null; + if (mOverlayViewContainer != null) { + removeOverlayView(false); } if (DEBUG) Log.d(TAG, "create overlay view(" + frame + ")"); mWindowToken = windowToken; @@ -942,6 +971,15 @@ public abstract class TvInputService extends Service { if (mOverlayView == null) { return; } + if (mOverlayViewCleanUpTask != null) { + mOverlayViewCleanUpTask.cancel(true); + mOverlayViewCleanUpTask = null; + } + // Creates a container view to check hanging on the overlay view detaching. + // Adding/removing the overlay view to/from the container make the view attach/detach + // logic run on the main thread. + mOverlayViewContainer = new FrameLayout(mContext); + mOverlayViewContainer.addView(mOverlayView); // TvView's window type is TYPE_APPLICATION_MEDIA and we want to create // an overlay window above the media window but below the application window. int type = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY; @@ -958,7 +996,7 @@ public abstract class TvInputService extends Service { WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; mWindowParams.gravity = Gravity.START | Gravity.TOP; mWindowParams.token = windowToken; - mWindowManager.addView(mOverlayView, mWindowParams); + mWindowManager.addView(mOverlayViewContainer, mWindowParams); } /** @@ -975,33 +1013,51 @@ public abstract class TvInputService extends Service { onOverlayViewSizeChanged(frame.right - frame.left, frame.bottom - frame.top); } mOverlayFrame = frame; - if (!mOverlayViewEnabled || mOverlayView == null) { + if (!mOverlayViewEnabled || mOverlayViewContainer == null) { return; } mWindowParams.x = frame.left; mWindowParams.y = frame.top; mWindowParams.width = frame.right - frame.left; mWindowParams.height = frame.bottom - frame.top; - mWindowManager.updateViewLayout(mOverlayView, mWindowParams); + mWindowManager.updateViewLayout(mOverlayViewContainer, mWindowParams); } /** * Removes the current overlay view. */ void removeOverlayView(boolean clearWindowToken) { - if (DEBUG) Log.d(TAG, "removeOverlayView(" + mOverlayView + ")"); + if (DEBUG) Log.d(TAG, "removeOverlayView(" + mOverlayViewContainer + ")"); if (clearWindowToken) { mWindowToken = null; mOverlayFrame = null; } - if (mOverlayView != null) { - mWindowManager.removeView(mOverlayView); + if (mOverlayViewContainer != null) { + // Removes the overlay view from the view hierarchy in advance so that it can be + // cleaned up in the {@link OverlayViewCleanUpTask} if the remove process is + // hanging. + mOverlayViewContainer.removeView(mOverlayView); mOverlayView = null; + mWindowManager.removeView(mOverlayViewContainer); + mOverlayViewContainer = null; mWindowParams = null; } } /** + * Schedules a task which checks whether the overlay view is detached and kills the process + * if it is not. Note that this method is expected to be called in a non-main thread. + */ + void scheduleOverlayViewCleanup() { + View overlayViewParent = mOverlayViewContainer; + if (overlayViewParent != null) { + mOverlayViewCleanUpTask = new OverlayViewCleanUpTask(); + mOverlayViewCleanUpTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, + overlayViewParent); + } + } + + /** * Takes care of dispatching incoming input events and tells whether the event was handled. */ int dispatchInputEvent(InputEvent event, InputEventReceiver receiver) { @@ -1030,46 +1086,89 @@ public abstract class TvInputService extends Service { } } } - if (mOverlayView == null || !mOverlayView.isAttachedToWindow()) { + if (mOverlayViewContainer == null || !mOverlayViewContainer.isAttachedToWindow()) { return TvInputManager.Session.DISPATCH_NOT_HANDLED; } - if (!mOverlayView.hasWindowFocus()) { - mOverlayView.getViewRootImpl().windowFocusChanged(true, true); + if (!mOverlayViewContainer.hasWindowFocus()) { + mOverlayViewContainer.getViewRootImpl().windowFocusChanged(true, true); } - if (isNavigationKey && mOverlayView.hasFocusable()) { + if (isNavigationKey && mOverlayViewContainer.hasFocusable()) { // If mOverlayView has focusable views, navigation key events should be always // handled. If not, it can make the application UI navigation messed up. // For example, in the case that the left-most view is focused, a left key event // will not be handled in ViewRootImpl. Then, the left key event will be handled in // the application during the UI navigation of the TV input. - mOverlayView.getViewRootImpl().dispatchInputEvent(event); + mOverlayViewContainer.getViewRootImpl().dispatchInputEvent(event); return TvInputManager.Session.DISPATCH_HANDLED; } else { - mOverlayView.getViewRootImpl().dispatchInputEvent(event, receiver); + mOverlayViewContainer.getViewRootImpl().dispatchInputEvent(event, receiver); return TvInputManager.Session.DISPATCH_IN_PROGRESS; } } - private void setSessionCallback(ITvInputSessionCallback callback) { - mSessionCallback = callback; + private void initialize(ITvInputSessionCallback callback) { + synchronized(mLock) { + mSessionCallback = callback; + for (Runnable runnable : mPendingActions) { + runnable.run(); + } + mPendingActions.clear(); + } } - private final void runOnMainThread(Runnable action) { - if (mHandler.getLooper().isCurrentThread() && mSessionCallback != null) { - action.run(); - } else { - // Posts the runnable if this is not called from the main thread or the session - // is not initialized yet. - mHandler.post(action); + private final void executeOrPostRunnable(Runnable action) { + synchronized(mLock) { + if (mSessionCallback == null) { + // The session is not initialized yet. + mPendingActions.add(action); + } else { + if (mHandler.getLooper().isCurrentThread()) { + action.run(); + } else { + // Posts the runnable if this is not called from the main thread + mHandler.post(action); + } + } + } + } + + private final class OverlayViewCleanUpTask extends AsyncTask<View, Void, Void> { + @Override + protected Void doInBackground(View... views) { + View overlayViewParent = views[0]; + try { + Thread.sleep(DETACH_OVERLAY_VIEW_TIMEOUT); + } catch (InterruptedException e) { + return null; + } + if (isCancelled()) { + return null; + } + if (overlayViewParent.isAttachedToWindow()) { + Log.e(TAG, "Time out on releasing overlay view. Killing " + + overlayViewParent.getContext().getPackageName()); + Process.killProcess(Process.myPid()); + } + return null; } } } /** * Base class for a TV input session which represents an external device connected to a - * hardware TV input. Once TV input returns an implementation of this class on - * {@link #onCreateSession(String)}, the framework will create a hardware session and forward - * the application's surface to the hardware TV input. + * hardware TV input. + * <p> + * This class is for an input which provides channels for the external set-top box to the + * application. Once a TV input returns an implementation of this class on + * {@link #onCreateSession(String)}, the framework will create a separate session for + * a hardware TV Input (e.g. HDMI 1) and forward the application's surface to the session so + * that the user can see the screen of the hardware TV Input when she tunes to a channel from + * this TV input. The implementation of this class is expected to change the channel of the + * external set-top box via a proprietary protocol when {@link HardwareSession#onTune(Uri)} is + * requested by the application. + * </p><p> + * Note that this class is not for inputs for internal hardware like built-in tuner and HDMI 1. + * </p> * @see #onCreateSession(String) */ public abstract static class HardwareSession extends Session { @@ -1106,13 +1205,15 @@ public abstract class TvInputService extends Service { mHardwareSession = session; SomeArgs args = SomeArgs.obtain(); if (session != null) { - args.arg1 = mProxySession; - args.arg2 = mProxySessionCallback; - args.arg3 = session.getToken(); + args.arg1 = HardwareSession.this; + args.arg2 = mProxySession; + args.arg3 = mProxySessionCallback; + args.arg4 = session.getToken(); } else { args.arg1 = null; - args.arg2 = mProxySessionCallback; - args.arg3 = null; + args.arg2 = null; + args.arg3 = mProxySessionCallback; + args.arg4 = null; onRelease(); } mServiceHandler.obtainMessage(ServiceHandler.DO_NOTIFY_SESSION_CREATED, args) @@ -1250,7 +1351,6 @@ public abstract class TvInputService extends Service { } return; } - sessionImpl.setSessionCallback(cb); ITvInputSession stub = new ITvInputSessionWrapper(TvInputService.this, sessionImpl, channel); if (sessionImpl instanceof HardwareSession) { @@ -1281,9 +1381,10 @@ public abstract class TvInputService extends Service { proxySession.mHardwareSessionCallback, mServiceHandler); } else { SomeArgs someArgs = SomeArgs.obtain(); - someArgs.arg1 = stub; - someArgs.arg2 = cb; - someArgs.arg3 = null; + someArgs.arg1 = sessionImpl; + someArgs.arg2 = stub; + someArgs.arg3 = cb; + someArgs.arg4 = null; mServiceHandler.obtainMessage(ServiceHandler.DO_NOTIFY_SESSION_CREATED, someArgs).sendToTarget(); } @@ -1291,14 +1392,18 @@ public abstract class TvInputService extends Service { } case DO_NOTIFY_SESSION_CREATED: { SomeArgs args = (SomeArgs) msg.obj; - ITvInputSession stub = (ITvInputSession) args.arg1; - ITvInputSessionCallback cb = (ITvInputSessionCallback) args.arg2; - IBinder hardwareSessionToken = (IBinder) args.arg3; + Session sessionImpl = (Session) args.arg1; + ITvInputSession stub = (ITvInputSession) args.arg2; + ITvInputSessionCallback cb = (ITvInputSessionCallback) args.arg3; + IBinder hardwareSessionToken = (IBinder) args.arg4; try { cb.onSessionCreated(stub, hardwareSessionToken); } catch (RemoteException e) { Log.e(TAG, "error in onSessionCreated"); } + if (sessionImpl != null) { + sessionImpl.initialize(cb); + } args.recycle(); return; } diff --git a/media/java/android/media/tv/TvStreamConfig.java b/media/java/android/media/tv/TvStreamConfig.java index a7e7e44ac6e6..1bdc63eb0e97 100644 --- a/media/java/android/media/tv/TvStreamConfig.java +++ b/media/java/android/media/tv/TvStreamConfig.java @@ -33,7 +33,6 @@ public class TvStreamConfig implements Parcelable { private int mStreamId; private int mType; - // TODO: Revisit if max widht/height really make sense. private int mMaxWidth; private int mMaxHeight; /** @@ -166,4 +165,17 @@ public class TvStreamConfig implements Parcelable { return config; } } + + @Override + public boolean equals(Object obj) { + if (obj == null) return false; + if (!(obj instanceof TvStreamConfig)) return false; + + TvStreamConfig config = (TvStreamConfig) obj; + return config.mGeneration == mGeneration + && config.mStreamId == mStreamId + && config.mType == mType + && config.mMaxWidth == mMaxWidth + && config.mMaxHeight == mMaxHeight; + } } diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java index 0949b1af9dc8..f9d84c1b037f 100644 --- a/media/java/android/media/tv/TvView.java +++ b/media/java/android/media/tv/TvView.java @@ -59,8 +59,6 @@ public class TvView extends ViewGroup { private static final String TAG = "TvView"; private static final boolean DEBUG = false; - private static final int VIDEO_SIZE_VALUE_UNKNOWN = 0; - private static final int ZORDER_MEDIA = 0; private static final int ZORDER_MEDIA_OVERLAY = 1; private static final int ZORDER_ON_TOP = 2; @@ -69,7 +67,7 @@ public class TvView extends ViewGroup { private static final int CAPTION_ENABLED = 1; private static final int CAPTION_DISABLED = 2; - private static final WeakReference<TvView> NULL_TV_VIEW = new WeakReference(null); + private static final WeakReference<TvView> NULL_TV_VIEW = new WeakReference<>(null); private static final Object sMainTvViewLock = new Object(); private static WeakReference<TvView> sMainTvView = NULL_TV_VIEW; @@ -86,8 +84,10 @@ public class TvView extends ViewGroup { private OnUnhandledInputEventListener mOnUnhandledInputEventListener; private boolean mHasStreamVolume; private float mStreamVolume; - private int mVideoWidth = VIDEO_SIZE_VALUE_UNKNOWN; - private int mVideoHeight = VIDEO_SIZE_VALUE_UNKNOWN; + private int mCaptionEnabled; + private String mAppPrivateCommandAction; + private Bundle mAppPrivateCommandData; + private boolean mSurfaceChanged; private int mSurfaceFormat; private int mSurfaceWidth; @@ -100,7 +100,6 @@ public class TvView extends ViewGroup { private int mSurfaceViewRight; private int mSurfaceViewTop; private int mSurfaceViewBottom; - private int mCaptionEnabled; private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() { @Override @@ -197,7 +196,7 @@ public class TvView extends ViewGroup { @SystemApi public void setMain() { synchronized (sMainTvViewLock) { - sMainTvView = new WeakReference(this); + sMainTvView = new WeakReference<>(this); if (hasWindowFocus() && mSession != null) { mSession.setMain(); } @@ -291,7 +290,7 @@ public class TvView extends ViewGroup { } synchronized (sMainTvViewLock) { if (sMainTvView.get() == null) { - sMainTvView = new WeakReference(this); + sMainTvView = new WeakReference<>(this); } } if (mSessionCallback != null && mSessionCallback.mInputId.equals(inputId)) { @@ -421,10 +420,10 @@ public class TvView extends ViewGroup { * Calls {@link TvInputService.Session#appPrivateCommand(String, Bundle) * TvInputService.Session.appPrivateCommand()} on the current TvView. * - * @param action Name of the command to be performed. This <em>must</em> be a scoped name, i.e. - * prefixed with a package name you own, so that different developers will not create - * conflicting commands. - * @param data Any data to include with the command. + * @param action The name of the private command to send. This <em>must</em> be a scoped name, + * i.e. prefixed with a package name you own, so that different developers will not + * create conflicting commands. + * @param data An optional bundle to send with the command. * @hide */ @SystemApi @@ -434,6 +433,13 @@ public class TvView extends ViewGroup { } if (mSession != null) { mSession.sendAppPrivateCommand(action, data); + } else { + Log.w(TAG, "sendAppPrivateCommand - session not created (action " + action + " cached)"); + if (mAppPrivateCommandAction != null) { + Log.w(TAG, "previous cached action " + action + " removed"); + } + mAppPrivateCommandAction = action; + mAppPrivateCommandData = data; } } @@ -619,6 +625,9 @@ public class TvView extends ViewGroup { } private void release() { + mAppPrivateCommandAction = null; + mAppPrivateCommandData = null; + setSessionSurface(null); removeSessionOverlayView(); mUseRequestedSurfaceLayout = false; @@ -703,19 +712,8 @@ public class TvView extends ViewGroup { } /** - * This is invoked when the view is tuned to a specific channel and starts decoding video - * stream from there. It is also called later when the video size is changed. - * - * @param inputId The ID of the TV input bound to this view. - * @param width The width of the video. - * @param height The height of the video. - */ - public void onVideoSizeChanged(String inputId, int width, int height) { - } - - /** * This is invoked when the channel of this TvView is changed by the underlying TV input - * with out any {@link TvView#tune(String, Uri)} request. + * without any {@link TvView#tune(String, Uri)} request. * * @param inputId The ID of the TV input bound to this view. * @param channelUri The URI of a channel. @@ -745,6 +743,18 @@ public class TvView extends ViewGroup { } /** + * This is invoked when the video size has been changed. It is also called when the first + * time video size information becomes available after this view is tuned to a specific + * channel. + * + * @param inputId The ID of the TV input bound to this view. + * @param width The width of the video. + * @param height The height of the video. + */ + public void onVideoSizeChanged(String inputId, int width, int height) { + } + + /** * This is called when the video is available, so the TV input starts the playback. * * @param inputId The ID of the TV input bound to this view. @@ -828,16 +838,17 @@ public class TvView extends ViewGroup { @Override public void onSessionCreated(Session session) { + if (DEBUG) { + Log.d(TAG, "onSessionCreated()"); + } if (this != mSessionCallback) { + Log.w(TAG, "onSessionCreated - session already created"); // This callback is obsolete. if (session != null) { session.release(); } return; } - if (DEBUG) { - Log.d(TAG, "onSessionCreated()"); - } mSession = session; if (session != null) { synchronized (sMainTvViewLock) { @@ -862,6 +873,12 @@ public class TvView extends ViewGroup { if (mHasStreamVolume) { mSession.setStreamVolume(mStreamVolume); } + if (mAppPrivateCommandAction != null) { + mSession.sendAppPrivateCommand( + mAppPrivateCommandAction, mAppPrivateCommandData); + mAppPrivateCommandAction = null; + mAppPrivateCommandData = null; + } } else { mSessionCallback = null; if (mCallback != null) { @@ -872,7 +889,11 @@ public class TvView extends ViewGroup { @Override public void onSessionReleased(Session session) { + if (DEBUG) { + Log.d(TAG, "onSessionReleased()"); + } if (this != mSessionCallback) { + Log.w(TAG, "onSessionReleased - session not created"); return; } mOverlayViewCreated = false; @@ -886,12 +907,13 @@ public class TvView extends ViewGroup { @Override public void onChannelRetuned(Session session, Uri channelUri) { - if (this != mSessionCallback) { - return; - } if (DEBUG) { Log.d(TAG, "onChannelChangedByTvInput(" + channelUri + ")"); } + if (this != mSessionCallback) { + Log.w(TAG, "onChannelRetuned - session not created"); + return; + } if (mCallback != null) { mCallback.onChannelRetuned(mInputId, channelUri); } @@ -899,12 +921,13 @@ public class TvView extends ViewGroup { @Override public void onTracksChanged(Session session, List<TvTrackInfo> tracks) { + if (DEBUG) { + Log.d(TAG, "onTracksChanged(" + tracks + ")"); + } if (this != mSessionCallback) { + Log.w(TAG, "onTracksChanged - session not created"); return; } - if (DEBUG) { - Log.d(TAG, "onTracksChanged()"); - } if (mCallback != null) { mCallback.onTracksChanged(mInputId, tracks); } @@ -912,26 +935,41 @@ public class TvView extends ViewGroup { @Override public void onTrackSelected(Session session, int type, String trackId) { + if (DEBUG) { + Log.d(TAG, "onTrackSelected(type=" + type + ", trackId=" + trackId + ")"); + } if (this != mSessionCallback) { + Log.w(TAG, "onTrackSelected - session not created"); return; } - if (DEBUG) { - Log.d(TAG, "onTrackSelected()"); - } - // TODO: Update the video size when the type is TYPE_VIDEO. if (mCallback != null) { mCallback.onTrackSelected(mInputId, type, trackId); } } @Override - public void onVideoAvailable(Session session) { + public void onVideoSizeChanged(Session session, int width, int height) { + if (DEBUG) { + Log.d(TAG, "onVideoSizeChanged()"); + } if (this != mSessionCallback) { + Log.w(TAG, "onVideoSizeChanged - session not created"); return; } + if (mCallback != null) { + mCallback.onVideoSizeChanged(mInputId, width, height); + } + } + + @Override + public void onVideoAvailable(Session session) { if (DEBUG) { Log.d(TAG, "onVideoAvailable()"); } + if (this != mSessionCallback) { + Log.w(TAG, "onVideoAvailable - session not created"); + return; + } if (mCallback != null) { mCallback.onVideoAvailable(mInputId); } @@ -939,12 +977,13 @@ public class TvView extends ViewGroup { @Override public void onVideoUnavailable(Session session, int reason) { + if (DEBUG) { + Log.d(TAG, "onVideoUnavailable(reason=" + reason + ")"); + } if (this != mSessionCallback) { + Log.w(TAG, "onVideoUnavailable - session not created"); return; } - if (DEBUG) { - Log.d(TAG, "onVideoUnavailable(" + reason + ")"); - } if (mCallback != null) { mCallback.onVideoUnavailable(mInputId, reason); } @@ -952,12 +991,13 @@ public class TvView extends ViewGroup { @Override public void onContentAllowed(Session session) { - if (this != mSessionCallback) { - return; - } if (DEBUG) { Log.d(TAG, "onContentAllowed()"); } + if (this != mSessionCallback) { + Log.w(TAG, "onContentAllowed - session not created"); + return; + } if (mCallback != null) { mCallback.onContentAllowed(mInputId); } @@ -965,12 +1005,13 @@ public class TvView extends ViewGroup { @Override public void onContentBlocked(Session session, TvContentRating rating) { + if (DEBUG) { + Log.d(TAG, "onContentBlocked(rating=" + rating + ")"); + } if (this != mSessionCallback) { + Log.w(TAG, "onContentBlocked - session not created"); return; } - if (DEBUG) { - Log.d(TAG, "onContentBlocked()"); - } if (mCallback != null) { mCallback.onContentBlocked(mInputId, rating); } @@ -978,13 +1019,14 @@ public class TvView extends ViewGroup { @Override public void onLayoutSurface(Session session, int left, int top, int right, int bottom) { - if (this != mSessionCallback) { - return; - } if (DEBUG) { Log.d(TAG, "onLayoutSurface (left=" + left + ", top=" + top + ", right=" + right + ", bottom=" + bottom + ",)"); } + if (this != mSessionCallback) { + Log.w(TAG, "onLayoutSurface - session not created"); + return; + } mSurfaceViewLeft = left; mSurfaceViewTop = top; mSurfaceViewRight = right; @@ -995,12 +1037,13 @@ public class TvView extends ViewGroup { @Override public void onSessionEvent(Session session, String eventType, Bundle eventArgs) { - if (this != mSessionCallback) { - return; - } if (DEBUG) { Log.d(TAG, "onSessionEvent(" + eventType + ")"); } + if (this != mSessionCallback) { + Log.w(TAG, "onSessionEvent - session not created"); + return; + } if (mCallback != null) { mCallback.onEvent(mInputId, eventType, eventArgs); } diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp index 19b54a6d8f78..62b4a3693a37 100644 --- a/media/jni/android_mtp_MtpDatabase.cpp +++ b/media/jni/android_mtp_MtpDatabase.cpp @@ -207,7 +207,8 @@ MyMtpDatabase::MyMtpDatabase(JNIEnv *env, jobject client) return; // Already threw. } mLongBuffer = (jlongArray)env->NewGlobalRef(longArray); - jcharArray charArray = env->NewCharArray(256); + // Needs to be long enough to hold a file path for getObjectFilePath() + jcharArray charArray = env->NewCharArray(PATH_MAX + 1); if (!charArray) { return; // Already threw. } @@ -761,7 +762,7 @@ MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle, return result; } -static void foreachentry(ExifEntry *entry, void *user) { +static void foreachentry(ExifEntry *entry, void * /*user*/) { char buf[1024]; ALOGI("entry %x, format %d, size %d: %s", entry->tag, entry->format, entry->size, exif_entry_get_value(entry, buf, sizeof(buf))); diff --git a/media/tests/omxjpegdecoder/Android.mk b/media/tests/omxjpegdecoder/Android.mk deleted file mode 100644 index b0bc5d4a2e36..000000000000 --- a/media/tests/omxjpegdecoder/Android.mk +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (C) 2009 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. - -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - omx_jpeg_decoder.cpp \ - jpeg_decoder_bench.cpp \ - StreamSource.cpp - -LOCAL_SHARED_LIBRARIES := \ - libcutils \ - libskia \ - libstagefright \ - libstagefright_foundation \ - libbinder \ - libutils \ - liblog \ - libjpeg - -LOCAL_C_INCLUDES := \ - $(TOP)/external/jpeg \ - $(TOP)/frameworks/base/media/libstagefright \ - $(TOP)/frameworks/base/include/ \ - $(TOP)/frameworks/base/ \ - $(TOP)/frameworks/native/include/media/openmax - -LOCAL_MODULE := jpeg_bench - -LOCAL_MODULE_TAGS := optional - -include $(BUILD_EXECUTABLE) diff --git a/media/tests/omxjpegdecoder/StreamSource.cpp b/media/tests/omxjpegdecoder/StreamSource.cpp deleted file mode 100644 index f764121a0dff..000000000000 --- a/media/tests/omxjpegdecoder/StreamSource.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -#include <media/stagefright/foundation/ADebug.h> - -#include "StreamSource.h" - -namespace android { - -StreamSource::StreamSource(SkStream *stream) - : mStream(stream) { - CHECK(stream != NULL); - mSize = stream->getLength(); -} - -StreamSource::~StreamSource() { - delete mStream; - mStream = NULL; -} - -status_t StreamSource::initCheck() const { - return mStream != NULL ? OK : NO_INIT; -} - -ssize_t StreamSource::readAt(off64_t offset, void *data, size_t size) { - Mutex::Autolock autoLock(mLock); - - mStream->rewind(); - mStream->skip(offset); - ssize_t result = mStream->read(data, size); - - return result; -} - -status_t StreamSource::getSize(off64_t *size) { - *size = mSize; - return OK; -} - -} // namespace android diff --git a/media/tests/omxjpegdecoder/StreamSource.h b/media/tests/omxjpegdecoder/StreamSource.h deleted file mode 100644 index 980738590587..000000000000 --- a/media/tests/omxjpegdecoder/StreamSource.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -#ifndef STREAM_SOURCE_H_ - -#define STREAM_SOURCE_H_ - -#include <stdio.h> - -#include <SkStream.h> -#include <media/stagefright/DataSource.h> -#include <media/stagefright/MediaErrors.h> -#include <utils/threads.h> - -namespace android { - -class StreamSource : public DataSource { -public: - // Pass the ownership of SkStream to StreamSource. - StreamSource(SkStream *SkStream); - virtual status_t initCheck() const; - virtual ssize_t readAt(off64_t offset, void *data, size_t size); - virtual status_t getSize(off64_t *size); - -protected: - virtual ~StreamSource(); - -private: - SkStream *mStream; - size_t mSize; - Mutex mLock; - - StreamSource(const StreamSource &); - StreamSource &operator=(const StreamSource &); -}; - -} // namespace android - -#endif // STREAM_SOURCE_H_ diff --git a/media/tests/omxjpegdecoder/jpeg_decoder_bench.cpp b/media/tests/omxjpegdecoder/jpeg_decoder_bench.cpp deleted file mode 100644 index de6294dabaeb..000000000000 --- a/media/tests/omxjpegdecoder/jpeg_decoder_bench.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -#define LOG_TAG "OmxJpegDecoder" -#include <sys/time.h> -#include <utils/Log.h> - -#include <binder/ProcessState.h> - -#include "SkBitmap.h" -#include "SkImageDecoder.h" -#include "SkStream.h" -#include "omx_jpeg_decoder.h" - -class SkJPEGImageDecoder : public SkImageDecoder { -public: - virtual Format getFormat() const { - return kJPEG_Format; - } - -protected: - virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode); -}; - -int nullObjectReturn(const char msg[]) { - if (msg) { - SkDebugf("--- %s\n", msg); - } - return -1; -} - -static int64_t getNowUs() { - struct timeval tv; - gettimeofday(&tv, NULL); - - return tv.tv_usec + (int64_t) tv.tv_sec * 1000000; -} - -int testDecodeBounds(SkImageDecoder* decoder, SkStream* stream, - SkBitmap* bitmap) { - int64_t startTime = getNowUs(); - SkColorType prefColorType = kN32_SkColorType; - SkImageDecoder::Mode decodeMode = SkImageDecoder::kDecodeBounds_Mode; - - // Decode the input stream and then use the bitmap. - if (!decoder->decode(stream, bitmap, prefColorType, decodeMode)) { - return nullObjectReturn("decoder->decode returned false"); - } else { - int64_t delay = getNowUs() - startTime; - printf("WidthxHeight: %dx%d\n", bitmap->width(), bitmap->height()); - printf("Decoding Time in BoundsMode %.1f msec.\n", delay / 1000.0f); - return 0; - } -} - -int testDecodePixels(SkImageDecoder* decoder, SkStream* stream, - SkBitmap* bitmap) { - int64_t startTime = getNowUs(); - SkColorType prefColorType = kN32_SkColorType; - SkImageDecoder::Mode decodeMode = SkImageDecoder::kDecodePixels_Mode; - - // Decode the input stream and then use the bitmap. - if (!decoder->decode(stream, bitmap, prefColorType, decodeMode)) { - return nullObjectReturn("decoder->decode returned false"); - } else { - int64_t delay = getNowUs() - startTime; - printf("Decoding Time in PixelsMode %.1f msec.\n", delay / 1000.0f); - const char* filename = "/sdcard/omxJpegDecodedBitmap.rgba"; - return storeBitmapToFile(bitmap, filename); - } -} - -int testDecoder(SkImageDecoder* decoder, char* filename) { - // test DecodeMode == Pixels - SkStream* stream = new SkFILEStream(filename); - SkBitmap* bitmap = new SkBitmap; - testDecodePixels(decoder, stream, bitmap); - delete bitmap; - - // test DecodeMode == Bounds - stream = new SkFILEStream(filename); - bitmap = new SkBitmap; - testDecodeBounds(decoder, stream, bitmap); - delete bitmap; - - delete decoder; - return 0; -} - -int main(int argc, char** argv) { - android::ProcessState::self()->startThreadPool(); - - printf("Decoding jpeg with libjpeg...\n"); - SkJPEGImageDecoder* libjpeg = new SkJPEGImageDecoder; - testDecoder(libjpeg, argv[1]); - - printf("\nDecoding jpeg with OMX...\n"); - OmxJpegImageDecoder* omx = new OmxJpegImageDecoder; - testDecoder(omx, argv[1]); - return 0; -} diff --git a/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp b/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp deleted file mode 100644 index 229bfdb1a655..000000000000 --- a/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -#define LOG_TAG "OmxJpegDecoder" -#include <sys/time.h> -#include <utils/Log.h> - -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <binder/IServiceManager.h> -#include <binder/ProcessState.h> -#include <media/IMediaPlayerService.h> -#include <media/stagefright/foundation/ADebug.h> -#include <media/stagefright/MediaSource.h> -#include <media/stagefright/MetaData.h> -#include <media/stagefright/OMXClient.h> -#include <media/stagefright/OMXCodec.h> -#include <SkImage.h> -#include <SkMallocPixelRef.h> - -#include "omx_jpeg_decoder.h" -#include "StreamSource.h" - -using namespace android; - -static void getJpegOutput(MediaBuffer* buffer, const char* filename) { - int size = buffer->range_length(); - int offset = buffer->range_offset(); - FILE *pFile = fopen(filename, "w+"); - - if (pFile == NULL) { - printf("Error: cannot open %s.\n", filename); - } else { - char* data = (char*) buffer->data(); - data += offset; - while (size > 0) { - int numChars = fwrite(data, sizeof(char), 1024, pFile); - int numBytes = numChars * sizeof(char); - size -= numBytes; - data += numBytes; - } - fclose(pFile); - } - return; -} - -extern int storeBitmapToFile(SkBitmap* bitmap, const char* filename) { - bitmap->lockPixels(); - uint8_t* data = (uint8_t *)bitmap->getPixels(); - int size = bitmap->getSize(); - FILE* fp = fopen(filename, "w+"); - - if (NULL == fp) { - printf("Cannot open the output file! \n"); - return -1; - } else { - while (size > 0) { - int numChars = fwrite(data, sizeof(char), 1024, fp); - int numBytes = numChars * sizeof(char); - size -= numBytes; - data += numBytes; - } - fclose(fp); - } - return 0; -} - -static int64_t getNowUs() { - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int64_t)tv.tv_usec + tv.tv_sec * 1000000; -} - -OmxJpegImageDecoder::OmxJpegImageDecoder() { - status_t err = mClient.connect(); - CHECK_EQ(err, (status_t)OK); -} - -OmxJpegImageDecoder::~OmxJpegImageDecoder() { - mClient.disconnect(); -} - -bool OmxJpegImageDecoder::onDecode(SkStream* stream, - SkBitmap* bm, Mode mode) { - sp<MediaSource> source = prepareMediaSource(stream); - sp<MetaData> meta = source->getFormat(); - int width; - int height; - meta->findInt32(kKeyWidth, &width); - meta->findInt32(kKeyHeight, &height); - configBitmapSize( - bm, getPrefColorType(k32Bit_SrcDepth, false), - width, height); - - // mode == DecodeBounds - if (mode == SkImageDecoder::kDecodeBounds_Mode) { - return true; - } - - // mode == DecodePixels - if (!this->allocPixelRef(bm, NULL)) { - ALOGI("Cannot allocPixelRef()!"); - return false; - } - - sp<MediaSource> decoder = getDecoder(&mClient, source); - return decodeSource(decoder, source, bm); -} - -JPEGSource* OmxJpegImageDecoder::prepareMediaSource(SkStream* stream) { - DataSource::RegisterDefaultSniffers(); - sp<DataSource> dataSource = new StreamSource(stream); - return new JPEGSource(dataSource); -} - -sp<MediaSource> OmxJpegImageDecoder::getDecoder( - OMXClient *client, const sp<MediaSource>& source) { - sp<MetaData> meta = source->getFormat(); - sp<MediaSource> decoder = OMXCodec::Create( - client->interface(), meta, false /* createEncoder */, source); - - CHECK(decoder != NULL); - return decoder; -} - -bool OmxJpegImageDecoder::decodeSource(sp<MediaSource> decoder, - const sp<MediaSource>& source, SkBitmap* bm) { - status_t rt = decoder->start(); - if (rt != OK) { - ALOGE("Cannot start OMX Decoder!"); - return false; - } - int64_t startTime = getNowUs(); - MediaBuffer *buffer; - - // decode source - status_t err = decoder->read(&buffer, NULL); - int64_t duration = getNowUs() - startTime; - - if (err != OK) { - CHECK(buffer == NULL); - } - printf("Duration in decoder->read(): %.1f (msecs). \n", - duration / 1E3 ); - - // Copy pixels from buffer to bm. - // May need to check buffer->rawBytes() == bm->rawBytes(). - CHECK_EQ(buffer->size(), bm->getSize()); - memcpy(bm->getPixels(), buffer->data(), buffer->size()); - buffer->release(); - decoder->stop(); - - return true; -} - -void OmxJpegImageDecoder::configBitmapSize(SkBitmap* bm, SkColorType pref, - int width, int height) { - // Set the color space to ARGB_8888 for now (ignoring pref) - // because of limitation in hardware support. - bm->setInfo(SkImageInfo::MakeN32(width, height, kOpaque_SkAlphaType)); -} diff --git a/media/tests/omxjpegdecoder/omx_jpeg_decoder.h b/media/tests/omxjpegdecoder/omx_jpeg_decoder.h deleted file mode 100644 index e487245fd551..000000000000 --- a/media/tests/omxjpegdecoder/omx_jpeg_decoder.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -#ifndef OMXJPEGIMAGEDECODER -#define OMXJPEGIMAGEDECODER - -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <media/stagefright/JPEGSource.h> -#include <media/stagefright/MediaSource.h> -#include <media/stagefright/OMXClient.h> -#include <media/stagefright/OMXCodec.h> -#include <SkImageDecoder.h> -#include <SkStream.h> - -using namespace android; - -extern int storeBitmapToFile(SkBitmap* bitmap, const char* filename); - -class OmxJpegImageDecoder : public SkImageDecoder { -public: - OmxJpegImageDecoder(); - ~OmxJpegImageDecoder(); - - virtual Format getFormat() const { - return kJPEG_Format; - } - -protected: - virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode); - -private: - JPEGSource* prepareMediaSource(SkStream* stream); - sp<MediaSource> getDecoder(OMXClient* client, const sp<MediaSource>& source); - bool decodeSource(sp<MediaSource> decoder, const sp<MediaSource>& source, - SkBitmap* bm); - void configBitmapSize(SkBitmap* bm, SkColorType, int width, int height); - - OMXClient mClient; -}; - -#endif diff --git a/packages/BackupRestoreConfirmation/res/values-hi/strings.xml b/packages/BackupRestoreConfirmation/res/values-hi/strings.xml index 3621ebfd6791..71a319f26d3a 100644 --- a/packages/BackupRestoreConfirmation/res/values-hi/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-hi/strings.xml @@ -26,7 +26,7 @@ <string name="deny_restore_button_label" msgid="1724367334453104378">"पुनर्स्थापित न करें"</string> <string name="current_password_text" msgid="8268189555578298067">"कृपया नीचे अपना वर्तमान सुरक्षित करने का पासवर्ड डालें:"</string> <string name="device_encryption_restore_text" msgid="1570864916855208992">"कृपया नीचे अपना उपकरण एन्क्रिप्शन पासवर्ड डालें."</string> - <string name="device_encryption_backup_text" msgid="5866590762672844664">"कृपया अपना उपकरण सुरक्षित तरीका पासवर्ड नीचे दर्ज करें. बैकअप मेमोरी को एन्क्रिप्ट करने के लिए भी इसका उपयोग किया जाएगा."</string> + <string name="device_encryption_backup_text" msgid="5866590762672844664">"कृपया अपना उपकरण सुरक्षित तरीका पासवर्ड नीचे दर्ज करें. बैकअप संग्रहण को एन्क्रिप्ट करने के लिए भी इसका उपयोग किया जाएगा."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"कृपया संपूर्ण सुरक्षित डेटा को एन्क्रिप्ट करने में उपयोग के लिए पासवर्ड डालें. यदि यह खाली छोड़ दिया जाता है, तो आपके वर्तमान बैकअप पासवर्ड का उपयोग किया जाएगा:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"यदि आप संपूर्ण सुरक्षित डेटा को एन्क्रिप्ट करना चाहते हैं, तो नीचे पासवर्ड डालें:"</string> <string name="backup_enc_password_required" msgid="7889652203371654149">"चूंकि आपका उपकरण एन्क्रिप्ट किया हुआ है, इसलिए आपको अपने बैकअप को एन्क्रिप्ट करना आवश्यक है. कृपया नीचे पासवर्ड डालें:"</string> diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java index fef1f4a2871b..219de383ee91 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java @@ -574,7 +574,8 @@ public class DocumentsActivity extends Activity { // Only sort by size when visible sortSize.setVisible(mState.showSize); - final boolean searchVisible; + boolean searchVisible; + boolean fileSizeVisible = mState.action != ACTION_MANAGE; if (mState.action == ACTION_CREATE || mState.action == ACTION_OPEN_TREE) { createDir.setVisible(cwd != null && cwd.isCreateSupported()); searchVisible = false; @@ -583,6 +584,7 @@ public class DocumentsActivity extends Activity { if (cwd == null) { grid.setVisible(false); list.setVisible(false); + fileSizeVisible = false; } if (mState.action == ACTION_CREATE) { @@ -604,7 +606,7 @@ public class DocumentsActivity extends Activity { ? R.string.menu_file_size_hide : R.string.menu_file_size_show); advanced.setVisible(mState.action != ACTION_MANAGE); - fileSize.setVisible(mState.action != ACTION_MANAGE); + fileSize.setVisible(fileSizeVisible); return true; } diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java index c323a3326d7f..066acac2c22d 100644 --- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java @@ -154,7 +154,12 @@ public class ExternalStorageProvider extends DocumentsProvider { if (ROOT_ID_PRIMARY_EMULATED.equals(rootId)) { root.title = getContext().getString(R.string.root_internal_storage); } else { - root.title = volume.getUserLabel(); + final String userLabel = volume.getUserLabel(); + if (!TextUtils.isEmpty(userLabel)) { + root.title = userLabel; + } else { + root.title = volume.getDescription(getContext()); + } } root.docId = getDocIdForFile(path); mRoots.add(root); diff --git a/packages/Keyguard/res/values-hi/strings.xml b/packages/Keyguard/res/values-hi/strings.xml index b8c335860456..423c2765855e 100644 --- a/packages/Keyguard/res/values-hi/strings.xml +++ b/packages/Keyguard/res/values-hi/strings.xml @@ -36,19 +36,19 @@ <string name="keyguard_low_battery" msgid="8143808018719173859">"अपना चार्जर कनेक्ट करें."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="1332288268600329841">"अनलॉक करने के लिए मेनू दबाएं."</string> <string name="keyguard_network_locked_message" msgid="9169717779058037168">"नेटवर्क लॉक किया गया"</string> - <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"कोई सिम कार्ड नहीं है"</string> - <string name="keyguard_missing_sim_message" product="tablet" msgid="1445849005909260039">"टेबलेट में कोई सिम कार्ड नहीं है."</string> - <string name="keyguard_missing_sim_message" product="default" msgid="3481110395508637643">"फ़ोन में कोई सिम कार्ड नहीं है."</string> - <string name="keyguard_missing_sim_instructions" msgid="5210891509995942250">"सिम कार्ड डालें."</string> - <string name="keyguard_missing_sim_instructions_long" msgid="5968985489463870358">"सिम कार्ड गुम है या पढ़ने योग्य नहीं है. सिम कार्ड डालें."</string> - <string name="keyguard_permanent_disabled_sim_message_short" msgid="8340813989586622356">"अनुपयोगी सिम कार्ड."</string> - <string name="keyguard_permanent_disabled_sim_instructions" msgid="5892940909699723544">"आपका सिम कार्ड स्थायी रूप से अक्षम कर दिया गया है.\n दूसरे सिम कार्ड के लिए अपने वायरलेस सेवा प्रदाता से संपर्क करें."</string> + <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"कोई SIM कार्ड नहीं है"</string> + <string name="keyguard_missing_sim_message" product="tablet" msgid="1445849005909260039">"टेबलेट में कोई SIM कार्ड नहीं है."</string> + <string name="keyguard_missing_sim_message" product="default" msgid="3481110395508637643">"फ़ोन में कोई SIM कार्ड नहीं है."</string> + <string name="keyguard_missing_sim_instructions" msgid="5210891509995942250">"SIM कार्ड डालें."</string> + <string name="keyguard_missing_sim_instructions_long" msgid="5968985489463870358">"SIM कार्ड गुम है या पढ़ने योग्य नहीं है. SIM कार्ड डालें."</string> + <string name="keyguard_permanent_disabled_sim_message_short" msgid="8340813989586622356">"अनुपयोगी SIM कार्ड."</string> + <string name="keyguard_permanent_disabled_sim_instructions" msgid="5892940909699723544">"आपका SIM कार्ड स्थायी रूप से अक्षम कर दिया गया है.\n दूसरे SIM कार्ड के लिए अपने वायरलेस सेवा प्रदाता से संपर्क करें."</string> <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"सिम कार्ड लॉक है."</string> - <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"सिम कार्ड PUK द्वारा लॉक किया हुआ है."</string> - <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"सिम कार्ड अनलॉक हो रहा है…"</string> + <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM कार्ड PUK द्वारा लॉक किया हुआ है."</string> + <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM कार्ड अनलॉक हो रहा है…"</string> <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. %3$d विजेट में से %2$d."</string> <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"विजेट जोड़ें"</string> - <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"खाली"</string> + <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"रिक्त"</string> <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"अनलॉक क्षेत्र को विस्तृत कर दिया गया."</string> <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"अनलॉक क्षेत्र को संक्षिप्त कर दिया गया."</string> <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> विजेट."</string> @@ -83,7 +83,7 @@ <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string> <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string> <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string> - <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"रहने दें"</string> + <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"रद्द करें"</string> <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"हटाएं"</string> <string name="keyboardview_keycode_done" msgid="1992571118466679775">"पूर्ण"</string> <string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"Mode change"</string> @@ -112,7 +112,7 @@ <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"सिम अब अक्षम हो गई है. जारी रखने के लिए PUK कोड डालें. विवरण के लिए कैरियर से संपर्क करें."</string> <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"इच्छित पिन कोड डालें"</string> <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"इच्छित पिन कोड की पुष्टि करें"</string> - <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"सिम कार्ड अनलॉक कर रहा है…"</string> + <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM कार्ड अनलॉक कर रहा है…"</string> <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"ऐसा PIN लिखें, जो 4 से 8 अंकों का हो."</string> <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK कोड 8 या अधिक संख्या वाला होना चाहिए."</string> <string name="kg_invalid_puk" msgid="3638289409676051243">"सही PUK कोड पुन: डालें. बार-बार प्रयास करने से सिम स्थायी रूप से अक्षम हो जाएगी."</string> diff --git a/packages/Keyguard/res/values-sw/strings.xml b/packages/Keyguard/res/values-sw/strings.xml index 7b4f46bf26eb..814dc906c1c9 100644 --- a/packages/Keyguard/res/values-sw/strings.xml +++ b/packages/Keyguard/res/values-sw/strings.xml @@ -39,8 +39,8 @@ <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"Hakuna SIM kadi"</string> <string name="keyguard_missing_sim_message" product="tablet" msgid="1445849005909260039">"Hakuna SIM kadi katika kompyuta ndogo."</string> <string name="keyguard_missing_sim_message" product="default" msgid="3481110395508637643">"Hakuna SIM kadi kwenye simu."</string> - <string name="keyguard_missing_sim_instructions" msgid="5210891509995942250">"Weka SIM kadi."</string> - <string name="keyguard_missing_sim_instructions_long" msgid="5968985489463870358">"SIM kadi haiko au haisomeki. Weka SIM kadi."</string> + <string name="keyguard_missing_sim_instructions" msgid="5210891509995942250">"Ingiza SIM kadi."</string> + <string name="keyguard_missing_sim_instructions_long" msgid="5968985489463870358">"SIM kadi haiko au haisomeki. Ingiza SIM kadi."</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="8340813989586622356">"SIM kadi isiyotumika."</string> <string name="keyguard_permanent_disabled_sim_instructions" msgid="5892940909699723544">"SIM kadi yako imefungwa kabisa.\n Wasiliana na mtoa huduma wako wa pasi waya ili upate SIM kadi nyingine."</string> <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kadi imefungwa."</string> diff --git a/packages/Keyguard/res/values-sw600dp/bools.xml b/packages/Keyguard/res/values-sw600dp/bools.xml index ddc48c575381..00f45c1512a2 100644 --- a/packages/Keyguard/res/values-sw600dp/bools.xml +++ b/packages/Keyguard/res/values-sw600dp/bools.xml @@ -19,7 +19,6 @@ <bool name="show_ongoing_ime_switcher">true</bool> <bool name="kg_share_status_area">false</bool> <bool name="kg_sim_puk_account_full_screen">false</bool> - <bool name="kg_show_ime_at_screen_on">false</bool> <!-- No camera for you, tablet user --> <bool name="kg_enable_camera_default_widget">false</bool> <bool name="kg_center_small_widgets_vertically">true</bool> diff --git a/packages/Keyguard/res/values-zh-rCN/strings.xml b/packages/Keyguard/res/values-zh-rCN/strings.xml index 295df9c27f67..8e8c4c878610 100644 --- a/packages/Keyguard/res/values-zh-rCN/strings.xml +++ b/packages/Keyguard/res/values-zh-rCN/strings.xml @@ -21,14 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="719438068451601849">"Keyguard"</string> - <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"输入PIN码"</string> - <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"请输入SIM卡PUK码和新的PIN码"</string> + <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"输入 PIN 码"</string> + <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"请输入SIM卡PUK码和新的 PIN 码"</string> <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM卡PUK码"</string> <string name="keyguard_password_enter_pin_prompt" msgid="3201151840570492538">"新SIM卡PIN码"</string> <string name="keyguard_password_entry_touch_hint" msgid="7858547464982981384"><font size="17">"触摸可输入密码"</font></string> <string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"输入密码以解锁"</string> - <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"输入PIN码进行解锁"</string> - <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"PIN码有误。"</string> + <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"输入 PIN 进行解锁"</string> + <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"PIN 码有误。"</string> <string name="keyguard_label_text" msgid="861796461028298424">"要解锁,请先按 MENU 再按 0。"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"已超过“人脸解锁”尝试次数上限"</string> <string name="keyguard_charged" msgid="3272223906073492454">"充电完成"</string> @@ -62,7 +62,7 @@ <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"滑动解锁。"</string> <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"图案解锁。"</string> <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"人脸解锁。"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN码解锁。"</string> + <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN 解锁。"</string> <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"密码解锁。"</string> <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"图案区域。"</string> <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"滑动区域。"</string> @@ -103,20 +103,20 @@ <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"忘记了图案"</string> <string name="kg_wrong_pattern" msgid="1850806070801358830">"图案错误"</string> <string name="kg_wrong_password" msgid="2333281762128113157">"密码错误"</string> - <string name="kg_wrong_pin" msgid="1131306510833563801">"PIN码有误"</string> + <string name="kg_wrong_pin" msgid="1131306510833563801">"PIN 有误"</string> <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"请在 <xliff:g id="NUMBER">%d</xliff:g> 秒后重试。"</string> <string name="kg_pattern_instructions" msgid="398978611683075868">"绘制您的图案"</string> <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"输入SIM卡PIN码"</string> - <string name="kg_pin_instructions" msgid="2377242233495111557">"输入PIN码"</string> + <string name="kg_pin_instructions" msgid="2377242233495111557">"输入 PIN"</string> <string name="kg_password_instructions" msgid="5753646556186936819">"输入密码"</string> <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM卡已被停用,需要输入PUK码才能继续使用。有关详情,请联系您的运营商。"</string> - <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"请输入所需的PIN码"</string> - <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"请确认所需的PIN码"</string> + <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"请输入所需 PIN 码"</string> + <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"请确认所需 PIN 码"</string> <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"正在解锁SIM卡..."</string> - <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"请输入4至8位数的PIN码。"</string> + <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"请输入 4 至 8 位数的 PIN。"</string> <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK码应至少包含8位数字。"</string> <string name="kg_invalid_puk" msgid="3638289409676051243">"请重新输入正确的PUK码。如果尝试错误次数过多,SIM卡将永久停用。"</string> - <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN码不匹配"</string> + <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN 码不匹配"</string> <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"图案尝试次数过多"</string> <string name="kg_login_instructions" msgid="1100551261265506448">"要解锁,请登录您的Google帐户。"</string> <string name="kg_login_username_hint" msgid="5718534272070920364">"用户名(电子邮件地址)"</string> @@ -125,13 +125,13 @@ <string name="kg_login_invalid_input" msgid="5754664119319872197">"用户名或密码无效。"</string> <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"忘记了用户名或密码?\n请访问 "<b>"google.com/accounts/recovery"</b>"。"</string> <string name="kg_login_checking_password" msgid="1052685197710252395">"正在检查帐户…"</string> - <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"您已经<xliff:g id="NUMBER_0">%d</xliff:g>次输错了PIN码。\n\n请在<xliff:g id="NUMBER_1">%d</xliff:g>秒后重试。"</string> + <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地输入了 PIN。\n\n请在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒后重试。"</string> <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地输入了密码。\n\n请在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒后重试。"</string> <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地绘制了解锁图案。\n\n请在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒后重试。"</string> - <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"您已经<xliff:g id="NUMBER_0">%d</xliff:g>次错误地尝试解锁平板电脑。如果再尝试<xliff:g id="NUMBER_1">%d</xliff:g>次后仍不成功,平板电脑就会恢复为出厂默认设置,而且所有用户数据都会丢失。"</string> - <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"您已经<xliff:g id="NUMBER_0">%d</xliff:g>次错误地尝试解锁手机。如果再尝试<xliff:g id="NUMBER_1">%d</xliff:g>次后仍不成功,手机就会恢复为出厂默认设置,而且所有用户数据都会丢失。"</string> - <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"您已经<xliff:g id="NUMBER">%d</xliff:g>次错误地尝试解锁平板电脑。平板电脑现在将恢复为出厂默认设置。"</string> - <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"您已经<xliff:g id="NUMBER">%d</xliff:g>次错误地尝试解锁手机。手机现在将恢复为出厂默认设置。"</string> + <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地尝试解锁平板电脑。如果再尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次后仍不成功,平板电脑就会重置为出厂默认设置,而且所有用户数据都会丢失。"</string> + <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地尝试解锁手机。如果再尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次后仍不成功,手机就会重置为出厂默认设置,而且所有用户数据都会丢失。"</string> + <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"您已经 <xliff:g id="NUMBER">%d</xliff:g> 次错误地尝试解锁平板电脑。平板电脑现在将重置为出厂默认设置。"</string> + <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"您已经 <xliff:g id="NUMBER">%d</xliff:g> 次错误地尝试解锁手机。手机现在将重置为出厂默认设置。"</string> <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地绘制了解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐户解锁平板电脑。\n\n请在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒后重试。"</string> <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地绘制了解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐户解锁手机。\n\n请在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒后重试。"</string> <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string> diff --git a/packages/Keyguard/res/values-zh-rHK/strings.xml b/packages/Keyguard/res/values-zh-rHK/strings.xml index f196ffdd5bce..064c6dfd91c4 100644 --- a/packages/Keyguard/res/values-zh-rHK/strings.xml +++ b/packages/Keyguard/res/values-zh-rHK/strings.xml @@ -52,7 +52,7 @@ <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"解鎖區域已展開。"</string> <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"解鎖區域已收合。"</string> <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g>小工具。"</string> - <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"使用者選取工具"</string> + <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"用戶選取工具"</string> <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"相機"</string> <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"媒體控制"</string> <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"已開始為小工具重新排列次序。"</string> @@ -98,7 +98,7 @@ <string name="description_direction_down" msgid="5087739728639014595">"向下滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string> <string name="description_direction_left" msgid="7207478719805562165">"向左滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string> <string name="description_direction_right" msgid="8034433242579600980">"向右滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string> - <string name="user_switched" msgid="3768006783166984410">"目前的使用者是<xliff:g id="NAME">%1$s</xliff:g>。"</string> + <string name="user_switched" msgid="3768006783166984410">"目前的用戶是<xliff:g id="NAME">%1$s</xliff:g>。"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"緊急電話"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"忘記圖案"</string> <string name="kg_wrong_pattern" msgid="1850806070801358830">"圖案錯誤"</string> @@ -119,17 +119,17 @@ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN 碼不符"</string> <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"圖案嘗試次數過多"</string> <string name="kg_login_instructions" msgid="1100551261265506448">"如要解鎖,請以 Google 帳戶登入。"</string> - <string name="kg_login_username_hint" msgid="5718534272070920364">"使用者名稱 (電子郵件)"</string> + <string name="kg_login_username_hint" msgid="5718534272070920364">"用戶名稱 (電子郵件)"</string> <string name="kg_login_password_hint" msgid="9057289103827298549">"密碼"</string> <string name="kg_login_submit_button" msgid="5355904582674054702">"登入"</string> - <string name="kg_login_invalid_input" msgid="5754664119319872197">"無效的使用者名稱或密碼。"</string> - <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"忘記使用者名稱或密碼?\n請瀏覽 "<b>"google.com/accounts/recovery"</b>"。"</string> + <string name="kg_login_invalid_input" msgid="5754664119319872197">"無效的用戶名稱或密碼。"</string> + <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"忘記用戶名稱或密碼?\n請瀏覽 "<b>"google.com/accounts/recovery"</b>"。"</string> <string name="kg_login_checking_password" msgid="1052685197710252395">"正在檢查帳戶…"</string> <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"您已輸入錯誤的 PIN 碼 <xliff:g id="NUMBER_0">%d</xliff:g> 次。\n\n請在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒後再試一次。"</string> <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"您已輸入錯誤的密碼 <xliff:g id="NUMBER_0">%d</xliff:g> 次。\n\n請在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒後再試一次。"</string> <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"您已畫錯解鎖圖案 <xliff:g id="NUMBER_0">%d</xliff:g> 次。\n\n請在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒後再試一次。"</string> - <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"您嘗試了 <xliff:g id="NUMBER_0">%d</xliff:g> 次仍未能成功解開這部上鎖的平板電腦。如果再嘗試 <xliff:g id="NUMBER_1">%d</xliff:g> 次仍未成功,平板電腦將回復原廠設定,所有使用者資料均會失去。"</string> - <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"您嘗試了 <xliff:g id="NUMBER_0">%d</xliff:g> 次仍未能成功解開這部上鎖的手機。如果再嘗試 <xliff:g id="NUMBER_1">%d</xliff:g> 次仍未成功,手機將回復原廠設定,所有使用者資料均會失去。"</string> + <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"您嘗試了 <xliff:g id="NUMBER_0">%d</xliff:g> 次仍未能成功解開這部上鎖的平板電腦。如果再嘗試 <xliff:g id="NUMBER_1">%d</xliff:g> 次仍未成功,平板電腦將回復原廠設定,所有用戶資料均會失去。"</string> + <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"您嘗試了 <xliff:g id="NUMBER_0">%d</xliff:g> 次仍未能成功解開這部上鎖的手機。如果再嘗試 <xliff:g id="NUMBER_1">%d</xliff:g> 次仍未成功,手機將回復原廠設定,所有用戶資料均會失去。"</string> <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"您嘗試了 <xliff:g id="NUMBER">%d</xliff:g> 次仍未能成功解開這部上鎖的平板電腦。平板電腦現在將回復原廠設定。"</string> <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"您嘗試了 <xliff:g id="NUMBER">%d</xliff:g> 次仍未能成功解開這部上鎖的手機。手機現在將回復原廠設定。"</string> <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"您已畫錯解鎖圖案 <xliff:g id="NUMBER_0">%d</xliff:g> 次,如果再嘗試 <xliff:g id="NUMBER_1">%d</xliff:g> 次仍未成功,系統會要求您透過電郵帳戶解開上鎖的平板電腦。\n\n請在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒後再試一次。"</string> diff --git a/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml b/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml index 796cefbe68c3..63694a82fd72 100644 --- a/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml +++ b/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml @@ -44,4 +44,18 @@ android:paddingTop="8dp" android:paddingBottom="8dp" android:text="Report unlock attempts" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content"> + <Button android:id="@+id/check_trusted" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Keyguard in trusted state?" /> + <TextView android:id="@+id/check_trusted_result" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" /> + </LinearLayout> + </LinearLayout>
\ No newline at end of file diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java index bea74ab00655..39a599e726f0 100644 --- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java +++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java @@ -18,10 +18,12 @@ package com.android.trustagent.test; import android.annotation.Nullable; import android.app.Activity; +import android.app.KeyguardManager; import android.os.Bundle; import android.view.View; import android.widget.CheckBox; import android.widget.CompoundButton; +import android.widget.TextView; public class SampleTrustAgentSettings extends Activity implements View.OnClickListener, CompoundButton.OnCheckedChangeListener { @@ -30,21 +32,31 @@ public class SampleTrustAgentSettings extends Activity implements View.OnClickLi private CheckBox mReportUnlockAttempts; private CheckBox mManagingTrust; + private TextView mCheckTrustedStateResult; + + private KeyguardManager mKeyguardManager; + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + mKeyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE); + setContentView(R.layout.sample_trust_agent_settings); findViewById(R.id.enable_trust).setOnClickListener(this); findViewById(R.id.revoke_trust).setOnClickListener(this); findViewById(R.id.crash).setOnClickListener(this); + findViewById(R.id.check_trusted).setOnClickListener(this); mReportUnlockAttempts = (CheckBox) findViewById(R.id.report_unlock_attempts); mReportUnlockAttempts.setOnCheckedChangeListener(this); mManagingTrust = (CheckBox) findViewById(R.id.managing_trust); mManagingTrust.setOnCheckedChangeListener(this); + + mCheckTrustedStateResult = (TextView) findViewById(R.id.check_trusted_result); } @Override @@ -52,6 +64,7 @@ public class SampleTrustAgentSettings extends Activity implements View.OnClickLi super.onResume(); mReportUnlockAttempts.setChecked(SampleTrustAgent.getReportUnlockAttempts(this)); mManagingTrust.setChecked(SampleTrustAgent.getIsManagingTrust(this)); + updateTrustedState(); } @Override @@ -64,6 +77,8 @@ public class SampleTrustAgentSettings extends Activity implements View.OnClickLi SampleTrustAgent.sendRevokeTrust(this); } else if (id == R.id.crash) { throw new RuntimeException("crash"); + } else if (id == R.id.check_trusted) { + updateTrustedState(); } } @@ -75,4 +90,9 @@ public class SampleTrustAgentSettings extends Activity implements View.OnClickLi SampleTrustAgent.setIsManagingTrust(this, isChecked); } } + + private void updateTrustedState() { + mCheckTrustedStateResult.setText(Boolean.toString( + mKeyguardManager.isKeyguardInTrustedState())); + } } diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/OpenDocumentCallback.java b/packages/PrintSpooler/src/com/android/printspooler/model/OpenDocumentCallback.java new file mode 100644 index 000000000000..50f424ad4842 --- /dev/null +++ b/packages/PrintSpooler/src/com/android/printspooler/model/OpenDocumentCallback.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2014 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.printspooler.model; + +/** + * Callbacks interface for opening a file. + */ +public interface OpenDocumentCallback { + public static final int ERROR_MALFORMED_PDF_FILE = -1; + public static final int ERROR_SECURE_PDF_FILE = -2; + + /** + * Called after the file is opened. + */ + public void onSuccess(); + + /** + * Called after opening the file failed. + * + * @param error The error. + */ + public void onFailure(int error); +} diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java index 85b2490c68fb..882b364daa51 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java +++ b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java @@ -24,6 +24,7 @@ import android.content.ServiceConnection; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.drawable.BitmapDrawable; +import android.net.Uri; import android.os.AsyncTask; import android.os.IBinder; import android.os.ParcelFileDescriptor; @@ -77,13 +78,8 @@ public final class PageContentRepository { public void onPageContentAvailable(BitmapDrawable content); } - public interface OnMalformedPdfFileListener { - public void onMalformedPdfFile(); - } - - public PageContentRepository(Context context, - OnMalformedPdfFileListener malformedPdfFileListener) { - mRenderer = new AsyncRenderer(context, malformedPdfFileListener); + public PageContentRepository(Context context) { + mRenderer = new AsyncRenderer(context); mState = STATE_CLOSED; if (DEBUG) { Log.i(LOG_TAG, "STATE_CLOSED"); @@ -91,7 +87,7 @@ public final class PageContentRepository { mCloseGuard.open("destroy"); } - public void open(ParcelFileDescriptor source, final Runnable callback) { + public void open(ParcelFileDescriptor source, final OpenDocumentCallback callback) { throwIfNotClosed(); mState = STATE_OPENED; if (DEBUG) { @@ -110,13 +106,12 @@ public final class PageContentRepository { mRenderer.close(callback); } - public void destroy(Runnable callback) { - throwIfNotClosed(); + public void destroy() { mState = STATE_DESTROYED; if (DEBUG) { Log.i(LOG_TAG, "STATE_DESTROYED"); } - doDestroy(callback); + mRenderer.destroy(); } public void startPreload(int firstShownPage, int lastShownPage) { @@ -163,21 +158,13 @@ public final class PageContentRepository { try { if (mState != STATE_DESTROYED) { mCloseGuard.warnIfOpen(); - doDestroy(null); + destroy(); } } finally { super.finalize(); } } - private void doDestroy(Runnable callback) { - mState = STATE_DESTROYED; - if (DEBUG) { - Log.i(LOG_TAG, "STATE_DESTROYED"); - } - mRenderer.destroy(callback); - } - private void throwIfNotOpened() { if (mState != STATE_OPENED) { throw new IllegalStateException("Not opened"); @@ -420,18 +407,16 @@ public final class PageContentRepository { private final ArrayMap<Integer, RenderPageTask> mPageToRenderTaskMap = new ArrayMap<>(); - private final OnMalformedPdfFileListener mOnMalformedPdfFileListener; - private int mPageCount = PrintDocumentInfo.PAGE_COUNT_UNKNOWN; @GuardedBy("mLock") private IPdfRenderer mRenderer; private boolean mBoundToService; + private boolean mDestroyed; - public AsyncRenderer(Context context, OnMalformedPdfFileListener malformedPdfFileListener) { + public AsyncRenderer(Context context) { mContext = context; - mOnMalformedPdfFileListener = malformedPdfFileListener; ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); @@ -441,7 +426,6 @@ public final class PageContentRepository { @Override public void onServiceConnected(ComponentName name, IBinder service) { - mBoundToService = true; synchronized (mLock) { mRenderer = IPdfRenderer.Stub.asInterface(service); mLock.notifyAll(); @@ -455,7 +439,7 @@ public final class PageContentRepository { } } - public void open(final ParcelFileDescriptor source, final Runnable callback) { + public void open(final ParcelFileDescriptor source, final OpenDocumentCallback callback) { // Opening a new document invalidates the cache as it has pages // from the last document. We keep the cache even when the document // is closed to show pages while the other side is writing the new @@ -465,9 +449,16 @@ public final class PageContentRepository { new AsyncTask<Void, Void, Integer>() { @Override protected void onPreExecute() { + if (mDestroyed) { + cancel(true); + return; + } Intent intent = new Intent(PdfManipulationService.ACTION_GET_RENDERER); intent.setClass(mContext, PdfManipulationService.class); + intent.setData(Uri.fromParts("fake-scheme", String.valueOf( + AsyncRenderer.this.hashCode()), null)); mContext.bindService(intent, AsyncRenderer.this, Context.BIND_AUTO_CREATE); + mBoundToService = true; } @Override @@ -484,7 +475,7 @@ public final class PageContentRepository { return mRenderer.openDocument(source); } catch (RemoteException re) { Log.e(LOG_TAG, "Cannot open PDF document"); - return PdfManipulationService.MALFORMED_PDF_FILE_ERROR; + return PdfManipulationService.ERROR_MALFORMED_PDF_FILE; } finally { // Close the fd as we passed it to another process // which took ownership. @@ -495,14 +486,25 @@ public final class PageContentRepository { @Override public void onPostExecute(Integer pageCount) { - if (pageCount == PdfManipulationService.MALFORMED_PDF_FILE_ERROR) { - mOnMalformedPdfFileListener.onMalformedPdfFile(); - mPageCount = PrintDocumentInfo.PAGE_COUNT_UNKNOWN; - } else { - mPageCount = pageCount; - } - if (callback != null) { - callback.run(); + switch (pageCount) { + case PdfManipulationService.ERROR_MALFORMED_PDF_FILE: { + mPageCount = PrintDocumentInfo.PAGE_COUNT_UNKNOWN; + if (callback != null) { + callback.onFailure(OpenDocumentCallback.ERROR_MALFORMED_PDF_FILE); + } + } break; + case PdfManipulationService.ERROR_SECURE_PDF_FILE: { + mPageCount = PrintDocumentInfo.PAGE_COUNT_UNKNOWN; + if (callback != null) { + callback.onFailure(OpenDocumentCallback.ERROR_SECURE_PDF_FILE); + } + } break; + default: { + mPageCount = pageCount; + if (callback != null) { + callback.onSuccess(); + } + } break; } } }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); @@ -513,6 +515,14 @@ public final class PageContentRepository { new AsyncTask<Void, Void, Void>() { @Override + protected void onPreExecute() { + if (mDestroyed) { + cancel(true); + return; + } + } + + @Override protected Void doInBackground(Void... params) { synchronized (mLock) { try { @@ -534,27 +544,14 @@ public final class PageContentRepository { }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); } - public void destroy(final Runnable callback) { - new AsyncTask<Void, Void, Void>() { - @Override - protected Void doInBackground(Void... params) { - return null; - } - - @Override - public void onPostExecute(Void result) { - if (mBoundToService) { - mBoundToService = false; - mContext.unbindService(AsyncRenderer.this); - } - mPageContentCache.invalidate(); - mPageContentCache.clear(); - if (callback != null) { - callback.run(); - } - - } - }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); + public void destroy() { + if (mBoundToService) { + mBoundToService = false; + mContext.unbindService(AsyncRenderer.this); + } + mPageContentCache.invalidate(); + mPageContentCache.clear(); + mDestroyed = true; } public void startPreload(int firstShownPage, int lastShownPage, RenderSpec renderSpec) { diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java index 045a2f9ea2f2..2cc5e049e3aa 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java +++ b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java @@ -78,7 +78,7 @@ public final class PrintSpoolerService extends Service { private static final boolean DEBUG_PERSISTENCE = false; - private static final boolean PERSISTNECE_MANAGER_ENABLED = true; + private static final boolean PERSISTENCE_MANAGER_ENABLED = true; private static final long CHECK_ALL_PRINTJOBS_HANDLED_DELAY = 5000; @@ -728,7 +728,7 @@ public final class PrintSpoolerService extends Service { } public void writeStateLocked() { - if (!PERSISTNECE_MANAGER_ENABLED) { + if (!PERSISTENCE_MANAGER_ENABLED) { return; } if (mWriteStateScheduled) { @@ -935,7 +935,7 @@ public final class PrintSpoolerService extends Service { } public void readStateLocked() { - if (!PERSISTNECE_MANAGER_ENABLED) { + if (!PERSISTENCE_MANAGER_ENABLED) { return; } FileInputStream in = null; diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java index c53fcadde4e7..1b6e9ce2db37 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java +++ b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java @@ -137,7 +137,7 @@ public final class RemotePrintDocument { private final DeathRecipient mDeathRecipient = new DeathRecipient() { @Override public void binderDied() { - notifyPrintingAppDied(); + onPrintingAppDied(); } }; @@ -268,7 +268,7 @@ public final class RemotePrintDocument { mPrintDocumentAdapter.finish(); mState = STATE_FINISHED; } catch (RemoteException re) { - Log.e(LOG_TAG, "Error calling finish()", re); + Log.e(LOG_TAG, "Error calling finish()"); mState = STATE_FAILED; } } @@ -304,6 +304,18 @@ public final class RemotePrintDocument { disconnectFromRemoteDocument(); } + public void kill(String reason) { + if (DEBUG) { + Log.i(LOG_TAG, "[CALLED] kill()"); + } + + try { + mPrintDocumentAdapter.kill(reason); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error calling kill()", re); + } + } + public boolean isUpdating() { return mState == STATE_UPDATING || mState == STATE_CANCELING; } @@ -1108,7 +1120,8 @@ public final class RemotePrintDocument { } } - private void notifyPrintingAppDied() { + private void onPrintingAppDied() { + mState = STATE_FAILED; new Handler(mLooper).post(new Runnable() { @Override public void run() { @@ -1129,7 +1142,7 @@ public final class RemotePrintDocument { public void onDestroy() { final RemotePrintDocument document = mWeakDocument.get(); if (document != null) { - document.notifyPrintingAppDied(); + document.onPrintingAppDied(); } } } diff --git a/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfEditor.aidl b/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfEditor.aidl index b450ccb2e777..01cabe127bf2 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfEditor.aidl +++ b/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfEditor.aidl @@ -18,6 +18,7 @@ package com.android.printspooler.renderer; import android.os.ParcelFileDescriptor; import android.print.PageRange; +import android.print.PrintAttributes; /** * Interface for communication with a remote pdf editor. @@ -25,6 +26,7 @@ import android.print.PageRange; interface IPdfEditor { int openDocument(in ParcelFileDescriptor source); void removePages(in PageRange[] pages); + void applyPrintAttributes(in PrintAttributes attributes); void write(in ParcelFileDescriptor destination); void closeDocument(); } diff --git a/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java b/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java index 00e505149d1d..7db207498775 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java +++ b/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java @@ -47,7 +47,9 @@ public final class PdfManipulationService extends Service { public static final String ACTION_GET_EDITOR = "com.android.printspooler.renderer.ACTION_GET_EDITOR"; - public static final int MALFORMED_PDF_FILE_ERROR = -2; + public static final int ERROR_MALFORMED_PDF_FILE = -2; + + public static final int ERROR_SECURE_PDF_FILE = -3; private static final String LOG_TAG = "PdfManipulationService"; private static final boolean DEBUG = false; @@ -87,10 +89,14 @@ public final class PdfManipulationService extends Service { } mRenderer = new PdfRenderer(source); return mRenderer.getPageCount(); - } catch (IOException|IllegalStateException e) { + } catch (IOException | IllegalStateException e) { + IoUtils.closeQuietly(source); + Log.e(LOG_TAG, "Cannot open file", e); + return ERROR_MALFORMED_PDF_FILE; + } catch (SecurityException e) { IoUtils.closeQuietly(source); Log.e(LOG_TAG, "Cannot open file", e); - return MALFORMED_PDF_FILE_ERROR; + return ERROR_SECURE_PDF_FILE; } } } @@ -217,7 +223,7 @@ public final class PdfManipulationService extends Service { } mEditor = new PdfEditor(source); return mEditor.getPageCount(); - } catch (IOException|IllegalStateException e) { + } catch (IOException | IllegalStateException e) { IoUtils.closeQuietly(source); Log.e(LOG_TAG, "Cannot open file", e); throw new RemoteException(e.toString()); @@ -246,6 +252,111 @@ public final class PdfManipulationService extends Service { } @Override + public void applyPrintAttributes(PrintAttributes attributes) { + synchronized (mLock) { + throwIfNotOpened(); + if (DEBUG) { + Log.i(LOG_TAG, "applyPrintAttributes()"); + } + + Rect mediaBox = new Rect(); + Rect cropBox = new Rect(); + Matrix transform = new Matrix(); + + final boolean contentPortrait = attributes.getMediaSize().isPortrait(); + + final boolean layoutDirectionRtl = getResources().getConfiguration() + .getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; + + // We do not want to rotate the media box, so take into account orientation. + final int dstWidthPts = contentPortrait + ? pointsFromMils(attributes.getMediaSize().getWidthMils()) + : pointsFromMils(attributes.getMediaSize().getHeightMils()); + final int dstHeightPts = contentPortrait + ? pointsFromMils(attributes.getMediaSize().getHeightMils()) + : pointsFromMils(attributes.getMediaSize().getWidthMils()); + + final boolean scaleForPrinting = mEditor.shouldScaleForPrinting(); + + final int pageCount = mEditor.getPageCount(); + for (int i = 0; i < pageCount; i++) { + if (!mEditor.getPageMediaBox(i, mediaBox)) { + Log.e(LOG_TAG, "Malformed PDF file"); + return; + } + + final int srcWidthPts = mediaBox.width(); + final int srcHeightPts = mediaBox.height(); + + // Update the media box with the desired size. + mediaBox.right = dstWidthPts; + mediaBox.bottom = dstHeightPts; + mEditor.setPageMediaBox(i, mediaBox); + + // Make sure content is top-left after media box resize. + transform.setTranslate(0, srcHeightPts - dstHeightPts); + + // Rotate the content if in landscape. + if (!contentPortrait) { + transform.postRotate(270); + transform.postTranslate(0, dstHeightPts); + } + + // Scale the content if document allows it. + final float scale; + if (scaleForPrinting) { + if (contentPortrait) { + scale = Math.min((float) dstWidthPts / srcWidthPts, + (float) dstHeightPts / srcHeightPts); + transform.postScale(scale, scale); + } else { + scale = Math.min((float) dstWidthPts / srcHeightPts, + (float) dstHeightPts / srcWidthPts); + transform.postScale(scale, scale, mediaBox.left, mediaBox.bottom); + } + } else { + scale = 1.0f; + } + + // Update the crop box relatively to the media box change, if needed. + if (mEditor.getPageCropBox(i, cropBox)) { + cropBox.left = (int) (cropBox.left * scale + 0.5f); + cropBox.top = (int) (cropBox.top * scale + 0.5f); + cropBox.right = (int) (cropBox.right * scale + 0.5f); + cropBox.bottom = (int) (cropBox.bottom * scale + 0.5f); + cropBox.intersect(mediaBox); + mEditor.setPageCropBox(i, cropBox); + } + + // If in RTL mode put the content in the logical top-right corner. + if (layoutDirectionRtl) { + final float dx = contentPortrait + ? dstWidthPts - (int) (srcWidthPts * scale + 0.5f) : 0; + final float dy = contentPortrait + ? 0 : - (dstHeightPts - (int) (srcWidthPts * scale + 0.5f)); + transform.postTranslate(dx, dy); + } + + // Adjust the physical margins if needed. + Margins minMargins = attributes.getMinMargins(); + final int paddingLeftPts = pointsFromMils(minMargins.getLeftMils()); + final int paddingTopPts = pointsFromMils(minMargins.getTopMils()); + final int paddingRightPts = pointsFromMils(minMargins.getRightMils()); + final int paddingBottomPts = pointsFromMils(minMargins.getBottomMils()); + + Rect clip = new Rect(mediaBox); + clip.left += paddingLeftPts; + clip.top += paddingTopPts; + clip.right -= paddingRightPts; + clip.bottom -= paddingBottomPts; + + // Apply the accumulated transforms. + mEditor.setTransformAndClip(i, transform, clip); + } + } + } + + @Override public void write(ParcelFileDescriptor destination) throws RemoteException { synchronized (mLock) { try { diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java index 8a65a2ef1652..02d2715c035f 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java @@ -48,6 +48,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -91,14 +92,14 @@ public final class FusedPrintersProvider extends Loader<List<PrinterInfo>> { mPersistenceManager.addPrinterAndWritePrinterHistory(printer); } - private void computeAndDeliverResult(ArrayMap<PrinterId, PrinterInfo> discoveredPrinters, - ArrayMap<PrinterId, PrinterInfo> favoritePrinters) { + private void computeAndDeliverResult(Map<PrinterId, PrinterInfo> discoveredPrinters, + List<PrinterInfo> favoritePrinters) { List<PrinterInfo> printers = new ArrayList<>(); // Add the updated favorite printers. final int favoritePrinterCount = favoritePrinters.size(); for (int i = 0; i < favoritePrinterCount; i++) { - PrinterInfo favoritePrinter = favoritePrinters.valueAt(i); + PrinterInfo favoritePrinter = favoritePrinters.get(i); PrinterInfo updatedPrinter = discoveredPrinters.remove( favoritePrinter.getId()); if (updatedPrinter != null) { @@ -215,21 +216,14 @@ public final class FusedPrintersProvider extends Loader<List<PrinterInfo>> { // printer to use its current name instead of the historical one. mPersistenceManager.updatePrintersHistoricalNamesIfNeeded(printers); - ArrayMap<PrinterId, PrinterInfo> printersMap = new ArrayMap<>(); + Map<PrinterId, PrinterInfo> printersMap = new LinkedHashMap<>(); final int printerCount = printers.size(); for (int i = 0; i < printerCount; i++) { PrinterInfo printer = printers.get(i); printersMap.put(printer.getId(), printer); } - ArrayMap<PrinterId, PrinterInfo> favoritePrintersMap = new ArrayMap<>(); - final int favoritePrinterCount = favoritePrinters.size(); - for (int i = 0; i < favoritePrinterCount; i++) { - PrinterInfo favoritePrinter = favoritePrinters.get(i); - favoritePrintersMap.put(favoritePrinter.getId(), favoritePrinter); - } - - computeAndDeliverResult(printersMap, favoritePrintersMap); + computeAndDeliverResult(printersMap, favoritePrinters); } @Override @@ -544,7 +538,7 @@ public final class FusedPrintersProvider extends Loader<List<PrinterInfo>> { mReadHistoryCompleted = true; // Deliver the printers. - updatePrinters(mDiscoverySession.getPrinters(), mHistoricalPrinters); + updatePrinters(mDiscoverySession.getPrinters(), mFavoritePrinters); // Loading the available printers if needed. loadInternal(); diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java index fbf72048133a..0d2e7361cfdd 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java @@ -37,6 +37,7 @@ import android.view.ViewGroup.LayoutParams; import android.view.View.MeasureSpec; import android.widget.TextView; import com.android.printspooler.R; +import com.android.printspooler.model.OpenDocumentCallback; import com.android.printspooler.model.PageContentRepository; import com.android.printspooler.model.PageContentRepository.PageContentProvider; import com.android.printspooler.util.PageRangeUtils; @@ -51,8 +52,7 @@ import java.util.List; /** * This class represents the adapter for the pages in the print preview list. */ -public final class PageAdapter extends Adapter implements - PageContentRepository.OnMalformedPdfFileListener { +public final class PageAdapter extends Adapter { private static final String LOG_TAG = "PageAdapter"; private static final int MAX_PREVIEW_PAGES_BATCH = 50; @@ -113,6 +113,7 @@ public final class PageAdapter extends Adapter implements public interface ContentCallbacks { public void onRequestContentUpdate(); public void onMalformedPdfFile(); + public void onSecurePdfFile(); } public interface PreviewArea { @@ -127,7 +128,7 @@ public final class PageAdapter extends Adapter implements mCallbacks = callbacks; mLayoutInflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE); - mPageContentRepository = new PageContentRepository(context, this); + mPageContentRepository = new PageContentRepository(context); mPreviewPageMargin = mContext.getResources().getDimensionPixelSize( R.dimen.preview_page_margin); @@ -156,11 +157,6 @@ public final class PageAdapter extends Adapter implements } } - @Override - public void onMalformedPdfFile() { - mCallbacks.onMalformedPdfFile(); - } - public void onOrientationChanged() { mColumnCount = mContext.getResources().getInteger( R.integer.preview_page_per_row_count); @@ -181,12 +177,25 @@ public final class PageAdapter extends Adapter implements if (DEBUG) { Log.i(LOG_TAG, "STATE_OPENED"); } - mPageContentRepository.open(source, new Runnable() { + mPageContentRepository.open(source, new OpenDocumentCallback() { @Override - public void run() { + public void onSuccess() { notifyDataSetChanged(); callback.run(); } + + @Override + public void onFailure(int error) { + switch (error) { + case OpenDocumentCallback.ERROR_MALFORMED_PDF_FILE: { + mCallbacks.onMalformedPdfFile(); + } break; + + case OpenDocumentCallback.ERROR_SECURE_PDF_FILE: { + mCallbacks.onSecurePdfFile(); + } break; + } + } }); } @@ -484,9 +493,13 @@ public final class PageAdapter extends Adapter implements return selectedPages; } - public void destroy(Runnable callback) { - throwIfNotClosed(); - doDestroy(callback); + public void destroy() { + mPageContentRepository.destroy(); + mCloseGuard.close(); + mState = STATE_DESTROYED; + if (DEBUG) { + Log.i(LOG_TAG, "STATE_DESTROYED"); + } } @Override @@ -494,7 +507,7 @@ public final class PageAdapter extends Adapter implements try { if (mState != STATE_DESTROYED) { mCloseGuard.warnIfOpen(); - doDestroy(null); + destroy(); } } finally { super.finalize(); @@ -741,15 +754,6 @@ public final class PageAdapter extends Adapter implements mPageContentRepository.stopPreload(); } - private void doDestroy(Runnable callback) { - mPageContentRepository.destroy(callback); - mCloseGuard.close(); - mState = STATE_DESTROYED; - if (DEBUG) { - Log.i(LOG_TAG, "STATE_DESTROYED"); - } - } - private void throwIfNotOpened() { if (mState != STATE_OPENED) { throw new IllegalStateException("Not opened"); diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java index 20254f0b21a8..b76a9cd8b415 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java @@ -378,7 +378,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat return true; } - if (mState == STATE_PRINT_CANCELED ||mState == STATE_PRINT_CONFIRMED + if (mState == STATE_PRINT_CANCELED || mState == STATE_PRINT_CONFIRMED || mState == STATE_PRINT_COMPLETED) { return true; } @@ -405,12 +405,23 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat @Override public void onMalformedPdfFile() { + onPrintDocumentError("Cannot print a malformed PDF file"); + } + + @Override + public void onSecurePdfFile() { + onPrintDocumentError("Cannot print a password protected PDF file"); + } + + private void onPrintDocumentError(String message) { mProgressMessageController.cancel(); ensureErrorUiShown(null, PrintErrorFragment.ACTION_RETRY); setState(STATE_UPDATE_FAILED); updateOptionsUi(); + + mPrintedDocument.kill(message); } @Override @@ -592,7 +603,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat mDestinationSpinner.post(new Runnable() { @Override public void run() { - shredPagesAndFinish(uri); + transformDocumentAndFinish(uri); } }); } else if (resultCode == RESULT_CANCELED) { @@ -688,43 +699,63 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat PrintAttributes currAttributes = mPrintJob.getAttributes(); PrintAttributes newAttributes = printJobInfo.getAttributes(); - // Take the media size only if the current printer supports is. - MediaSize oldMediaSize = currAttributes.getMediaSize(); - MediaSize newMediaSize = newAttributes.getMediaSize(); - if (!oldMediaSize.equals(newMediaSize)) { - final int mediaSizeCount = mMediaSizeSpinnerAdapter.getCount(); - MediaSize newMediaSizePortrait = newAttributes.getMediaSize().asPortrait(); - for (int i = 0; i < mediaSizeCount; i++) { - MediaSize supportedSizePortrait = mMediaSizeSpinnerAdapter.getItem(i) - .value.asPortrait(); - if (supportedSizePortrait.equals(newMediaSizePortrait)) { - currAttributes.setMediaSize(newMediaSize); - mMediaSizeSpinner.setSelection(i); - if (currAttributes.getMediaSize().isPortrait()) { - if (mOrientationSpinner.getSelectedItemPosition() != 0) { - mOrientationSpinner.setSelection(0); + if (newAttributes != null) { + // Take the media size only if the current printer supports is. + MediaSize oldMediaSize = currAttributes.getMediaSize(); + MediaSize newMediaSize = newAttributes.getMediaSize(); + if (!oldMediaSize.equals(newMediaSize)) { + final int mediaSizeCount = mMediaSizeSpinnerAdapter.getCount(); + MediaSize newMediaSizePortrait = newAttributes.getMediaSize().asPortrait(); + for (int i = 0; i < mediaSizeCount; i++) { + MediaSize supportedSizePortrait = mMediaSizeSpinnerAdapter.getItem(i) + .value.asPortrait(); + if (supportedSizePortrait.equals(newMediaSizePortrait)) { + currAttributes.setMediaSize(newMediaSize); + mMediaSizeSpinner.setSelection(i); + if (currAttributes.getMediaSize().isPortrait()) { + if (mOrientationSpinner.getSelectedItemPosition() != 0) { + mOrientationSpinner.setSelection(0); + } + } else { + if (mOrientationSpinner.getSelectedItemPosition() != 1) { + mOrientationSpinner.setSelection(1); + } } - } else { - if (mOrientationSpinner.getSelectedItemPosition() != 1) { - mOrientationSpinner.setSelection(1); + break; + } + } + } + + // Take the resolution only if the current printer supports is. + Resolution oldResolution = currAttributes.getResolution(); + Resolution newResolution = newAttributes.getResolution(); + if (!oldResolution.equals(newResolution)) { + PrinterCapabilitiesInfo capabilities = mCurrentPrinter.getCapabilities(); + if (capabilities != null) { + List<Resolution> resolutions = capabilities.getResolutions(); + final int resolutionCount = resolutions.size(); + for (int i = 0; i < resolutionCount; i++) { + Resolution resolution = resolutions.get(i); + if (resolution.equals(newResolution)) { + currAttributes.setResolution(resolution); + break; } } - break; } } - } - // Take the color mode only if the current printer supports it. - final int currColorMode = currAttributes.getColorMode(); - final int newColorMode = newAttributes.getColorMode(); - if (currColorMode != newColorMode) { - final int colorModeCount = mColorModeSpinner.getCount(); - for (int i = 0; i < colorModeCount; i++) { - final int supportedColorMode = mColorModeSpinnerAdapter.getItem(i).value; - if (supportedColorMode == newColorMode) { - currAttributes.setColorMode(newColorMode); - mColorModeSpinner.setSelection(i); - break; + // Take the color mode only if the current printer supports it. + final int currColorMode = currAttributes.getColorMode(); + final int newColorMode = newAttributes.getColorMode(); + if (currColorMode != newColorMode) { + final int colorModeCount = mColorModeSpinner.getCount(); + for (int i = 0; i < colorModeCount; i++) { + final int supportedColorMode = mColorModeSpinnerAdapter.getItem(i).value; + if (supportedColorMode == newColorMode) { + currAttributes.setColorMode(newColorMode); + mColorModeSpinner.setSelection(i); + break; + } } } } @@ -902,7 +933,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat if (mCurrentPrinter == mDestinationSpinnerAdapter.getPdfPrinter()) { startCreateDocumentActivity(); } else { - shredPagesAndFinish(null); + transformDocumentAndFinish(null); } } @@ -1392,12 +1423,16 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat mCopiesEditText.setEnabled(true); mCopiesEditText.setFocusableInTouchMode(true); } else { + CharSequence text = mCopiesEditText.getText(); + if (TextUtils.isEmpty(text) || !MIN_COPIES_STRING.equals(text.toString())) { + mCopiesEditText.setText(MIN_COPIES_STRING); + } mCopiesEditText.setEnabled(false); mCopiesEditText.setFocusable(false); } if (mCopiesEditText.getError() == null && TextUtils.isEmpty(mCopiesEditText.getText())) { - mCopiesEditText.setText(String.valueOf(MIN_COPIES)); + mCopiesEditText.setText(MIN_COPIES_STRING); mCopiesEditText.requestFocus(); } } @@ -1573,8 +1608,11 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat return true; } - private void shredPagesAndFinish(final Uri writeToUri) { - new PageShredder(this, mPrintJob, mFileProvider, new Runnable() { + private void transformDocumentAndFinish(final Uri writeToUri) { + // If saving to PDF, apply the attibutes as we are acting as a print service. + PrintAttributes attributes = mDestinationSpinnerAdapter.getPdfPrinter() == mCurrentPrinter + ? mPrintJob.getAttributes() : null; + new DocumentTransformer(this, mPrintJob, mFileProvider, attributes, new Runnable() { @Override public void run() { if (writeToUri != null) { @@ -1582,7 +1620,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat } doFinish(); } - }).shred(); + }).transform(); } private void doFinish() { @@ -1592,15 +1630,9 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat mSpoolerProvider.destroy(); mPrintedDocument.finish(); mPrintedDocument.destroy(); - mPrintPreviewController.destroy(new Runnable() { - @Override - public void run() { - finish(); - } - }); - } else { - finish(); + mPrintPreviewController.destroy(); } + finish(); } private final class SpinnerItem<T> { @@ -2311,7 +2343,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat } } - private static final class PageShredder implements ServiceConnection { + private static final class DocumentTransformer implements ServiceConnection { private static final String TEMP_FILE_PREFIX = "print_job"; private static final String TEMP_FILE_EXTENSION = ".pdf"; @@ -2323,20 +2355,24 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat private final PageRange[] mPagesToShred; + private final PrintAttributes mAttributesToApply; + private final Runnable mCallback; - public PageShredder(Context context, PrintJobInfo printJob, - MutexFileProvider fileProvider, Runnable callback) { + public DocumentTransformer(Context context, PrintJobInfo printJob, + MutexFileProvider fileProvider, PrintAttributes attributes, + Runnable callback) { mContext = context; mPrintJob = printJob; mFileProvider = fileProvider; mCallback = callback; mPagesToShred = computePagesToShred(mPrintJob); + mAttributesToApply = attributes; } - public void shred() { + public void transform() { // If we have only the pages we want, done. - if (mPagesToShred.length <= 0) { + if (mPagesToShred.length <= 0 && mAttributesToApply == null) { mCallback.run(); return; } @@ -2358,14 +2394,14 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat // final and this code is the last one to touch // them as shredding is the very last step, so the // UI is not interactive at this point. - shredPages(editor); + doTransform(editor); updatePrintJob(); return null; } @Override protected void onPostExecute(Void aVoid) { - mContext.unbindService(PageShredder.this); + mContext.unbindService(DocumentTransformer.this); mCallback.run(); } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); @@ -2376,7 +2412,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat /* do nothing */ } - private void shredPages(IPdfEditor editor) { + private void doTransform(IPdfEditor editor) { File tempFile = null; ParcelFileDescriptor src = null; ParcelFileDescriptor dst = null; @@ -2395,6 +2431,11 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat // Drop the pages. editor.removePages(mPagesToShred); + // Apply print attributes if needed. + if (mAttributesToApply != null) { + editor.applyPrintAttributes(mAttributesToApply); + } + // Write the modified PDF to a temp file. tempFile = File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_EXTENSION, mContext.getCacheDir()); diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java index e4eab10e1b8c..15342ae3f595 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java @@ -192,15 +192,10 @@ class PrintPreviewController implements MutexFileProvider.OnReleaseRequestCallba }); } - public void destroy(Runnable callback) { - if (mPageAdapter.isOpened()) { - Message operation = mHandler.obtainMessage(MyHandler.MSG_CLOSE); - mHandler.enqueueOperation(operation); - } - - Message operation = mHandler.obtainMessage(MyHandler.MSG_DESTROY); - operation.obj = callback; - mHandler.enqueueOperation(operation); + public void destroy() { + mHandler.cancelQueuedOperations(); + mRecyclerView.setAdapter(null); + mPageAdapter.destroy(); } @Override @@ -226,7 +221,6 @@ class PrintPreviewController implements MutexFileProvider.OnReleaseRequestCallba private final class MyHandler extends Handler { public static final int MSG_OPEN = 1; public static final int MSG_CLOSE = 2; - public static final int MSG_DESTROY = 3; public static final int MSG_UPDATE = 4; public static final int MSG_START_PRELOAD = 5; @@ -246,6 +240,10 @@ class PrintPreviewController implements MutexFileProvider.OnReleaseRequestCallba super(looper, null, false); } + public void cancelQueuedOperations() { + mPendingOperations.clear(); + } + public void enqueueOperation(Message message) { mPendingOperations.add(message); handleNextOperation(); @@ -294,13 +292,6 @@ class PrintPreviewController implements MutexFileProvider.OnReleaseRequestCallba }); } break; - case MSG_DESTROY: { - Runnable callback = (Runnable) message.obj; - mRecyclerView.setAdapter(null); - mPageAdapter.destroy(callback); - handleNextOperation(); - } break; - case MSG_UPDATE: { SomeArgs args = (SomeArgs) message.obj; PageRange[] writtenPages = (PageRange[]) args.arg1; diff --git a/packages/SettingsProvider/Android.mk b/packages/SettingsProvider/Android.mk index da929ae6f1a0..c16f7b62eea4 100644 --- a/packages/SettingsProvider/Android.mk +++ b/packages/SettingsProvider/Android.mk @@ -5,7 +5,7 @@ LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(call all-subdir-java-files) -LOCAL_JAVA_LIBRARIES := telephony-common +LOCAL_JAVA_LIBRARIES := telephony-common ims-common LOCAL_PACKAGE_NAME := SettingsProvider LOCAL_CERTIFICATE := platform diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index 8ac1c9626ecf..eea97eac5c2f 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -43,6 +43,7 @@ import android.provider.Settings.Secure; import android.text.TextUtils; import android.util.Log; +import com.android.ims.ImsConfig; import com.android.internal.content.PackageHelper; import com.android.internal.telephony.RILConstants; import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager; @@ -70,7 +71,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion' // is properly propagated through your change. Not doing so will result in a loss of user // settings. - private static final int DATABASE_VERSION = 114; + private static final int DATABASE_VERSION = 116; private Context mContext; private int mUserHandle; @@ -567,7 +568,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)" + " VALUES(?,?);"); loadSetting(stmt, Settings.System.VOLUME_BLUETOOTH_SCO, - AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_BLUETOOTH_SCO]); + AudioService.getDefaultStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO)); db.setTransactionSuccessful(); } finally { db.endTransaction(); @@ -1827,20 +1828,41 @@ public class DatabaseHelper extends SQLiteOpenHelper { upgradeVersion = 113; } - if (upgradeVersion < 114) { - db.beginTransaction(); - SQLiteStatement stmt = null; - try { - stmt = db.compileStatement("INSERT OR IGNORE INTO global(name,value)" - + " VALUES(?,?);"); - loadBooleanSetting(stmt, Global.THEATER_MODE_ON, - R.bool.def_theater_mode_on); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - if (stmt != null) stmt.close(); + // We skipped 114 to handle a merge conflict with the introduction of theater mode. + + if (upgradeVersion < 115) { + if (mUserHandle == UserHandle.USER_OWNER) { + db.beginTransaction(); + SQLiteStatement stmt = null; + try { + stmt = db.compileStatement("INSERT OR IGNORE INTO global(name,value)" + + " VALUES(?,?);"); + loadBooleanSetting(stmt, Global.THEATER_MODE_ON, + R.bool.def_theater_mode_on); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + if (stmt != null) stmt.close(); + } + } + upgradeVersion = 115; + } + + if (upgradeVersion < 116) { + if (mUserHandle == UserHandle.USER_OWNER) { + db.beginTransaction(); + SQLiteStatement stmt = null; + try { + stmt = db.compileStatement("INSERT OR IGNORE INTO global(name,value)" + + " VALUES(?,?);"); + loadSetting(stmt, Settings.Global.ENHANCED_4G_MODE_ENABLED, ImsConfig.FeatureValueConstants.ON); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + if (stmt != null) stmt.close(); + } } - upgradeVersion = 114; + upgradeVersion = 116; } // *** Remember to update DATABASE_VERSION above! @@ -2147,25 +2169,25 @@ public class DatabaseHelper extends SQLiteOpenHelper { + " VALUES(?,?);"); loadSetting(stmt, Settings.System.VOLUME_MUSIC, - AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_MUSIC]); + AudioService.getDefaultStreamVolume(AudioManager.STREAM_MUSIC)); loadSetting(stmt, Settings.System.VOLUME_RING, - AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_RING]); + AudioService.getDefaultStreamVolume(AudioManager.STREAM_RING)); loadSetting(stmt, Settings.System.VOLUME_SYSTEM, - AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_SYSTEM]); + AudioService.getDefaultStreamVolume(AudioManager.STREAM_SYSTEM)); loadSetting( stmt, Settings.System.VOLUME_VOICE, - AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_VOICE_CALL]); + AudioService.getDefaultStreamVolume(AudioManager.STREAM_VOICE_CALL)); loadSetting(stmt, Settings.System.VOLUME_ALARM, - AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_ALARM]); + AudioService.getDefaultStreamVolume(AudioManager.STREAM_ALARM)); loadSetting( stmt, Settings.System.VOLUME_NOTIFICATION, - AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_NOTIFICATION]); + AudioService.getDefaultStreamVolume(AudioManager.STREAM_NOTIFICATION)); loadSetting( stmt, Settings.System.VOLUME_BLUETOOTH_SCO, - AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_BLUETOOTH_SCO]); + AudioService.getDefaultStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO)); // By default: // - ringtones, notification, system and music streams are affected by ringer mode @@ -2588,6 +2610,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { loadBooleanSetting(stmt, Settings.Global.GUEST_USER_ENABLED, R.bool.def_guest_user_enabled); + loadSetting(stmt, Settings.Global.ENHANCED_4G_MODE_ENABLED, ImsConfig.FeatureValueConstants.ON); // --- New global settings start here } finally { if (stmt != null) stmt.close(); diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 7e6afa67d962..3c4424505f04 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -92,6 +92,7 @@ <uses-permission android:name="android.permission.FRAME_STATS" /> <uses-permission android:name="android.permission.BIND_APPWIDGET" /> <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" /> + <uses-permission android:name="android.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS"/> <application android:label="@string/app_label"> <provider diff --git a/packages/SystemUI/res/drawable/ic_dismiss_all.xml b/packages/SystemUI/res/drawable/ic_dismiss_all.xml index 8e5e572f162b..c32e5b1138fd 100644 --- a/packages/SystemUI/res/drawable/ic_dismiss_all.xml +++ b/packages/SystemUI/res/drawable/ic_dismiss_all.xml @@ -16,6 +16,7 @@ <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" + android:autoMirrored="true" android:viewportWidth="48.0" android:viewportHeight="48.0"> <path diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml index adbda4ae968d..7fb423e5fc84 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml @@ -21,14 +21,14 @@ Copyright (C) 2014 The Android Open Source Project android:viewportHeight="24.0"> <path android:fillColor="#FFFFFFFF" - android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/> + android:pathData="M19.7,20.0l2.0,0.0l0.0,2.0l-2.0,0.0z"/> <path android:fillColor="#FFFFFFFF" - android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/> + android:pathData="M19.7,10.0l2.0,0.0l0.0,8.1l-2.0,0.0z"/> <path - android:fillColor="#FFFFFFFF" - android:pathData="M11.300000,12.700000l-9.300000,9.300000 9.300000,0.000000z"/> + android:fillColor="#4DFFFFFF" + android:pathData="M17.7,8.0l4.299999,0.0 0.0,-6.0 -20.0,20.0 15.700001,0.0z"/> <path - android:pathData="M17.700001,8.000000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z" - android:fillColor="#4DFFFFFF"/> + android:fillColor="#FFFFFFFF" + android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml index a71e33aa2eb5..8baa4ebd0c26 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml @@ -21,8 +21,8 @@ Copyright (C) 2014 The Android Open Source Project android:viewportHeight="24.0"> <path android:fillColor="#4DFFFFFF" - android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/> + android:pathData="M2.0,22.0l20.0,0.0 0.0,-20.0z"/> <path android:fillColor="#FFFFFFFF" - android:pathData="M11.300000,12.700000l-9.300000,9.300000 9.300000,0.000000z"/> + android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/> </vector> diff --git a/packages/SystemUI/res/drawable/qs_background_primary.xml b/packages/SystemUI/res/drawable/qs_background_primary.xml index b4e311f0896a..e33ff1e0949d 100644 --- a/packages/SystemUI/res/drawable/qs_background_primary.xml +++ b/packages/SystemUI/res/drawable/qs_background_primary.xml @@ -13,11 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. --> -<shape xmlns:android="http://schemas.android.com/apk/res/android"> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:top="@dimen/notification_material_rounded_rect_radius_negative" > <solid android:color="@color/system_primary_color" /> - <corners - android:topLeftRadius="0dp" - android:topRightRadius="0dp" - android:bottomLeftRadius="@dimen/notification_material_rounded_rect_radius" - android:bottomRightRadius="@dimen/notification_material_rounded_rect_radius"/> + <corners android:radius="@dimen/notification_material_rounded_rect_radius"/> </shape> diff --git a/packages/SystemUI/res/drawable/stat_sys_alarm.xml b/packages/SystemUI/res/drawable/stat_sys_alarm.xml index 57545691b4f6..48c2222f50ca 100644 --- a/packages/SystemUI/res/drawable/stat_sys_alarm.xml +++ b/packages/SystemUI/res/drawable/stat_sys_alarm.xml @@ -17,7 +17,7 @@ android:insetLeft="2.5dp" android:insetRight="2.5dp"> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="22dp" + android:width="17dp" android:height="17dp" android:viewportWidth="24.0" android:viewportHeight="24.0"> diff --git a/packages/SystemUI/res/drawable/stat_sys_cast.xml b/packages/SystemUI/res/drawable/stat_sys_cast.xml index df28638c64c8..4a7cbb3a4edf 100644 --- a/packages/SystemUI/res/drawable/stat_sys_cast.xml +++ b/packages/SystemUI/res/drawable/stat_sys_cast.xml @@ -16,7 +16,7 @@ Copyright (C) 2014 The Android Open Source Project <inset xmlns:android="http://schemas.android.com/apk/res/android" android:insetLeft="2.5dp" android:insetRight="2.5dp"> - <vector android:width="22dp" + <vector android:width="17dp" android:height="17dp" android:viewportWidth="48.0" android:viewportHeight="48.0"> diff --git a/packages/SystemUI/res/drawable/stat_sys_hotspot.xml b/packages/SystemUI/res/drawable/stat_sys_hotspot.xml new file mode 100644 index 000000000000..01e88885c617 --- /dev/null +++ b/packages/SystemUI/res/drawable/stat_sys_hotspot.xml @@ -0,0 +1,29 @@ +<!-- +Copyright (C) 2014 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. +--> +<inset xmlns:android="http://schemas.android.com/apk/res/android" + android:insetLeft="2.5dp" + android:insetRight="2.5dp"> + <vector + android:width="17.0dp" + android:height="17.0dp" + android:viewportWidth="48.0" + android:viewportHeight="48.0"> + + <path + android:fillColor="#FFFFFFFF" + android:pathData="M24.000000,22.000000c-2.200000,0.000000 -4.000000,1.800000 -4.000000,4.000000c0.000000,2.200000 1.800000,4.000000 4.000000,4.000000c2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000C28.000000,23.799999 26.200001,22.000000 24.000000,22.000000zM36.000000,26.000000c0.000000,-6.600000 -5.400000,-12.000000 -12.000000,-12.000000c-6.600000,0.000000 -12.000000,5.400000 -12.000000,12.000000c0.000000,4.400000 2.400000,8.300000 6.000000,10.400000l2.000000,-3.500000c-2.400000,-1.400000 -4.000000,-3.900000 -4.000000,-6.900000c0.000000,-4.400000 3.600000,-8.000000 8.000000,-8.000000s8.000000,3.600000 8.000000,8.000000c0.000000,3.000000 -1.600000,5.500000 -4.000000,6.900000l2.000000,3.500000C33.599998,34.299999 36.000000,30.400000 36.000000,26.000000zM24.000000,6.000000C13.000000,6.000000 4.000000,15.000000 4.000000,26.000000c0.000000,7.400000 4.000000,13.800000 10.000000,17.299999l2.000000,-3.500000c-4.800000,-2.800000 -8.000000,-7.900000 -8.000000,-13.800000c0.000000,-8.800000 7.200000,-16.000000 16.000000,-16.000000s16.000000,7.200000 16.000000,16.000000c0.000000,5.900000 -3.200000,11.100000 -8.000000,13.800000l2.000000,3.500000c6.000000,-3.500000 10.000000,-9.900000 10.000000,-17.299999C44.000000,15.000000 35.000000,6.000000 24.000000,6.000000z"/> + </vector> +</inset> diff --git a/packages/SystemUI/res/drawable/stat_sys_location.xml b/packages/SystemUI/res/drawable/stat_sys_location.xml index 433f73be3306..33ac5cd9e34e 100644 --- a/packages/SystemUI/res/drawable/stat_sys_location.xml +++ b/packages/SystemUI/res/drawable/stat_sys_location.xml @@ -17,7 +17,7 @@ android:insetLeft="1.5dp" android:insetRight="1.5dp"> <vector - android:width="20dp" + android:width="17dp" android:height="17dp" android:viewportWidth="48.0" android:viewportHeight="48.0"> diff --git a/packages/SystemUI/res/drawable/stat_sys_ringer_vibrate.xml b/packages/SystemUI/res/drawable/stat_sys_ringer_vibrate.xml index f017d5808768..eb7b4fca6a89 100644 --- a/packages/SystemUI/res/drawable/stat_sys_ringer_vibrate.xml +++ b/packages/SystemUI/res/drawable/stat_sys_ringer_vibrate.xml @@ -16,7 +16,7 @@ Copyright (C) 2014 The Android Open Source Project <inset xmlns:android="http://schemas.android.com/apk/res/android" android:insetLeft="3dp" android:insetRight="3dp"> - <vector android:width="24dp" + <vector android:width="18dp" android:height="18dp" android:viewportWidth="24.0" android:viewportHeight="24.0"> diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml b/packages/SystemUI/res/drawable/stat_sys_signal_1.xml index a53e946236cf..d1124eee9be9 100644 --- a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml +++ b/packages/SystemUI/res/drawable/stat_sys_signal_1.xml @@ -21,14 +21,14 @@ Copyright (C) 2014 The Android Open Source Project android:viewportHeight="24.0"> <path android:fillColor="#FFFFFFFF" - android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/> + android:pathData="M19.7,20.0l2.0,0.0l0.0,2.0l-2.0,0.0z"/> <path android:fillColor="#FFFFFFFF" - android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/> + android:pathData="M19.7,10.0l2.0,0.0l0.0,8.1l-2.0,0.0z"/> <path - android:fillColor="#FFFFFFFF" - android:pathData="M11.300000,12.700000l-9.300000,9.300000 9.300000,0.000000z"/> + android:fillColor="#4DFFFFFF" + android:pathData="M17.7,8.0l4.299999,0.0 0.0,-6.0 -20.0,20.0 15.700001,0.0z"/> <path - android:pathData="M17.700001,8.000000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z" - android:fillColor="#4DFFFFFF"/> + android:fillColor="#FFFFFFFF" + android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/> </vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml b/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml index 6bc55cd2324c..29eda9451dcd 100644 --- a/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml +++ b/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml @@ -21,8 +21,8 @@ Copyright (C) 2014 The Android Open Source Project android:viewportHeight="24.0"> <path android:fillColor="#4DFFFFFF" - android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/> + android:pathData="M2.0,22.0l20.0,0.0 0.0,-20.0z"/> <path android:fillColor="#FFFFFFFF" - android:pathData="M11.300000,12.700000l-9.300000,9.300000 9.300000,0.000000z"/> + android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/> </vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_zen_important.xml b/packages/SystemUI/res/drawable/stat_sys_zen_important.xml index 9dabb03e5fc3..1262617589d5 100644 --- a/packages/SystemUI/res/drawable/stat_sys_zen_important.xml +++ b/packages/SystemUI/res/drawable/stat_sys_zen_important.xml @@ -16,7 +16,7 @@ Copyright (C) 2014 The Android Open Source Project <inset xmlns:android="http://schemas.android.com/apk/res/android" android:insetLeft="2.5dp" android:insetRight="2.5dp"> - <vector android:width="23dp" + <vector android:width="18dp" android:height="18dp" android:viewportWidth="24.0" android:viewportHeight="24.0"> diff --git a/packages/SystemUI/res/drawable/stat_sys_zen_none.xml b/packages/SystemUI/res/drawable/stat_sys_zen_none.xml index 7573de0d6e65..92914a8dd988 100644 --- a/packages/SystemUI/res/drawable/stat_sys_zen_none.xml +++ b/packages/SystemUI/res/drawable/stat_sys_zen_none.xml @@ -16,7 +16,7 @@ Copyright (C) 2014 The Android Open Source Project <inset xmlns:android="http://schemas.android.com/apk/res/android" android:insetLeft="2.5dp" android:insetRight="2.5dp"> - <vector android:width="22dp" + <vector android:width="17dp" android:height="17dp" android:viewportWidth="48.0" android:viewportHeight="48.0"> diff --git a/packages/SystemUI/res/layout/keyguard_user_switcher.xml b/packages/SystemUI/res/layout/keyguard_user_switcher.xml index 3730bbe1ee56..773da9a32440 100644 --- a/packages/SystemUI/res/layout/keyguard_user_switcher.xml +++ b/packages/SystemUI/res/layout/keyguard_user_switcher.xml @@ -14,13 +14,18 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License --> -<com.android.keyguard.AlphaOptimizedLinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/keyguard_user_switcher" - android:orientation="vertical" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:gravity="end" - android:visibility="gone" - android:paddingTop="4dp"> -</com.android.keyguard.AlphaOptimizedLinearLayout> +<view xmlns:android="http://schemas.android.com/apk/res/android" + class="com.android.systemui.statusbar.policy.KeyguardUserSwitcher$Container" + android:layout_height="match_parent" + android:layout_width="match_parent"> + <com.android.keyguard.AlphaOptimizedLinearLayout + android:id="@+id/keyguard_user_switcher_inner" + android:orientation="vertical" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:layout_marginTop="@dimen/status_bar_header_height_keyguard" + android:layout_gravity="end" + android:gravity="end" + android:paddingTop="4dp"> + </com.android.keyguard.AlphaOptimizedLinearLayout> +</view>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml index 16027d96f0c0..2e38b2026112 100644 --- a/packages/SystemUI/res/layout/navigation_bar.xml +++ b/packages/SystemUI/res/layout/navigation_bar.xml @@ -43,7 +43,7 @@ <!-- navigation controls --> <View - android:layout_width="40dp" + android:layout_width="@dimen/navigation_side_padding" android:layout_height="match_parent" android:layout_weight="0" android:visibility="invisible" @@ -58,7 +58,7 @@ android:contentDescription="@string/accessibility_back" /> <View - android:layout_width="match_parent" + android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:visibility="invisible" @@ -70,10 +70,11 @@ systemui:keyCode="3" systemui:keyRepeat="false" android:layout_weight="0" + android:scaleType="center" android:contentDescription="@string/accessibility_home" /> <View - android:layout_width="match_parent" + android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:visibility="invisible" @@ -83,10 +84,11 @@ android:layout_height="match_parent" android:src="@drawable/ic_sysbar_recent" android:layout_weight="0" + android:scaleType="center" android:contentDescription="@string/accessibility_recent" /> <FrameLayout - android:layout_width="@dimen/navigation_extra_key_width" + android:layout_width="@dimen/navigation_side_padding" android:layout_height="match_parent" android:layout_weight="0" > <com.android.systemui.statusbar.policy.KeyButtonView @@ -96,6 +98,7 @@ android:contentDescription="@string/accessibility_menu" android:src="@drawable/ic_sysbar_menu" android:visibility="invisible" + android:layout_gravity="end" systemui:keyCode="82" /> <com.android.systemui.statusbar.policy.KeyButtonView @@ -105,7 +108,8 @@ android:contentDescription="@string/accessibility_ime_switch_button" android:scaleType="centerInside" android:src="@drawable/ic_ime_switcher_default" - android:visibility="invisible" /> + android:visibility="invisible" + android:layout_gravity="end" /> </FrameLayout> </LinearLayout> @@ -119,9 +123,9 @@ android:visibility="gone" > <ImageView - android:layout_width="80dp" + android:layout_width="@dimen/navigation_key_width" android:layout_height="match_parent" - android:layout_marginStart="40dp" + android:layout_marginStart="@dimen/navigation_side_padding" android:src="@drawable/ic_sysbar_lights_out_dot_small" android:scaleType="center" android:layout_weight="0" @@ -133,7 +137,7 @@ android:visibility="invisible" /> <ImageView - android:layout_width="80dp" + android:layout_width="@dimen/navigation_key_width" android:layout_height="match_parent" android:src="@drawable/ic_sysbar_lights_out_dot_large" android:scaleType="center" @@ -146,8 +150,8 @@ android:visibility="invisible" /> <ImageView - android:layout_width="80dp" - android:layout_marginEnd="40dp" + android:layout_width="@dimen/navigation_key_width" + android:layout_marginEnd="@dimen/navigation_side_padding" android:layout_height="match_parent" android:src="@drawable/ic_sysbar_lights_out_dot_small" android:scaleType="center" @@ -189,14 +193,15 @@ <FrameLayout android:layout_weight="0" android:layout_width="match_parent" - android:layout_height="40dp" > + android:layout_height="@dimen/navigation_side_padding" > <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/ime_switcher" android:layout_width="match_parent" - android:layout_height="40dp" + android:layout_height="@dimen/navigation_extra_key_width" android:contentDescription="@string/accessibility_ime_switch_button" android:scaleType="centerInside" android:src="@drawable/ic_ime_switcher_default" + android:layout_gravity="top" android:visibility="invisible" /> <com.android.systemui.statusbar.policy.KeyButtonView @@ -205,14 +210,16 @@ android:layout_height="40dp" android:contentDescription="@string/accessibility_menu" android:src="@drawable/ic_sysbar_menu_land" + android:layout_gravity="top" android:visibility="invisible" systemui:keyCode="82" /> </FrameLayout> <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps" - android:layout_height="80dp" + android:layout_height="@dimen/navigation_key_width" android:layout_width="match_parent" android:src="@drawable/ic_sysbar_recent_land" + android:scaleType="center" android:layout_weight="0" android:contentDescription="@string/accessibility_recent" /> @@ -223,9 +230,10 @@ android:visibility="invisible" /> <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home" - android:layout_height="80dp" + android:layout_height="@dimen/navigation_key_width" android:layout_width="match_parent" android:src="@drawable/ic_sysbar_home_land" + android:scaleType="center" systemui:keyCode="3" systemui:keyRepeat="false" android:layout_weight="0" @@ -238,7 +246,7 @@ android:visibility="invisible" /> <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back" - android:layout_height="80dp" + android:layout_height="@dimen/navigation_key_width" android:layout_width="match_parent" android:src="@drawable/ic_sysbar_back_land" android:scaleType="center" @@ -247,7 +255,7 @@ android:contentDescription="@string/accessibility_back" /> <View - android:layout_height="40dp" + android:layout_height="@dimen/navigation_side_padding" android:layout_width="match_parent" android:layout_weight="0" android:visibility="invisible" @@ -263,8 +271,8 @@ android:visibility="gone" > <ImageView - android:layout_height="80dp" - android:layout_marginTop="40dp" + android:layout_height="@dimen/navigation_key_width" + android:layout_marginTop="@dimen/navigation_side_padding" android:layout_width="match_parent" android:src="@drawable/ic_sysbar_lights_out_dot_small" android:scaleType="center" @@ -277,7 +285,7 @@ android:visibility="invisible" /> <ImageView - android:layout_height="80dp" + android:layout_height="@dimen/navigation_key_width" android:layout_width="match_parent" android:src="@drawable/ic_sysbar_lights_out_dot_large" android:scaleType="center" @@ -290,8 +298,8 @@ android:visibility="invisible" /> <ImageView - android:layout_height="80dp" - android:layout_marginBottom="40dp" + android:layout_height="@dimen/navigation_key_width" + android:layout_marginBottom="@dimen/navigation_side_padding" android:layout_width="match_parent" android:src="@drawable/ic_sysbar_lights_out_dot_small" android:scaleType="center" diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml index 5889c55a8f42..f45aa858d9bd 100644 --- a/packages/SystemUI/res/layout/signal_cluster_view.xml +++ b/packages/SystemUI/res/layout/signal_cluster_view.xml @@ -24,6 +24,7 @@ android:layout_width="wrap_content" android:gravity="center_vertical" android:orientation="horizontal" + android:paddingEnd="@dimen/signal_cluster_battery_padding" > <ImageView android:id="@+id/vpn" diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml index 96f9b91278d7..f6d4be54bfd2 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded.xml @@ -101,11 +101,9 @@ <ViewStub android:id="@+id/keyguard_user_switcher" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_marginTop="@dimen/status_bar_header_height_keyguard" - android:layout_gravity="end" - android:layout="@layout/keyguard_user_switcher" /> + android:layout="@layout/keyguard_user_switcher" + android:layout_height="match_parent" + android:layout_width="match_parent" /> <include layout="@layout/keyguard_status_bar" diff --git a/packages/SystemUI/res/layout/system_icons.xml b/packages/SystemUI/res/layout/system_icons.xml index 21386ef98054..943e84622fe7 100644 --- a/packages/SystemUI/res/layout/system_icons.xml +++ b/packages/SystemUI/res/layout/system_icons.xml @@ -36,6 +36,5 @@ <com.android.systemui.BatteryMeterView android:id="@+id/battery" android:layout_height="14.5dp" android:layout_width="9.5dp" - android:layout_marginBottom="@dimen/battery_margin_bottom" - android:layout_marginStart="7dp"/> + android:layout_marginBottom="@dimen/battery_margin_bottom"/> </LinearLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/zen_mode_condition.xml b/packages/SystemUI/res/layout/zen_mode_condition.xml index ad0d2dc37014..a9ad1fc7a0bd 100644 --- a/packages/SystemUI/res/layout/zen_mode_condition.xml +++ b/packages/SystemUI/res/layout/zen_mode_condition.xml @@ -29,16 +29,34 @@ android:layout_alignParentStart="true" android:gravity="center" /> - <TextView - android:id="@android:id/title" + <LinearLayout + android:id="@android:id/content" android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_height="wrap_content" + android:layout_centerVertical="true" + android:orientation="vertical" android:layout_toEndOf="@android:id/checkbox" - android:layout_toStartOf="@android:id/button1" - android:ellipsize="end" - android:gravity="center_vertical" - android:maxLines="1" - android:textAppearance="@style/TextAppearance.QS.DetailItemPrimary" /> + android:layout_toStartOf="@android:id/button1"> + + <TextView + android:id="@android:id/text1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:ellipsize="end" + android:textAlignment="viewStart" + android:maxLines="1" + android:textAppearance="@style/TextAppearance.QS.DetailItemPrimary" /> + + <TextView + android:id="@android:id/text2" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:ellipsize="end" + android:textAlignment="viewStart" + android:maxLines="1" + android:textAppearance="@style/TextAppearance.QS.DetailItemSecondary" /> + + </LinearLayout> <ImageView android:id="@android:id/button1" diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 7810d91bc0ce..25bd9939840b 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Voortdurend"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Kennisgewings"</string> <string name="battery_low_title" msgid="6456385927409742437">"Battery is amper pap"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> oor"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> oor. Batteryspaarder is aan."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> oor"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> oor. Batterybespaarder is aan."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB-laaiery nie ondersteun nie.\nGebruik net die laaier wat verskaf is."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Laai met USB word nie gesteun nie."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Gebruik slegs die laaier wat verskaf is."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Sluimer"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Vliegtuigmodus"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Laai, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Gelaai"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> toestelle)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth af"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> waarskuwing"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Jou onlangse skerms verskyn hier"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Programinligting"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"sluit na program"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"skermvaspen"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"soek"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Kon nie <xliff:g id="APP">%s</xliff:g> begin nie."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Gelaai"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Batteryspaarder is aan"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Verminder werkverrigting en agtergronddata"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Skakel batterybespaarder af"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Inhoud versteek"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sal alles begin vasvang wat op jou skerm gewys word."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Moenie weer wys nie"</string> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index fdc465fb2afd..5b21f3ffa674 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"በመካሄድ ላይ ያለ"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"ማሳወቂያዎች"</string> <string name="battery_low_title" msgid="6456385927409742437">"የባትሪ ኃይል አነስተኛ ነው"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> ቀሪ"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> ይቀራል። የባትሪ ኃይል ቆጣቢ በርቷል።"</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ይቀራል"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> ይቀራል። የባትሪ መቆጠቢያ በርቷል።"</string> <string name="invalid_charger" msgid="4549105996740522523">"USB ኃይል መሙያ አይታገዝም።\n የቀረበውን ኃይል መሙያ ብቻ ተጠቀም።"</string> <string name="invalid_charger_title" msgid="3515740382572798460">"የUSB ኃይል መሙላት አይደገፍም።"</string> <string name="invalid_charger_text" msgid="5474997287953892710">"የቀረበውን ኃይል መሙያ ብቻ ይጠቀሙ።"</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"የቀን ህልም"</string> <string name="ethernet_label" msgid="7967563676324087464">"ኤተርኔት"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"የአውሮፕላን ሁነታ"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"ባትሪ በመሙላት ላይ፣ <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"ባትሪ ሞልቷል።"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ብሉቱዝ"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ብሉቱዝ (<xliff:g id="NUMBER">%d</xliff:g> መሣሪያዎች)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ብሉቱዝ ጠፍቷል"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"የ<xliff:g id="DATA_LIMIT">%s</xliff:g> ማስጠንቀቂያ"</string> <string name="recents_empty_message" msgid="8682129509540827999">"የቅርብ ጊዜ ማያ ገጾችዎ እዚህ ይታያሉ"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"የመተግበሪያ መረጃ"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"መተግበሪያ-ጋር-ቆልፍ"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ማያ ገጽ መሰካት"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"ፈልግ"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ን መጀመር አልተቻለም።"</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ባትሪ ሞልቷል"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"የባትሪ ኃይል ቆጣቢ በርቷል"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"አፈጻጸምን እና የጀርባ ውሂብ ይቀንሳል"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"ባትሪ ቆጣቢን አጥፋ"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"ይዘቶች ተደብቀዋል"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> በማያ ገጽዎ ላይ የታየውን ነገር በሙሉ ማንሳት ይጀምራል።"</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"ዳግመኛ አታሳይ"</string> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index d4230f491f88..f59d011bbbe4 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"مستمر"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"الإشعارات"</string> <string name="battery_low_title" msgid="6456385927409742437">"البطارية منخفضة"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"المتبقي: <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"يتبقى <xliff:g id="NUMBER">%d%%</xliff:g>. وضع توفير الطاقة قيد التشغيل."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"متبقي <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"متبقي <xliff:g id="PERCENTAGE">%s</xliff:g>. وضع توفير الطاقة قيد التشغيل."</string> <string name="invalid_charger" msgid="4549105996740522523">"شحن USB غير معتمد.\nاستخدم الشاحن الموفر فقط."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"لا يمكن إجراء الشحن عبر USB."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"لا تستخدم سوى الشاحن المزوّد."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"حلم اليقظة"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"وضع الطائرة"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"جارٍ الشحن، <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"تم الشحن"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"بلوتوث"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"بلوتوث (<xliff:g id="NUMBER">%d</xliff:g> من الأجهزة)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"إيقاف البلوتوث"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"تحذير <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"تظهر شاشاتك المعروضة مؤخرًا هنا"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"معلومات التطبيق"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"تقييد بالتطبيق"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"تثبيت الشاشة"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"بحث"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"تعذر بدء <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"تم الشحن"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"وضع توفير الطاقة قيد التشغيل"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"لخفض مستوى الأداء وبيانات الخلفية"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"إيقاف توفير شحن البطارية"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"المحتويات مخفية"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> سيبدأ التقاط كل شيء يتم عرضه على الشاشة."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"عدم الإظهار مرة أخرى"</string> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 1132337a258a..3a2eabd241ed 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"В момента"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Известия"</string> <string name="battery_low_title" msgid="6456385927409742437">"Батерията е изтощена"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"Остава: <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Остава: <xliff:g id="NUMBER">%d%%</xliff:g>. Режимът за запазване на батерията е включен."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Остава/т <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Остава/т <xliff:g id="PERCENTAGE">%s</xliff:g>. Включен е режимът за запазване на батерията."</string> <string name="invalid_charger" msgid="4549105996740522523">"Не се поддържа зареждане през USB.\nИзползвайте само доставеното зарядно устройство."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Зареждането през USB не се поддържа."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Използвайте само предоставеното зарядно устройство."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Мечта"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Самолетен режим"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Зарежда се, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Заредена"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> устройства)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth е изключен"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Предупреждение: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Скорошните ви екрани се показват тук"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Информация за приложението"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"заключване в приложението"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"фиксиране на екрана"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"търсене"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> не можа да стартира."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Заредена"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Режимът за запазване на батерията е включен"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Намалява ефективността и данните на заден план"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Изключване на режима за запазване на батерията"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Скрито съдържание"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ще започне да заснема всичко, което се показва на екрана ви."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Да не се показва отново"</string> diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml index 43782ea02c08..ff1d1a0cf623 100644 --- a/packages/SystemUI/res/values-bn-rBD/strings.xml +++ b/packages/SystemUI/res/values-bn-rBD/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"চলতে-থাকা"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"বিজ্ঞপ্তিগুলি"</string> <string name="battery_low_title" msgid="6456385927409742437">"ব্যাটারি কম"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> অবশিষ্ট রয়েছে"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> অবশিষ্ট। ব্যাটারি সেভার চালু আছে।"</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> অবশিষ্ট আছে"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> অবশিষ্ট আছে৷ ব্যাটারি সাশ্রয়কারী চালু আছে৷"</string> <string name="invalid_charger" msgid="4549105996740522523">"USB চার্জিং সমর্থিত নয়৷\nকেবলমাত্র সরবহারকৃত চার্জার ব্যবহার করুন৷"</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB চার্জিং সমর্থিত নয়।"</string> <string name="invalid_charger_text" msgid="5474997287953892710">"শুধুমাত্র সরবরাহকৃত চার্জার ব্যবহার করুন।"</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"স্ক্রিনসেভার"</string> <string name="ethernet_label" msgid="7967563676324087464">"ইথারনেট"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"বিমান মোড"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"চার্জ হচ্ছে, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"চার্জ হয়েছে"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> টি ডিভাইস)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth বন্ধ"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> সতর্কতা"</string> <string name="recents_empty_message" msgid="8682129509540827999">"আপনার সাম্প্রতিক স্ক্রীনগুলো এখানে দেখা যাবে"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"অ্যাপ্লিকেশানের তথ্য"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"অ্যাপ্লিকেশানে লক করুন"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"স্ক্রীন পিন করা"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"অনুসন্ধান"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> শুরু করা যায়নি৷"</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"চার্জ হয়েছে"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"ব্যাটারি সেভার চালু রয়েছে"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"কার্য-সম্পাদনা ও পশ্চাদপট ডেটাকে কমিয়ে দেয়"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"ব্যাটারি সঞ্চয়কারী বন্ধ করুন"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"লুকানো বিষয়বস্তু"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> আপনার স্ক্রীনে দেখানো সব কিছু ক্যাপচার করা শুরু করবে।"</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"আর দেখাবেন না"</string> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index ee271392da96..feb326c044ca 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Continu"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificacions"</string> <string name="battery_low_title" msgid="6456385927409742437">"Queda poca bateria"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> restant"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Queda un <xliff:g id="NUMBER">%d%%</xliff:g>. Estalvi de bateria està activat."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g>."</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g>. L\'estalvi de bateria està activat."</string> <string name="invalid_charger" msgid="4549105996740522523">"Càrrega d\'USB no admesa.\nUtilitza només el carregador proporcionat."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"La càrrega per USB no és compatible."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Fes servir només el carregador proporcionat amb el dispositiu."</string> @@ -226,8 +226,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Estalvi de pantalla"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mode d\'avió"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"S\'està carregant, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Carregada"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositius)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desactivat"</string> @@ -279,7 +277,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advertiment: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Aquí es mostren les teves pantalles recents."</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informació de l\'aplicació"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"bloqueig d\'aplicació"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixació de pantalla"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"No s\'ha pogut iniciar <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string> @@ -326,7 +324,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Estalvi de bateria activada"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Redueix el rendiment i l\'ús de les dades en segon pla."</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Desactiva l\'estalvi de bateria"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Contingut amagat"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> començarà a enregistrar tot el que es mostri a la pantalla."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"No ho tornis a mostrar"</string> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 666c29a513cf..2e0e0d70672f 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Probíhající"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Oznámení"</string> <string name="battery_low_title" msgid="6456385927409742437">"Baterie je slabá"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"Zbývá <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Zbývá <xliff:g id="NUMBER">%d%%</xliff:g>. Režim Úspora baterie je zapnutý."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Zbývá <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Zbývá <xliff:g id="PERCENTAGE">%s</xliff:g>. Spořič baterie je zapnutý."</string> <string name="invalid_charger" msgid="4549105996740522523">"Nabíjení pomocí rozhraní USB není podporováno.\nPoužívejte pouze nabíječku, která byla dodána se zařízením."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Nabíjení přes USB není podporováno."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Používejte pouze nabíječku, která je součástí balení."</string> @@ -226,8 +226,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Spořič obrazovky"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Režim Letadlo"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Nabíjení, <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Nabito"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> zařízení)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Rozhraní Bluetooth je vypnuto"</string> @@ -279,7 +277,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Upozornění při <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Zde budou zobrazeny vaše poslední obrazovky"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informace o aplikaci"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"uzamknout v aplikaci"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"připnutí obrazovky"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"vyhledat"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikaci <xliff:g id="APP">%s</xliff:g> nelze spustit."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nabito"</string> @@ -326,7 +324,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Režim Úspora baterie je zapnutý."</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Omezuje výkon a data na pozadí"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Vypnout úsporu baterie"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g> %%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Skrytý obsah"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"Aplikace <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> začne zaznamenávat vše, co je zobrazeno na obrazovce."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Tuto zprávu příště nezobrazovat"</string> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 66e5f42aed83..ae8ccf34d31d 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"I gang"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Underretninger"</string> <string name="battery_low_title" msgid="6456385927409742437">"Batteriniveauet er lavt"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> tilbage"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> tilbage. Batteribesparelse er slået til."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> tilbage"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> tilbage. Batterisparefunktionen er slået til."</string> <string name="invalid_charger" msgid="4549105996740522523">"Opladning via USB understøttes ikke.\nBrug kun den medfølgende oplader."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB-opladning understøttes ikke."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Brug kun den oplader, der føler med."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Dagdrøm"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flytilstand"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Oplader, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Opladet"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> enheder)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth slået fra"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advarsel ved <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Dine seneste skærme vises her"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Oplysninger om applikationen"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"Bliv i app"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"skærmfastholdelse"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"søg"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> kunne ikke startes."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Opladet"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Batteribesparelse er slået til"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Reducerer ydeevne og baggrundsdata"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Deaktiver batterisparefunktion"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g> %%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Indholdet er skjult"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vil begynde at optage alt, hvad der vises på din skærm."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Vis ikke igen"</string> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 2c5cfce0ccb3..55422295566a 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Aktuell"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Benachrichtigungen"</string> <string name="battery_low_title" msgid="6456385927409742437">"Akku ist schwach"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"Noch <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Noch <xliff:g id="NUMBER">%d%%</xliff:g>. Energiesparmodus ist aktiviert."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> verbleibend"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> verbleibend. Der Energiesparmodus ist aktiviert."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB-Aufladung wird nicht unterstützt.\nVerwenden Sie das mitgelieferte Aufladegerät."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Laden per USB wird nicht unterstützt."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Verwenden Sie nur das im Lieferumfang enthaltene Ladegerät."</string> @@ -226,8 +226,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flugmodus"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Lädt, <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Aufgeladen"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Geräte)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth aus"</string> @@ -279,7 +277,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Warnung für <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Hier sehen Sie Ihre zuletzt geöffneten Apps."</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"App-Info"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"App-Verriegelung"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Bildschirmfixierung"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"Suche"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> konnte nicht gestartet werden."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Aufgeladen"</string> @@ -326,7 +324,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Energiesparmodus ist aktiviert"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Reduzierung der Leistung und Hintergrunddaten"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Energiesparmodus deaktivieren"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g> %%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Inhalte ausgeblendet"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> nimmt alle auf Ihrem Bildschirm angezeigten Aktivitäten auf."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Nicht erneut anzeigen"</string> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 9b9e56de462c..946dc2c20423 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Εν εξελίξει"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Ειδοποιήσεις"</string> <string name="battery_low_title" msgid="6456385927409742437">"Χαμηλή στάθμη μπαταρίας"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"Απομένει <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Απομένει <xliff:g id="NUMBER">%d%%</xliff:g>. Η Εξοικονόμηση μπαταρίας είναι ενεργή."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Απομένουν <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Απομένουν <xliff:g id="PERCENTAGE">%s</xliff:g>. Η λειτουργία εξοικονόμησης μπαταρίας είναι ενεργή."</string> <string name="invalid_charger" msgid="4549105996740522523">"Δεν υποστηρίζεται η φόρτιση USB.\nΧρησιμοποιείτε μόνο τον φορτιστή που παρέχεται."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Δεν υποστηρίζεται η φόρτιση μέσω USB."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Χρήση μόνο του παρεχόμενου φορτιστή."</string> @@ -226,8 +226,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Λειτουργία πτήσης"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Φόρτιση, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Μπαταρία πλήρης"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> συσκευές)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Απενεργοποιημένο Bluetooth"</string> @@ -279,7 +277,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Προειδοποίηση για <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Οι πρόσφατες οθόνες σας εμφανίζονται εδώ"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Πληροφορίες εφαρμογής"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lock to app"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"καρφίτσωμα οθόνης"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"αναζήτηση"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Δεν ήταν δυνατή η εκκίνηση της εφαρμογής <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Φορτίστηκε"</string> @@ -326,7 +324,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Η Εξοικονόμηση μπαταρίας είναι ενεργή"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Μειώνει την απόδοση και τα δεδομένα παρασκηνίου"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Απενεργοποίηση εξοικονόμησης μπαταρίας"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Κρυφό περιεχόμενο"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"Θα ξεκινήσει η καταγραφή του περιεχομένου που εμφανίζεται στην οθόνη σας από την εφαρμογή <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Να μην εμφανιστεί ξανά"</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 3898d02a59bb..f2018fa10c35 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Ongoing"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string> <string name="battery_low_title" msgid="6456385927409742437">"Battery is low"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> remaining"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> remaining. Battery saver is on."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining. Battery saver is on."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB charging not supported.\nUse only the supplied charger."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB charging not supported."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Use only the supplied charger."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Aeroplane mode"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Charging, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Charged"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Devices)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Off"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> warning"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Your recent screens appear here"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Application Info"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lock to app"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"screen pinning"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Could not start <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Charged"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Battery saver is on"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Reduces performance and background data"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Turn off battery saver"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Contents hidden"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> will start capturing everything that\'s displayed on your screen."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Don\'t show again"</string> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 3898d02a59bb..f2018fa10c35 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Ongoing"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string> <string name="battery_low_title" msgid="6456385927409742437">"Battery is low"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> remaining"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> remaining. Battery saver is on."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining. Battery saver is on."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB charging not supported.\nUse only the supplied charger."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB charging not supported."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Use only the supplied charger."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Aeroplane mode"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Charging, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Charged"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Devices)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Off"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> warning"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Your recent screens appear here"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Application Info"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lock to app"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"screen pinning"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Could not start <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Charged"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Battery saver is on"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Reduces performance and background data"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Turn off battery saver"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Contents hidden"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> will start capturing everything that\'s displayed on your screen."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Don\'t show again"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index ccba7f27a92b..d3aab3b79a58 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Continuo"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificaciones"</string> <string name="battery_low_title" msgid="6456385927409742437">"Batería baja"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"Quedan <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> restante. El ahorro de batería está activado."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de batería."</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de batería. La función de ahorro de batería está activada."</string> <string name="invalid_charger" msgid="4549105996740522523">"No admite la carga USB.\nUsa sólo el cargador provisto."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"No se admite la carga por USB."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Usa solo el cargador suministrado."</string> @@ -226,8 +226,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Activar protector"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo avión"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Cargando (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Cargada"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivos)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desactivado"</string> @@ -279,7 +277,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advertencia de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Las pantallas recientes aparecen aquí."</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Información de la aplicación"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"fijar aplicación"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Fijar pantalla"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"No se pudo iniciar <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string> @@ -326,7 +324,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Ahorro de batería activado"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Reduce el rendimiento y el uso de datos en segundo plano."</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Desactivar el ahorro de batería"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Contenidos ocultos"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> comenzará la captura de todo lo que se muestre en la pantalla."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"No volver a mostrar"</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 80eff2af5bd7..1530bf3ac21c 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Entrante"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificaciones"</string> <string name="battery_low_title" msgid="6456385927409742437">"Nivel de batería bajo"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> restante"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> restante. Ahorro de batería activado."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de batería"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de batería. La función de ahorro de energía está activada."</string> <string name="invalid_charger" msgid="4549105996740522523">"No se admite la carga por USB.\nUtiliza solo el cargador proporcionado."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"No se admite la carga por USB."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Utiliza solo el cargador proporcionado."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Salvapantallas"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo avión"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Cargando (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Cargada"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivos)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desactivado"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advertencia de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Aquí aparecerán tus pantallas recientes"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Información de la aplicación"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"bloqueo de aplicación"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fijación de pantalla"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"No se ha podido iniciar <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Ahorro de batería activado"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Reduce el rendimiento y el envío de datos en segundo plano"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Desactivar ahorro de batería"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Contenidos ocultos"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> empezará a capturar todo lo que aparezca en la pantalla."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"No volver a mostrar"</string> diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml index 24139942818c..55d6d1fabc87 100644 --- a/packages/SystemUI/res/values-et-rEE/strings.xml +++ b/packages/SystemUI/res/values-et-rEE/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Jätkuv"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Teadistused"</string> <string name="battery_low_title" msgid="6456385927409742437">"Aku hakkab tühjaks saama"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> on alles"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Alles: <xliff:g id="NUMBER">%d%%</xliff:g>. Akusäästja on sisse lülitatud."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Jäänud on <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Jäänud on <xliff:g id="PERCENTAGE">%s</xliff:g>. Akusäästja on sisse lülitatud."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB laadimist ei toetata.\nKasutage ainult tootja laadija."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB-ga laadimist ei toetata."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Kasutage ainult kaasasolevat laadijat."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Unistus"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Lennurežiim"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Laadimine, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Laetud"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> seadet)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth on väljas"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> hoiatus"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Teie viimane ekraanikuva ilmub siia"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Rakenduste teave"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lukusta rakendusele"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekraanikuva kinnitamine"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"otsing"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Rakendust <xliff:g id="APP">%s</xliff:g> ei saanud käivitada."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Laetud"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Akusäästja on sisse lülitatud"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Vähendab jõudlust ja taustaandmeid"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Akusäästja väljalülitamine"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Sisu on peidetud"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> hakkab jäädvustama kõike, mida ekraanil kuvatakse."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Ära kuva uuesti"</string> diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml index bd87668f2f78..01cd8600af78 100644 --- a/packages/SystemUI/res/values-eu-rES/strings.xml +++ b/packages/SystemUI/res/values-eu-rES/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Abian"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Jakinarazpenak"</string> <string name="battery_low_title" msgid="6456385927409742437">"Bateria agortzen ari da"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> geratzen da"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Bateriaren <xliff:g id="NUMBER">%d%%</xliff:g> geratzen da. Bateria aurrezlea aktibatu da."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> gelditzen da"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> gelditzen da. Bateria-aurrezteko aukera aktibatuta dago."</string> <string name="invalid_charger" msgid="4549105996740522523">"Ez da USB bidez kargatzea onartzen.\nErabili hornitu zaizun kargagailua soilik."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Ez da USB bidez kargatzea onartzen."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Erabili jatorrizko kargagailua soilik."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Pantaila-babeslea"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Hegaldi modua"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Kargatzen: <xliff:g id="PERCENT">%%</xliff:g> <xliff:g id="NUMBER">%d</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Kargatuta"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetootha (<xliff:g id="NUMBER">%d</xliff:g> gailu)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetootha desaktibatuta"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Abisua: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Ikusitako azken pantailak erakusten dira hemen"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Aplikazioaren informazioa"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"aplikazio bakarreko modua"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pantaila-ainguratzea"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"bilatu"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Ezin izan da hasi <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Kargatuta"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Bateria aurrezlea aktibatuta dago"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Errendimendua eta atzeko planoko datuak murrizten ditu"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Desaktibatu bateria aurrezteko aukera"</string> - <string name="battery_level_template" msgid="1609636980292580020">"%% <xliff:g id="LEVEL">%d</xliff:g>"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Edukiak ezkutatuta daude"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak pantailan bistaratzen den guztia grabatuko du."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Ez erakutsi berriro"</string> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index ebddd5b5814e..245ac4a596b9 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"در حال انجام"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"اعلانها"</string> <string name="battery_low_title" msgid="6456385927409742437">"شارژ باتری کم است"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> باقیمانده است"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> باقی مانده است. ذخیره کننده باتری روشن است."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی مانده است"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی مانده است. ذخیره کننده باتری روشن است."</string> <string name="invalid_charger" msgid="4549105996740522523">"شارژ USB پشتیبانی نمیشود.\nفقط از شارژر ارائه شده استفاده کنید."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"شارژ با USB پشتیبانی نمیشود."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"فقط از شارژر ارائه شده استفاده کنید."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"رویاپردازی"</string> <string name="ethernet_label" msgid="7967563676324087464">"اترنت"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"حالت هواپیما"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"در حال شارژ، <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"شارژ شد"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"بلوتوث"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"بلوتوث ( <xliff:g id="NUMBER">%d</xliff:g> دستگاه)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"بلوتوث خاموش"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"هشدار <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"صفحههای اخیر شما اینجا نمایان میشوند"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"اطلاعات برنامه"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"قفل به برنامه"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"پین کردن صفحه"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"جستجو"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> شروع نشد."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"شارژ کامل شد"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"ذخیره کننده باتری روشن است."</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"عملکرد و اطلاعات پسزمینه را کاهش میدهد"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"خاموش کردن ذخیرهکننده باتری"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"محتواها پنهان هستند"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> شروع به ضبط هر چیزی میکند که در صفحهنمایش شما نمایش داده میشود."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"دوباره نشان داده نشود"</string> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 01b936ac4f8f..0d5281cbd1dd 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Käynnissä olevat"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Ilmoitukset"</string> <string name="battery_low_title" msgid="6456385927409742437">"Akku on vähissä"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> jäljellä"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> jäljellä. Virransäästö on käytössä."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> jäljellä"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> jäljellä. Virransäästö on käytössä."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB-latausta ei tueta.\nKäytä laitteen mukana tullutta laturia."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB-latausta ei tueta."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Käytä vain laitteen mukana toimitettua laturia."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Unelmat"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Lentokonetila"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Ladataan (<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Täynnä"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> laitetta)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth pois käytöstä"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> – varoitus"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Äskettäin käytetyt ruudut näkyvät tässä"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Sovellustiedot"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lukitse sovellukseen"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"näytön kiinnitys"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"haku"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Sovelluksen <xliff:g id="APP">%s</xliff:g> käynnistäminen epäonnistui."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Ladattu"</string> @@ -324,9 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Virransäästö on käytössä"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Rajoittaa suorituskykyä ja taustatiedonsiirtoa"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Poista virransäästö käytöstä"</string> - <!-- String.format failed for translation --> - <!-- no translation found for battery_level_template (1609636980292580020) --> - <skip /> <string name="notification_hidden_text" msgid="1135169301897151909">"Sisältö piilotettu"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> alkaa tallentaa kaiken näytölläsi näkyvän."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Älä näytä uudelleen"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index aeabd69bfa09..5119babc0552 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"En cours"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string> <string name="battery_low_title" msgid="6456385927409742437">"Pile faible"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> restant(s)"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Il reste : <xliff:g id="NUMBER">%d%%</xliff:g>. La fonction Économie d\'énergie est activée."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> restants"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> restants. L\'économiseur d\'énergie est activé."</string> <string name="invalid_charger" msgid="4549105996740522523">"Chargement USB non compatible.\nVous devez utiliser le chargeur fourni."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Le chargement par USB n\'est pas pris en charge."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Utilisez uniquement le chargeur fourni."</string> @@ -226,8 +226,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Écran de veille"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mode Avion"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"En charge (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Chargée"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> appareils)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"BLUETOOTH DÉSACTIVÉ"</string> @@ -279,7 +277,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Avertissement : <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Vos écrans récents s\'affichent ici"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Détails de l\'application"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"verrouiller sur l\'application"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"épinglage d\'écran"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Impossible de lancer <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Chargée"</string> @@ -326,7 +324,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"La fonction Économie d\'énergie est activée"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Réduire les performances et de fond"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Désactiver l\'économiseur d\'énergie"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g> %%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Contenus masqués"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> commencer à enregistrer tout ce qui s\'affiche sur votre écran."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Ne plus afficher"</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index b7825df265d8..52f05db2b4fa 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"En cours"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string> <string name="battery_low_title" msgid="6456385927409742437">"Batterie faible"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> restant(s)"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Il reste <xliff:g id="NUMBER">%d%%</xliff:g>. L\'économiseur de batterie est activé."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> restants"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> restants. L\'économiseur de batterie est activé."</string> <string name="invalid_charger" msgid="4549105996740522523">"Chargement USB non disponible.\nVous devez utiliser le chargeur fourni."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Chargeur USB non compatible."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Veuillez n\'utiliser que le chargeur fourni."</string> @@ -226,8 +226,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Écran de veille interactif"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mode avion"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"En charge (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Chargée"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> appareils)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth désactivé"</string> @@ -279,7 +277,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Avertissement : <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Vos écrans récents s\'affichent ici"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informations sur l\'application"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"verrouiller sur l\'application"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"épinglage d\'écran"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Impossible de lancer <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Chargé"</string> @@ -326,7 +324,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"L\'économiseur de batterie est activé"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Limite les performances et les données en arrière-plan."</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Désactiver l\'économiseur de batterie"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g> %%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Contenus masqués"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> va commencer à capturer tous les contenus affichés à l\'écran."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Ne plus afficher"</string> diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml index 51f0d579ba0a..f5b773f408df 100644 --- a/packages/SystemUI/res/values-gl-rES/strings.xml +++ b/packages/SystemUI/res/values-gl-rES/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"En curso"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificacións"</string> <string name="battery_low_title" msgid="6456385927409742437">"Queda pouca batería"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> restante"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Queda un <xliff:g id="NUMBER">%d%%</xliff:g>. O aforro de batería está activado."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante. A función aforro de batería está activada."</string> <string name="invalid_charger" msgid="4549105996740522523">"Non compatible coa carga por USB.\nUtiliza só o cargador proporcionado."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Non se admite a carga mediante USB."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Utiliza soamente o cargador fornecido."</string> @@ -226,8 +226,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Protector pantalla"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo avión"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Cargando, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Cargada"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivos)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desactivado"</string> @@ -279,7 +277,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advertencia <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"As túas pantallas recentes aparecen aquí"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Información da aplicación"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"bloqueo de aplicación"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixación de pantalla"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Non foi posible iniciar <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string> @@ -326,7 +324,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"O aforro de batería está activado"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Reduce o rendemento e os datos en segundo plano"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Desactivar o aforro de batería"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Contido oculto"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> comezará a capturar todo o que apareza na túa pantalla."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Non mostrar outra vez"</string> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 962bcac4aa9c..47da5bfa9523 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ऑनगोइंग"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"सूचनाएं"</string> <string name="battery_low_title" msgid="6456385927409742437">"बैटरी कम है"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> शेष"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> शेष. बैटरी सेवर चालू है."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> शेष"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> शेष. बैटरी सेवर चालू है."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB चार्जिंग समर्थित नहीं है.\nकेवल आपूर्ति किए गए चार्जर का उपयोग करें."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB चार्जिंग समर्थित नहीं है."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"केवल आपूर्ति किए गए चार्जर का उपयोग करें."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"स्क्रीनसेवर"</string> <string name="ethernet_label" msgid="7967563676324087464">"ईथरनेट"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"हवाई जहाज़ मोड"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"चार्ज हो रही है, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"चार्ज हो गई है"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ब्लूटूथ"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ब्लूटूथ (<xliff:g id="NUMBER">%d</xliff:g> डिवाइस)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ब्लूटूथ बंद"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> चेतावनी"</string> <string name="recents_empty_message" msgid="8682129509540827999">"आपकी हाल की स्क्रीन यहां दिखाई देती हैं"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"एप्लिकेशन जानकारी"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"ऐप्स पर लॉक करें"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"स्क्रीन पिन करना"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"खोज"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> प्रारंभ नहीं किया जा सका."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"चार्ज हो गई है"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"बैटरी सेवर चालू है"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"निष्पादन और पृष्ठभूमि डेटा को कम करता है"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"बैटरी बचतकर्ता को बंद करें"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"छिपी हुई सामग्री"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> आपके स्क्रीन पर प्रदर्शित प्रत्येक सामग्री को कैप्चर करना प्रारंभ कर देगी."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"फिर से न दिखाएं"</string> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 00bb24fc9dcd..101b4cdad7fe 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"U tijeku"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Obavijesti"</string> <string name="battery_low_title" msgid="6456385927409742437">"Niska razina baterije"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> preostalo"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Preostalo je <xliff:g id="NUMBER">%d%%</xliff:g>. Štednja baterije je uključena."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Preostalo <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Preostalo <xliff:g id="PERCENTAGE">%s</xliff:g>. Uključena je štednja baterije."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB punjenje nije podržano.\nUpotrijebite samo priloženi punjač."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Punjenje putem USB-a nije podržano."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Upotrebljavajte samo priloženi punjač."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Sanjarenje"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Način rada u zrakoplovu"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Puni se, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Napunjena"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (broj uređaja: <xliff:g id="NUMBER">%d</xliff:g>)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth isključen"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Upozorenje <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Ovdje se pojavljuju vaši nedavni zasloni"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacije o aplikaciji"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"zaključaj na aplikaciju"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"prikačivanje zaslona"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"pretraži"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikacija <xliff:g id="APP">%s</xliff:g> nije pokrenuta."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Napunjeno"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Štednja baterije je uključena"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Smanjuje količinu rada i pozadinske podatke"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Isključi uštedu baterije"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Sadržaj je skriven"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"Aplikacija <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> počet će snimati sve što se prikazuje na zaslonu."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Ne prikazuj ponovo"</string> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 4b60d3bc431f..0b7dff3d11f5 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Folyamatban van"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Értesítések"</string> <string name="battery_low_title" msgid="6456385927409742437">"Alacsony az energiaszint"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> maradt"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> maradt. Az Akkumulátorkímélő mód bekapcsol."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> maradt"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> maradt. A takarékos akkumulátorhasználat engedélyezve van."</string> <string name="invalid_charger" msgid="4549105996740522523">"Az USB-n keresztüli töltés nincs támogatva.\nHasználja a kapott töltőt."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Az USB-n keresztüli töltés nem támogatott."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Kizárólag a tartozékként kapott töltőt használja."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Álmodozás"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Repülőgép üzemmód"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Töltés (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Feltöltve"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> eszköz)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth kikapcsolva"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Figyelem! <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"A legutóbbi képernyők itt jelennek meg"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Az alkalmazás adatai"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"alkalmazászárolás"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"képernyő rögzítése"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"keresés"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Nem lehet elindítani a következőt: <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Feltöltve"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Akkumulátorkímélő mód bekapcsolva"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Csökkenti a teljesítményt és a háttéradatok használatát"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Akkumulátorkímélő mód kikapcsolása"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>. szint"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Tartalomjegyzék elrejtve"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"A(z) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> alkalmazás rögzíteni fog mindent, ami megjelenik a képernyőn."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Ne jelenjen meg többé"</string> diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml index 1305a61e67d6..e56633a3ceca 100644 --- a/packages/SystemUI/res/values-hy-rAM/strings.xml +++ b/packages/SystemUI/res/values-hy-rAM/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Ընթացիկ"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Ծանուցումներ"</string> <string name="battery_low_title" msgid="6456385927409742437">"Մարտկոցը լիցքաթափվում է"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"մնում է <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Մնաց <xliff:g id="NUMBER">%d%%</xliff:g>: Մարտկոցի տնտեսումը միացված է:"</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Մնաց <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Մնաց <xliff:g id="PERCENTAGE">%s</xliff:g>: Մարտկոցի տնտեսումը միացված է:"</string> <string name="invalid_charger" msgid="4549105996740522523">"USB լիցքավորումը չի աջակցվում:\nՕգտվեք միայն գործող լիցքավորիչից:"</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB լիցքավորումը չի աջակցվում:"</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Օգտագործեք միայն մատակարարի տրամադրած լիցքավորիչը:"</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Ցերեկային ռեժիմ"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Ինքնաթիռային ռեժիմ"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Լիցքավորում` <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Լիցքավորված է"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> սարք)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth-ն անջատված է"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> զգուշացում"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Ձեր վերջին էկրանները տեսանելի են այստեղ"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Հավելվածի մասին"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"Lock-to-app"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"էկրանի ամրակցում"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"որոնել"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Հնարավոր չէ գործարկել <xliff:g id="APP">%s</xliff:g>-ը:"</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Լիցքավորված է"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Մարտկոցի տնտեսումը միացված է"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Նվազեցնում է ծանրաբեռնվածությունը և ֆոնային տվյալները"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Անջատել մարտկոցի տնտեսումը"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Բովանդակությունը թաքցված է"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ծրագիրը կսկսի հավաքագրել այն ամենն ինչ ցուցադրվում է ձեր էկրանին:"</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Այլևս ցույց չտալ"</string> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 8f750dfb2279..2ad0285968c5 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Berkelanjutan"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Pemberitahuan"</string> <string name="battery_low_title" msgid="6456385927409742437">"Baterai lemah"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> tersisa"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Tersisa <xliff:g id="NUMBER">%d%%</xliff:g>. Penghemat baterai aktif."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Tersisa <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Tersisa <xliff:g id="PERCENTAGE">%s</xliff:g>. Penghemat baterai aktif."</string> <string name="invalid_charger" msgid="4549105996740522523">"Pengisian daya USB tidak didukung.\nGunakan hanya pengisi daya yang disediakan."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Pengisian daya USB tidak didukung."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Hanya gunakan pengisi daya yang disediakan."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Lamunan"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mode pesawat"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Mengisi baterai, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Terisi"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Perangkat)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Mati"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Peringatan <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Layar terkini Anda muncul di sini"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Info Aplikasi"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"kunci ke aplikasi"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pin ke layar"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"telusuri"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Tidak dapat memulai <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Terisi"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Penghemat baterai aktif"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Mengurangi kinerja dan data latar belakang"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Nonaktifkan penghemat baterai"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Konten tersembunyi"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> akan mulai menangkap apa saja yang ditampilkan pada layar Anda."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Jangan tampilkan lagi"</string> diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml index 681309697a80..cac5b271b312 100644 --- a/packages/SystemUI/res/values-is-rIS/strings.xml +++ b/packages/SystemUI/res/values-is-rIS/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Áframhaldandi"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Tilkynningar"</string> <string name="battery_low_title" msgid="6456385927409742437">"Rafhlaðan er að tæmast"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> eftir"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> eftir. Kveikt er á rafhlöðusparnaði."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> eftir"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> eftir. Kveikt er á rafhlöðusparnaði."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB-hleðsla er ekki studd.\nNotaðu eingöngu hleðslutækið sem fylgdi."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Ekki er stuðningur við USB-hleðslu."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Notaðu eingöngu hleðslutækið sem fylgir með."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Skjávari"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flugstilling"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Í hleðslu, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Fullhlaðið"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> tæki)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Slökkt á Bluetooth"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> viðvörun"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Nýlegar skjámyndir birtast hér"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Forritsupplýsingar"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"forritslæsing"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"skjáfesting"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"leita"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Ekki var hægt að ræsa <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Fullhlaðin"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Kveikt er á rafhlöðusparnaði"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Dregur úr afköstum og bakgrunnsgögnum"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Slökkva á rafhlöðusparnaði"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Innihald falið"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> mun fanga allt sem birtist á skjánum."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Ekki sýna þetta aftur"</string> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index abf22befb8cf..150bcec59661 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"In corso"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifiche"</string> <string name="battery_low_title" msgid="6456385927409742437">"Batteria quasi scarica"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> rimanente"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> rimanente. La funzione Risparmio batteria è attiva."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> rimanente"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> rimanente. Risparmio energetico attivo."</string> <string name="invalid_charger" msgid="4549105996740522523">"Ricarica tramite USB non supportata.\nUtilizza solo il caricatore in dotazione."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Ricarica tramite USB non supportata."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Utilizza solo il caricabatterie fornito in dotazione."</string> @@ -226,8 +226,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modalità aereo"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"In carica (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Carica"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivi)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth spento"</string> @@ -279,7 +277,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Avviso <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Le tue schermate recenti vengono visualizzate in questa sezione"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informazioni sull\'applicazione"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"blocca su app"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"blocco su schermo"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Impossibile avviare <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carica"</string> @@ -326,7 +324,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Risparmio batteria attivo"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Riduce le prestazioni e i dati in background"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Disattiva risparmio energetico"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Contenuti nascosti"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> inizierà ad acquisire tutto ciò che è visualizzato sul tuo schermo."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Non mostrare più"</string> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 460d2b1f252f..a07370696c3f 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"מתמשך"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"התראות"</string> <string name="battery_low_title" msgid="6456385927409742437">"עוצמת הסוללה נמוכה"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"נותרו <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"נותרו <xliff:g id="NUMBER">%d%%</xliff:g>. תכונת \'חיסכון בסוללה\' פועלת."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"נותרו <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"נותרו <xliff:g id="PERCENTAGE">%s</xliff:g>. הופעל שירות חיסכון בסוללה."</string> <string name="invalid_charger" msgid="4549105996740522523">"טעינה באמצעות USB אינה נתמכת.\nהשתמש אך ורק במטען שסופק."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"טעינה בחיבור USB אינה נתמכת."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"השתמש רק במטען שסופק."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"חלום בהקיץ"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"מצב טיסה"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"טוען (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"מלאה"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> מכשירים)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth מופסק"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"אזהרה - <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"המסכים האחרונים מופיעים כאן"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"מידע על האפליקציה"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"נעל לאפליקציה"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"הצמדת מסך"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"חפש"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"לא ניתן היה להפעיל את <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"טעון"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"תכונת \'חיסכון בסוללה\' פועלת"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"מפחית את הביצועים ונתונים ברקע"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"כבה את החיסכון בסוללה"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"התוכן מוסתר"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> יתחיל להקליט את כל התוכן המוצג במסך שלך."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"אל תציג שוב"</string> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 24fd627f61d2..22501d2a0b4f 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"実行中"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string> <string name="battery_low_title" msgid="6456385927409742437">"電池残量が少なくなっています"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"残り<xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"残量が<xliff:g id="NUMBER">%d%%</xliff:g>です。バッテリーセーバーはONです。"</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"残量が<xliff:g id="PERCENTAGE">%s</xliff:g>です"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"残量が<xliff:g id="PERCENTAGE">%s</xliff:g>です。バッテリーセーバーはONです。"</string> <string name="invalid_charger" msgid="4549105996740522523">"USB充電には対応していません。\n付属の充電器をお使いください。"</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB充電には対応していません。"</string> <string name="invalid_charger_text" msgid="5474997287953892710">"専用の充電器のみを使用してください。"</string> @@ -226,8 +226,6 @@ <string name="start_dreams" msgid="7219575858348719790">"スクリーンセーバー"</string> <string name="ethernet_label" msgid="7967563676324087464">"イーサネット"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"機内モード"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"充電中: <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"充電完了"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth(端末数<xliff:g id="NUMBER">%d</xliff:g>)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth OFF"</string> @@ -279,7 +277,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"警告: 上限は<xliff:g id="DATA_LIMIT">%s</xliff:g>です"</string> <string name="recents_empty_message" msgid="8682129509540827999">"ここに最近の画面が表示されます"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"アプリ情報"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"アプリロック"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"画面固定"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"検索"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>を開始できません。"</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"充電が完了しました"</string> @@ -326,7 +324,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"バッテリーセーバーがON"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"パフォーマンスとバックグラウンドデータを制限します"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"バッテリーセーバーをOFFにします"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"コンテンツが非表示"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>で、画面に表示されているコンテンツのキャプチャを開始します。"</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"次回から表示しない"</string> diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml index 33dc69fe528a..9f4163f4d918 100644 --- a/packages/SystemUI/res/values-ka-rGE/strings.xml +++ b/packages/SystemUI/res/values-ka-rGE/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"მიმდინარე"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"შეტყობინებები"</string> <string name="battery_low_title" msgid="6456385927409742437">"ბატარეა იწურება"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"დარჩენილია <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"დარჩენილია <xliff:g id="NUMBER">%d%%</xliff:g>. გააქტიურებულია ბატარეის დამზოგი."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"დარჩენილია <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"დარჩენილია <xliff:g id="PERCENTAGE">%s</xliff:g>. ბატარეის დაზოგვა ჩართულია."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB-ით დატენვა არ არის მხარდაჭერილი.\nგამოიყენეთ მხოლოდ ელექტრო-დამტენი."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB დატენვა მხარდაჭერილი არ არის."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"გამოიყენეთ მხოლოდ მოყოლილი დამტენი."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string> <string name="ethernet_label" msgid="7967563676324087464">"ეთერნეტი"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"თვითმფრინავის რეჟიმი"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"დამუხტვა, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"დამუხტულია"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> მოწყობილობა)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth გამორთულია"</string> @@ -277,7 +275,8 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> გაფრთხილება"</string> <string name="recents_empty_message" msgid="8682129509540827999">"თქვენი ბოლო ეკრანები აქ გამოჩნდება"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"აპლიკაციის შესახებ"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"აპზე ფიქსაცია"</string> + <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) --> + <skip /> <string name="recents_search_bar_label" msgid="8074997400187836677">"ძიება"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>-ის გამოძახება ვერ მოხერხდა."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"დატენილია"</string> @@ -324,7 +323,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"ბატარეის დამზოგი ჩართულია"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"ამცირებს წარმადობას და უკანა ფონის მონაცემებს"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"ბატარეის დაზოგვის გამორთვა"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"შიგთავსი დამალულია"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> დაიწყებს იმ ყველაფრის აღბეჭდვას, რაც თქვენს ეკრანზე ჩანს."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"აღარ მაჩვენო"</string> diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml index 5c290e4cbb08..34ee563adbfe 100644 --- a/packages/SystemUI/res/values-kk-rKZ/strings.xml +++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Ағымдағы"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Хабарлар"</string> <string name="battery_low_title" msgid="6456385927409742437">"Батарея заряды төмен"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> қуат қалды"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> қалды. Батарея үнемдегіш қосулы."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> қалды"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> қалды. Батарея үнемдегіш қосулы."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB зарядтауды қолдау ұсынылмаған.\nЖабдықталған зарядтағыш құрылғысын ғана қолданыңыз."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB арқылы зарядтауға қолдау көрсетілмейді."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Тек жинақтағы зарядтағышты пайдаланыңыз."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Қалғу"</string> <string name="ethernet_label" msgid="7967563676324087464">"Этернет"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Ұшақ режимі"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Зарядтауда, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Зарядталды"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> құрылғылары)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth өшірулі"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> туралы ескерту"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Мұнда жақындағы экрандар көрсетіледі"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Қолданба туралы ақпарат"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"қолданбаға бекіту"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"экранды бекіту"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"іздеу"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> іске қосу мүмкін болмады."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Зарядталды"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Батарея үнемдегіш қосулы"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Өнімділікті және фондық деректерді азайтады"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Батарея үнемдегішті өшіру"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Мазмұн жасырылған"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> экранда көрсетілгеннің барлығын түсіре бастайды."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Қайта көрсетпеу"</string> diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml index 264be48b1925..efa9eb72484c 100644 --- a/packages/SystemUI/res/values-km-rKH/strings.xml +++ b/packages/SystemUI/res/values-km-rKH/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"បន្ត"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"ការជូនដំណឹង"</string> <string name="battery_low_title" msgid="6456385927409742437">"ជិតអស់ថ្មហើយ"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"នៅសល់ <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"នៅសល់ <xliff:g id="NUMBER">%d%%</xliff:g> ។ កម្មវិធីសន្សំថ្មគឺបើក។"</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"នៅសល់ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"នៅសល់ <xliff:g id="PERCENTAGE">%s</xliff:g> ។ កម្មវិធីសន្សំថ្មគឺបើក។"</string> <string name="invalid_charger" msgid="4549105996740522523">"មិនគាំទ្រការបញ្ចូលតាមយូអេសប៊ី។\nប្រើតែឧបករណ៍បញ្ចូលថ្មដែលបានផ្ដល់។"</string> <string name="invalid_charger_title" msgid="3515740382572798460">"មិនគាំទ្រការបញ្ចូលថ្មតាមយូអេសប៊ីទេ។"</string> <string name="invalid_charger_text" msgid="5474997287953892710">"ប្រើតែឧបករណ៍បញ្ចូលថ្មដែលបានផ្ដល់ឲ្យ។"</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"ធាតុរក្សាអេក្រង់"</string> <string name="ethernet_label" msgid="7967563676324087464">"អ៊ីសឺរណិត"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"របៀបពេលជិះយន្តហោះ"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"បញ្ចូលថ្ម <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"បានបញ្ចូលពេញ"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ប៊្លូធូស"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ប៊្លូធូស (ឧបករណ៍ <xliff:g id="NUMBER">%d</xliff:g>)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ប៊្លូធូសបានបិទ"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ការព្រមាន"</string> <string name="recents_empty_message" msgid="8682129509540827999">"អេក្រង់បច្ចុប្បន្នរបស់អ្នកបង្ហាញនៅទីនេះ"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"ព័ត៌មានកម្មវិធី"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"ចាក់សោទៅកម្មវិធី"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ការភ្ជាប់អេក្រង់"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"ស្វែងរក"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"មិនអាចចាប់ផ្ដើម <xliff:g id="APP">%s</xliff:g> ទេ។"</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"បានបញ្ចូលថ្ម"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"កម្មវិធីសន្សំថ្មគឺបើក"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"ការបន្ថយការប្រតិបត្តិ និងទិន្នន័យផ្ទៃខាងក្រោយ"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"បិទធាតុរក្សាថាមពលថ្ម"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"បានលាក់មាតិកា"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> នឹងចាប់ផ្ដើមចាប់យកអ្វីៗគ្រប់យ៉ាងដែលបង្ហាញលើអេក្រង់របស់អ្នក។"</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"កុំបង្ហាញម្ដងទៀត"</string> diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml index 83699b13ef24..99d8acdffdf7 100644 --- a/packages/SystemUI/res/values-kn-rIN/strings.xml +++ b/packages/SystemUI/res/values-kn-rIN/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ಚಾಲ್ತಿಯಲ್ಲಿರುವ"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"ಅಧಿಸೂಚನೆಗಳು"</string> <string name="battery_low_title" msgid="6456385927409742437">"ಬ್ಯಾಟರಿ ಕಡಿಮೆ ಇದೆ"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> ಉಳಿದಿದೆ"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> ಉಳಿದಿದೆ. ಬ್ಯಾಟರಿ ರಕ್ಷಕ ಆನ್ ಆಗಿದೆ."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ಉಳಿದಿದೆ"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> ಉಳಿದಿದೆ. ಬ್ಯಾಟರಿ ಉಳಿತಾಯ ಆನ್ ಆಗಿದೆ."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB ಚಾರ್ಜಿಂಗ್ ಬೆಂಬಲಿತವಾಗಿಲ್ಲ.\nಒದಗಿಸಿರುವ ಚಾರ್ಜರ್ ಮಾತ್ರ ಬಳಸಿ."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB ಚಾರ್ಜಿಂಗ್ ಬೆಂಬಲಿತವಾಗಿಲ್ಲ."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"ಒದಗಿಸಿರುವ ಚಾರ್ಜರ್ ಮಾತ್ರ ಬಳಸಿ."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"ಡೇಡ್ರೀಮ್"</string> <string name="ethernet_label" msgid="7967563676324087464">"ಇಥರ್ನೆಟ್"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"ಏರ್ಪ್ಲೇನ್ ಮೋಡ್"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ಬ್ಲೂಟೂತ್"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ಬ್ಲೂಟೂತ್ (<xliff:g id="NUMBER">%d</xliff:g> ಸಾಧನಗಳು)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ಬ್ಲೂಟೂತ್ ಆಫ್"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ಎಚ್ಚರಿಕೆ"</string> <string name="recents_empty_message" msgid="8682129509540827999">"ನಿಮ್ಮ ಇತ್ತೀಚಿನ ಪರದೆಗಳು ಇಲ್ಲಿ ಕಾಣಿಸಿಕೊಳ್ಳುತ್ತವೆ"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"ಅಪ್ಲಿಕೇಶನ್ಗೆ ಲಾಕ್"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ಪರದೆ ಪಿನ್ನಿಂಗ್"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"ಹುಡುಕಾಟ"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ಪ್ರಾರಂಭಿಸಲು ಸಾದ್ಯವಿಲ್ಲ."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"ಬ್ಯಾಟರಿ ರಕ್ಷಕ ಆನ್ ಆಗಿದೆ"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"ಕಾರ್ಯಕ್ಷಮತೆ ಮತ್ತು ಹಿನ್ನೆಲೆ ಡೇಟಾವನ್ನು ಕಡಿಮೆ ಮಾಡುತ್ತದೆ"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"ಬ್ಯಾಟರಿ ಉಳಿತಾಯವನ್ನು ಆಫ್ ಮಾಡಿ"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"ವಿಷಯಗಳನ್ನು ಮರೆಮಾಡಲಾಗಿದೆ"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"ನಿಮ್ಮ ಪರದೆಯ ಮೇಲೆ ಪ್ರದರ್ಶಿಸಲಾಗುವ ಎಲ್ಲವನ್ನೂ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ಯು ಸೆರೆಹಿಡಿಯಲು ಪ್ರಾರಂಭಿಸುತ್ತದೆ."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"ಮತ್ತೊಮ್ಮೆ ತೋರಿಸದಿರಿ"</string> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 460837ed1ecd..f00bc0176dc0 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -33,10 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"진행 중"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"알림"</string> <string name="battery_low_title" msgid="6456385927409742437">"배터리 부족"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> 남음"</string> - <!-- String.format failed for translation --> - <!-- no translation found for battery_low_percent_format_saver_started (6534746636002666456) --> - <skip /> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> 남았습니다."</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> 남았습니다. 배터리 절약 기능을 사용 중입니다."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB 충전이 지원되지 않습니다.\n제공된 충전기만 사용하세요."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB 충전은 지원되지 않습니다."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"제공된 충전기만 사용하세요."</string> @@ -226,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"화면 보호기"</string> <string name="ethernet_label" msgid="7967563676324087464">"이더넷"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"비행기 모드"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"충전 중(<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"충전됨"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"블루투스"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"블루투스(<xliff:g id="NUMBER">%d</xliff:g>개의 기기)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"블루투스 사용 안함"</string> @@ -279,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> 경고"</string> <string name="recents_empty_message" msgid="8682129509540827999">"여기에 최근 화면이 표시됩니다."</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"애플리케이션 정보"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"앱에 잠금"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"화면 고정"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"검색"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>을(를) 시작할 수 없습니다."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"충전됨"</string> @@ -326,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"배터리 세이버 사용 중"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"성능 및 백그라운드 데이터를 줄입니다."</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"배터리 절약 기능 사용 중지"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"숨겨진 콘텐츠"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>에서 화면에 표시된 모든 것을 캡처하기 시작합니다."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"다시 표시 안함"</string> diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml index c64878fcec15..fc2281567f7f 100644 --- a/packages/SystemUI/res/values-ky-rKG/strings.xml +++ b/packages/SystemUI/res/values-ky-rKG/strings.xml @@ -38,9 +38,8 @@ <!-- no translation found for status_bar_latest_events_title (6594767438577593172) --> <skip /> <string name="battery_low_title" msgid="6456385927409742437">"Батареянын кубаты аз"</string> - <!-- no translation found for battery_low_percent_format (1077244949318261761) --> - <skip /> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> калды. Батарея үнөмдөгүч күйгүзүлдү."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> калды"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> калды. Батареянын кубатын үнөмдөгүч күйүк."</string> <!-- no translation found for invalid_charger (4549105996740522523) --> <skip /> <string name="invalid_charger_title" msgid="3515740382572798460">"USB аркылуу кубаттоого болбойт."</string> @@ -250,8 +249,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Кыялдануу"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Учак тартиби"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Дүрмөттөлүүдө, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Дүрмөттөлгөн"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> түзмөк)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth өчүк"</string> @@ -303,7 +300,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> эскертүү"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Акыркы экрандарыңыз бул жерден көрүнөт"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Колдонмо жөнүндө маалымат"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"колдонмого кулпулоо"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"экран кадоо"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"издөө"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> баштай алган жок."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Кубатталды"</string> @@ -350,7 +347,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Батареяны үнөмдөгүч күйгүзүлдү"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Иштин майнаптуулугун начарлатып, фондук дайындарды чектейт"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Батареянын кубатын үнөмдөгүчтү өчүрүп коюу"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Мазмундар жашырылган"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> экранга чыккан нерсенин баарын сүрөткө тарта баштайт."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Экинчи көрсөтүлбөсүн"</string> diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml index fa634ae39603..79a225dc0912 100644 --- a/packages/SystemUI/res/values-lo-rLA/strings.xml +++ b/packages/SystemUI/res/values-lo-rLA/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ດຳເນີນຢູ່"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"ການແຈ້ງເຕືອນ"</string> <string name="battery_low_title" msgid="6456385927409742437">"ແບັດເຕີຣີເຫຼືອໜ້ອຍ"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"ຍັງເຫຼືອອີກ <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"ຍັງເຫຼືອ <xliff:g id="NUMBER">%d%%</xliff:g>. ເປີດນຳໃຊ້ໂຕປະຢັດແບັດເຕີຣີຢູ່."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"ຍັງເຫຼືອ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"ຍັງເຫຼືອ <xliff:g id="PERCENTAGE">%s</xliff:g>. ການປະຢັດແບັດເຕີຣີໄດ້ຖືກເປີດໃຊ້ແລ້ວ."</string> <string name="invalid_charger" msgid="4549105996740522523">"ບໍ່ຮອງຮັບການສາກໄຟດ້ວຍ USB.\nຕ້ອງໃຊ້ສະເພາະເຄື່ອງສາກທີ່ແຖມມານຳເທົ່ານັ້ນ."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"ບໍ່ຮອງຮັບການສາກຜ່ານ USB."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"ໃຊ້ສະເພາະສາຍສາກທີ່ມາກັບເຄື່ອງ."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"ໂໝດຢູ່ໃນຍົນ"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"ກຳລັງສາກ, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"ສາກເຕັມແລ້ວ"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> ອຸປະກອນ)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth ປິດ"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"ຄຳເຕືອນ <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Your recent screens appear here"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"ຂໍ້ມູນແອັບພລິເຄຊັນ"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lock to app"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ການປັກໝຸດໜ້າຈໍ"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"ຊອກຫາ"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"ບໍ່ສາມາດເລີ່ມ <xliff:g id="APP">%s</xliff:g> ໄດ້."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ສາກເຕັມແລ້ວ."</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"ເປີດໃຊ້ໂຕປະຢັດແບັດເຕີຣີແລ້ວ"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"ຫຼຸດປະສິທິພາບແລະການນຳໃຊ້ຂໍ້ມູນພື້ນຫຼັງ"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"ປິດໂຕປະຢັດແບັດເຕີຣີ"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"ເນື້ອຫາຖືກເຊື່ອງໄວ້"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ຈະເລີ່ມບັນທຶກທຸກຢ່າງທີ່ສະແດງຜົນໃນໜ້າຈໍທ່ານ."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"ບໍ່ຕ້ອງສະແດງອີກ"</string> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 79522ca7831f..376d78eff041 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Vykstantys"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Pranešimai"</string> <string name="battery_low_title" msgid="6456385927409742437">"Akumuliatorius senka"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"Liko <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Liko <xliff:g id="NUMBER">%d%%</xliff:g>. Akumuliatoriaus tausojimo priemonė įjungta."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Liko <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Liko <xliff:g id="PERCENTAGE">%s</xliff:g>. Akumuliatoriaus tausojimo programa įjungta."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB krovimas nepalaikomas.\nNaudokite tik pateiktą įkroviklį."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB įkrovimas nepalaikomas."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Naudokite tik pateiktą kroviklį."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Svajonė"</string> <string name="ethernet_label" msgid="7967563676324087464">"Eternetas"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Lėktuvo režimas"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Įkraunama, <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Įkrauta"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"„Bluetooth“ (<xliff:g id="NUMBER">%d</xliff:g> įreng.)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"„Bluetooth“ išjungta"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> įspėjimas"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Čia rodomi naujausi ekranai"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Programos informacija"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"Programos užrakinimo funkcija"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekrano prisegimas"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"paieška"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Nepavyko paleisti <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Įkrautas"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Akumuliatoriaus tausojimo priemonė įjungta"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Sumažinamas našumas ir foninių duomenų naudojimas"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Išjungti Akumuliatoriaus tausojimo priemonę"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g> %%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Turinys paslėptas"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"„<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“ pradės fiksuoti viską, kas rodoma jūsų ekrane."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Daugiau neberodyti"</string> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 1f5eaefbcd36..fe88b1089748 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Notiekošs"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Paziņojumi"</string> <string name="battery_low_title" msgid="6456385927409742437">"Zems akumulatora enerģijas līmenis"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"Atlicis: <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Atlikuši <xliff:g id="NUMBER">%d%%</xliff:g>. Ir ieslēgts akumulatora enerģijas taupīšanas režīms."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Atlikuši <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Atlikuši <xliff:g id="PERCENTAGE">%s</xliff:g>. Ir ieslēgts akumulatora jaudas taupīšanas režīms."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB lādēšana netiek atbalstīta.\nIzmantojiet tikai komplektā iekļauto lādētāju."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB uzlāde netiek atbalstīta."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Izmantojiet tikai komplektā iekļauto lādētāju."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Ekrānsaudzētājs"</string> <string name="ethernet_label" msgid="7967563676324087464">"Tīkls Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Lidojuma režīms"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Notiek uzlāde, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Uzlādēts"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> ierīce(-es))"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth savienojums ir izslēgts."</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> brīdinājums"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Jūsu pēdējie ekrāni tiek rādīti šeit."</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informācija par lietojumprogrammu"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"fiksēt lietotni"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Piespraust ekrānu"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"Meklēt"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Nevarēja palaist lietotni <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Akumulators uzlādēts"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Ieslēgts akumulatora enerģijas taupīšanas režīms"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Samazina veiktspēju un fona datus"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Izslēgt akumulatora jaudas taupīšanu"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Saturs paslēpts"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sāks uzņemt visu, kas tiks rādīts jūsu ekrānā."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Vairs nerādīt"</string> diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml index f645a5cbd11a..67d6f6630615 100644 --- a/packages/SystemUI/res/values-mk-rMK/strings.xml +++ b/packages/SystemUI/res/values-mk-rMK/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Во тек"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Известувања"</string> <string name="battery_low_title" msgid="6456385927409742437">"Батеријата е слаба"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"Преостануваат <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Преостануваат <xliff:g id="NUMBER">%d%%</xliff:g>. Штедачот на батерија е вклучен."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Преостануваат <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Преостануваат <xliff:g id="PERCENTAGE">%s</xliff:g>. Вклучен е штедачот на батерија."</string> <string name="invalid_charger" msgid="4549105996740522523">"Полначот на УСБ меморијата не е поддржан.\nКористете го само полначот доставен со уредот."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Полнењето преку УСБ не е поддржано."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Користете го само доставениот полнач."</string> @@ -226,8 +226,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string> <string name="ethernet_label" msgid="7967563676324087464">"Етернет"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Режим на работа во авион"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Се полни, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Наполнета"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> уреди)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth е исклучен"</string> @@ -279,7 +277,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Предупредување за <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Вашите неодамнешни екрани се појавуваат тука"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Информации за апликацијата"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"заклучи на апликација"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"прикачување екран"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"пребарај"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> не може да се вклучи."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Наполнета"</string> @@ -326,7 +324,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Штедачот на батерија е вклучен"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Ја намалува изведбата и податоците во заднина"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Исклучете го штедачот на батерија"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Содржините се скриени"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ќе започне да презема сѐ што се прикажува на вашиот екран."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Не покажувај повторно"</string> diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml index 4a2d80aebdf5..ec22c9149b2b 100644 --- a/packages/SystemUI/res/values-ml-rIN/strings.xml +++ b/packages/SystemUI/res/values-ml-rIN/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"നടന്നുകൊണ്ടിരിക്കുന്നവ"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"അറിയിപ്പുകൾ"</string> <string name="battery_low_title" msgid="6456385927409742437">"ബാറ്ററി നില കുറവാണ്"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> ശേഷിക്കുന്നു"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> ശേഷിക്കുന്നു. ബാറ്ററി സേവർ ഓണാണ്."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ശേഷിക്കുന്നു"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> ശേഷിക്കുന്നു. ബാറ്ററി സേവർ ഓണാണ്."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB ചാർജ്ജുചെയ്യൽ പിന്തുണയ്ക്കുന്നില്ല.\nഅതിന്റെ അനുബന്ധ ചാർജ്ജർ മാത്രം ഉപയോഗിക്കുക."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB ചാർജ്ജുചെയ്യൽ പിന്തുണച്ചില്ല."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"വിതരണം ചെയ്ത ചാർജ്ജർ മാത്രം ഉപയോഗിക്കുക."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"ഡേഡ്രീം"</string> <string name="ethernet_label" msgid="7967563676324087464">"ഇതർനെറ്റ്"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"ഫ്ലൈറ്റ് മോഡ്"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"ചാർജ്ജുചെയ്യുന്നു, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"ചാർജ്ജുചെയ്തു"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ബ്ലൂടൂത്ത്"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ബ്ലൂടൂത്ത് (<xliff:g id="NUMBER">%d</xliff:g> ഉപകരണങ്ങൾ)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ബ്ലൂടൂത്ത് ഓഫുചെയ്യുക"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> മുന്നറിയിപ്പ്"</string> <string name="recents_empty_message" msgid="8682129509540827999">"നിങ്ങളുടെ പുതിയ സ്ക്രീനുകൾ ഇവിടെ ദൃശ്യമാകുന്നു"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"അപ്ലിക്കേഷൻ വിവരം"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"അപ്ലിക്കേഷനിലേക്ക് ലോക്കുചെയ്യൽ"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"സ്ക്രീൻ പിൻ ചെയ്യൽ"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"തിരയുക"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ആരംഭിക്കാനായില്ല."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ചാർജ്ജുചെയ്തു"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"ബാറ്ററി സേവർ ഓണാണ്"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"പ്രവർത്തനവും പശ്ചാത്തല ഡാറ്റയും കുറയ്ക്കുന്നു"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"ബാറ്ററി സേവർ ഓഫാക്കുക"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"കോൺടാക്റ്റുകൾ മറച്ചു"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"നിങ്ങളുടെ സ്ക്രീനിൽ പ്രദർശിപ്പിച്ചിരിക്കുന്ന എല്ലാ കാര്യങ്ങളും <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ക്യാപ്ചർ ചെയ്യുന്നത് ആരംഭിക്കും."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"വീണ്ടും കാണിക്കരുത്"</string> diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml index 47b6cbfe6ab2..7c475a98261d 100644 --- a/packages/SystemUI/res/values-mn-rMN/strings.xml +++ b/packages/SystemUI/res/values-mn-rMN/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Гарсан"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Мэдэгдэл"</string> <string name="battery_low_title" msgid="6456385927409742437">"Батерей дуусаж байна"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> үлдсэн"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> үлдсэн. Батерей хэмнэгч асаалттай."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> үлдсэн"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> үлдсэн. Батерей хэмнэгч ассан."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB цэнэглэлт дэмжигдэхгүй байна.\nЗөвхөн нийлүүлэгдсэн цэнэглэгчийг ашиглана уу."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB-р цэнэглэх дэмжигддэггүй."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Зөвхөн зориулалтын ирсэн цэнэглэгч ашиглана уу."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string> <string name="ethernet_label" msgid="7967563676324087464">"Этернет"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Нислэгийн горим"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Цэнэглэж байна, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Цэнэглэгдсэн"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Блютүүт"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Блютүүт (<xliff:g id="NUMBER">%d</xliff:g> төхөөрөмж)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Блютүүт унтраалттай"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> анхааруулга"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Таны саяхны дэлгэц энд харагдах болно"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Аппликешны мэдээлэл"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"Апп-дотор-түгжих"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"дэлгэц тогтоох"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"хайх"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>-г эхлүүлж чадсангүй."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Цэнэглэгдсэн"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Батерей хэмнэгч асаалттай"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Ажиллагаа болон далд датаг бууруулна"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Батерей хэмнэгчийг унтраах"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Контентыг нуусан"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> таны дэлгэц дээр гаргасан бүх зүйлийн зургийг авч эхэлнэ."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Дахиж үл харуулах"</string> diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml index 22ba18f67657..7b3934ca5728 100644 --- a/packages/SystemUI/res/values-mr-rIN/strings.xml +++ b/packages/SystemUI/res/values-mr-rIN/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"सुरु असलेले"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"सूचना"</string> <string name="battery_low_title" msgid="6456385927409742437">"बॅटरी कमी आहे"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> शिल्लक"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> उर्वरित. बॅटरी बचतकर्ता चालू आहे."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> शिल्लक"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> शिल्लक. बॅटरी बचतकर्ता चालू आहे."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB चार्जिंग समर्थित नाही.\nफक्त पुरवठा केलेले चार्जर वापरा."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB चार्जिंग समर्थित नाही."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"केवळ पुरविलेले चार्जर वापरा."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"डेड्रीम"</string> <string name="ethernet_label" msgid="7967563676324087464">"इथरनेट"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"विमान मोड"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"चार्ज होत आहे, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"चार्ज झाली"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ब"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ब (<xliff:g id="NUMBER">%d</xliff:g> डिव्हाइसेस)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ब बंद"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> चेतावणी"</string> <string name="recents_empty_message" msgid="8682129509540827999">"आपल्या अलीकडील स्क्रीन येथे दिसतात"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"अनुप्रयोग माहिती"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"अॅप-लॉक-करणे"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"स्क्रीन पिन करणे"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"शोधा"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> प्रारंभ करणे शक्य झाले नाही."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"चार्ज झाली"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"बॅटरी बचतकर्ता चालू आहे"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"कार्यप्रदर्शन आणि पार्श्वभूमी डेटा कमी करते"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"बॅटरी बचतकर्ता बंद करा"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"लपविलेली सामग्री"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> आपल्या स्क्रीनवर प्रदर्शित होणारी प्रत्येक गोष्ट कॅप्चर करणे प्रारंभ करेल."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"पुन्हा दर्शवू नका"</string> diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml index 8eee0a3c65c9..27b218447c9c 100644 --- a/packages/SystemUI/res/values-ms-rMY/strings.xml +++ b/packages/SystemUI/res/values-ms-rMY/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Sedang berlangsung"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Pemberitahuan"</string> <string name="battery_low_title" msgid="6456385927409742437">"Bateri lemah"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"Berbaki <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Tinggal <xliff:g id="NUMBER">%d%%</xliff:g>. Penjimat bateri dihidupkan."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> yang tinggal"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> yang tinggal. Penjimat bateri dihidupkan."</string> <string name="invalid_charger" msgid="4549105996740522523">"Pengecasan USB tidak disokong.\nGunakan hanya pengecas yang dibekalkan."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Pengecasan USB tidak disokong."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Gunakan pengecas yang dibekalkan sahaja."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Lamun"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mod kapal terbang"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Mengecas, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Sudah dicas"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Peranti)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Dimatikan"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Amaran <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Skrin terbaru anda terpapar di sini"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Maklumat Aplikasi"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"kunci ke apl"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"penyematan skrin"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"cari"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Tidak dapat memulakan <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Sudah dicas"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Penjimat bateri dihidupkan"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Mengurangkan prestasi dan data latar belakang"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Matikan penjimat bateri"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Kandungan tersembunyi"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> akan mula mengabadikan semua yang dipaparkan pada skrin anda.."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Jangan tunjukkan lagi"</string> diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml index b4f832cdd17b..6d7941f99502 100644 --- a/packages/SystemUI/res/values-my-rMM/strings.xml +++ b/packages/SystemUI/res/values-my-rMM/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"လက်ရှိအသုံးပြုမှု"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"အကြောင်းကြားချက်များ။"</string> <string name="battery_low_title" msgid="6456385927409742437">"ဘက်ထရီ အားနည်းနေ"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> ကျန်ရှိသည်"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> ကျန်နေ။ ဘက်ထရီ ချွေတာသူ ဖွင့်ထား။"</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ကျန်ရှိနေ"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> ကျန်ရှိနေ။ ဘက်ထရီ ချွေတာမှု ဖွင့်ထား။"</string> <string name="invalid_charger" msgid="4549105996740522523">"လက်ရှိUSBအားသွင်းခြင်း အသုံးမပြုနိုင်ပါ \n ပေးထားသောအားသွင်းကိရိယာကိုသာ အသုံးပြုပါ"</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB အားသွင်းမှု မပံ့ပိုးပါ။"</string> <string name="invalid_charger_text" msgid="5474997287953892710">"ပေးခဲ့သည့် အားသွင်းစက်ကိုသာ အသုံးပြုပါ"</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"ဒေးဒရင်းမ်"</string> <string name="ethernet_label" msgid="7967563676324087464">"အီသာနက်"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"လေယာဥ်ပျံပေါ်အသုံးပြုသောစနစ်"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"အားသွင်းနေစဉ်, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"အားပြည့်"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ဘလူးတု"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ဘလူးတု (<xliff:g id="NUMBER">%d</xliff:g> စက်များ)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ဘလူးတု ပိတ်ထားရန်"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> သတိပေးချက်"</string> <string name="recents_empty_message" msgid="8682129509540827999">"သင်၏ မကြာမီက မျက်နှာပြင်များ ဒီမှာ ပေါ်လာကြမည်"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"အပလီကေးရှင်း အင်ဖို"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"appသို့ သော့ခတ်ထားရန်"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"မျက်နှာပြင် ပင်ထိုးမှု"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"ရှာဖွေရန်"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ကို မစနိုင်ပါ။"</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"အားသွင်းပြီး"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"ဘက်ထရီ ချွေတာသူ ဖွင့်ထား"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"လုပ်ကိုင်မှုကို လျှော့ချလျက် နောက်ခံ ဒေတာကို ကန့်သတ်သည်"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"ဘက်ထရီ ချွေတာမှုကို ပိတ်ထားရန်"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"အကြောင်းအရာများ ဝှက်ထား"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> က သင်၏ မျက်နှာပြင် ပေါ်မှာ ပြသထားသည့် အရာတိုင်းကို စတင် ဖမ်းယူမည်။"</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"နောက်ထပ် မပြပါနှင့်"</string> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 76d9598f3dc0..da01a12abc24 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Aktiviteter"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Varsler"</string> <string name="battery_low_title" msgid="6456385927409742437">"Batterikapasiteten er lav"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> gjenværende"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> gjenstår. Batterisparing er på."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> gjenstår"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> gjenstår. Batterisparing er på."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB-lading støttes ikke.\nBruk kun den medfølgende laderen."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Lading via USB støttes ikke."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Bruk bare den tilhørende laderen."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Dagdrøm"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flymodus"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Lader: <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Oppladet"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> enheter)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth er slått av"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advarsel for <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"De sist brukte skjermene dine vises her"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Appinformasjon"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lås til app"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"én-appsmodus"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"Søk"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Kunne ikke starte <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Oppladet"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Batterisparing er på"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Reduserer ytelsen og begrenser bakgrunnsdataene"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Slå av batterisparing"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g> %%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Innholdet er skjult"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tar opp alt som vies på skjermen din."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Ikke vis igjen"</string> diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml index a8d0337fe3f4..6caf070d9640 100644 --- a/packages/SystemUI/res/values-ne-rNP/strings.xml +++ b/packages/SystemUI/res/values-ne-rNP/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"चलिरहेको"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"सूचनाहरू"</string> <string name="battery_low_title" msgid="6456385927409742437">"ब्याट्रि कम छ"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> बाँकी"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> बाँकी। ब्याट्रि सेभर चालु छ।"</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> बाँकी"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> बाँकी। ब्याट्री बचत खुलै छ।"</string> <string name="invalid_charger" msgid="4549105996740522523">"USB चार्ज गर्न समर्थित छैन।\n आपूर्ति गरिएको चार्जर मात्र प्रयोग गर्नुहोस्।"</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB चार्ज समर्थित छैन।"</string> <string name="invalid_charger_text" msgid="5474997287953892710">"आपूर्ति गरिएको चार्जर मात्र प्रयोग गर्नुहोस्।"</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"दिवासपना"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"हवाइजहाज मोड"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"चार्ज हुँदै, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"चार्ज भयो"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ब्लुटुथ"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ब्लुटुथ (<xliff:g id="NUMBER">%d</xliff:g> उपकरणहरू)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ब्लुटुथ बन्द"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> चेतावनी दिँदै"</string> <string name="recents_empty_message" msgid="8682129509540827999">"तपाईँको हालको स्क्रिन यहाँ प्रकट हुन्छ"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"अनुप्रयोग जानकारी"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"अनुप्रयोग बन्द गर्न"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"स्क्रिन पिन गर्दै"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"खोजी गर्नुहोस्"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"सुरु गर्न सकिएन <xliff:g id="APP">%s</xliff:g>।"</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"चार्ज भयो"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"ब्याट्रि सेभर चालु छ"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"प्रदर्शन र पृष्ठभूमि डेटा घटाउँनुहोस्"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"ब्याट्री बचत बन्द गर्नुहोस्"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"लुकेका सामाग्रीहरू"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ले आफ्नो स्क्रीनमा प्रदर्शित हुने सबै खिच्न शुरू गर्नेछ।"</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"फेरि नदेखाउनुहोस्"</string> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 8b474c772f34..2663231c1ec1 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Actief"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meldingen"</string> <string name="battery_low_title" msgid="6456385927409742437">"Accu is bijna leeg"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> resterend"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> resterend. Accubesparing is ingeschakeld."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> resterend"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> resterend. Accubesparing is ingeschakeld."</string> <string name="invalid_charger" msgid="4549105996740522523">"Opladen via USB niet ondersteund.\nGebruik alleen de bijgeleverde oplader."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Opladen via USB wordt niet ondersteund."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Gebruik alleen de bijgeleverde oplader."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Dagdroom"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Vliegmodus"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Opladen, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Opgeladen"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> apparaten)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth uit"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Waarschuwing voor <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Uw recente schermen worden hier weergegeven"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"App-informatie"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"app-slot"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"scherm vastzetten"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"zoeken"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Kan <xliff:g id="APP">%s</xliff:g> niet starten."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Opgeladen"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Accubesparing is ingeschakeld"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Vermindert de prestaties en achtergrondgegevens"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Accubesparing uitschakelen"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Inhoud verborgen"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> gaat alles vastleggen dat wordt weergegeven op uw scherm."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Niet opnieuw weergeven"</string> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 2f7a742a0af7..fc79990d3586 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Bieżące"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Powiadomienia"</string> <string name="battery_low_title" msgid="6456385927409742437">"Bateria jest słaba"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"Pozostało: <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Zostało <xliff:g id="NUMBER">%d%%</xliff:g>. Oszczędzanie baterii jest włączone."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Pozostało <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Pozostało <xliff:g id="PERCENTAGE">%s</xliff:g>. Oszczędzanie baterii jest włączone."</string> <string name="invalid_charger" msgid="4549105996740522523">"Ładowanie przy użyciu złącza USB nie jest obsługiwane.\nNależy używać tylko dołączonej ładowarki."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Ładowanie przez USB nie jest obsługiwane."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Używaj tylko ładowarki dostarczonej z urządzeniem."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Wygaszacz ekranu"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Tryb samolotowy"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Ładowanie (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Naładowana"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (urządzenia: <xliff:g id="NUMBER">%d</xliff:g>)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth wył."</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Ostrzeżenie: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Tutaj pojawią się ostatnie ekrany"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacje o aplikacji"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"zablokuj na aplikacji"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"przypinanie ekranu"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"szukaj"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Nie udało się uruchomić aplikacji <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Naładowana"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Oszczędzanie baterii jest włączone"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Zmniejsza wydajność i ogranicza dane w tle"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Wyłącz oszczędzanie baterii"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Treści ukryte"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> będzie zapisywać wszystko, co wyświetli się na ekranie."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Nie pokazuj ponownie"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index c06be788fc91..bc345b169ebc 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Em curso"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificações"</string> <string name="battery_low_title" msgid="6456385927409742437">"Bateria fraca"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> restante"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> restantes. A Poupança de bateria está ligada."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante. A poupança da bateria está ativada."</string> <string name="invalid_charger" msgid="4549105996740522523">"Carregamento USB não suportado. \nUtilize apenas o carregador fornecido."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"O carregamento por USB não é suportado."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Utilize apenas o carregador fornecido."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo de avião"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"A carregar, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Carregada"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Dispositivos)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desat."</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Aviso de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Os ecrãs recentes aparecem aqui"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informações da aplicação"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"bloquear numa aplicação"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixação no ecrã"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Não foi possível iniciar o <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"A poupança de bateria está ligada"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Reduz o desempenho e os dados de segundo plano"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Desativar a poupança de bateria"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Conteúdo oculto"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"O(a) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vai começar a captar tudo o que é apresentado no ecrã."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Não mostrar de novo"</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 075cdf1ece8f..4d8b1d07a9ca 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Em andamento"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificações"</string> <string name="battery_low_title" msgid="6456385927409742437">"Bateria fraca"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> restante"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> restante(s). A Economia de bateria está ativada."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> restantes"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> restantes. A Economia de bateria está ativada."</string> <string name="invalid_charger" msgid="4549105996740522523">"O carregamento via USB não é suportado.\nUse apenas o carregador fornecido."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"O carregamento via USB não é suportado."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Use apenas o carregador fornecido."</string> @@ -226,8 +226,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo avião"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Carregando, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Carregado"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivos)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desativado"</string> @@ -279,7 +277,8 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Aviso de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Suas telas recentes aparecem aqui"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informações do app"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"bloquear no app"</string> + <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) --> + <skip /> <string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Não foi possível iniciar <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string> @@ -326,7 +325,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"A Economia de bateria está ativada"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Reduz o desempenho e os dados em segundo plano"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Desativar a economia de bateria"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Conteúdo oculto"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> começará a capturar tudo o que for exibido na tela."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Não mostrar novamente"</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index bd82615bf853..481a6dd6bfef 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"În desfăşurare"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificări"</string> <string name="battery_low_title" msgid="6456385927409742437">"Bateria este aproape descărcată"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"Rămas: <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Procent rămas din baterie: <xliff:g id="NUMBER">%d%%</xliff:g>. Economisirea bateriei este activată."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Procent rămas din baterie: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Procent rămas din baterie: <xliff:g id="PERCENTAGE">%s</xliff:g>. Economisirea bateriei este activată."</string> <string name="invalid_charger" msgid="4549105996740522523">"Încărcarea USB nu este acceptată. \nUtilizaţi numai încărcătorul furnizat."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Încărcarea prin USB nu este acceptată."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Utilizați numai încărcătorul furnizat."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mod Avion"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Se încarcă, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Încărcată"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispozitive)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth dezactivat"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Avertizare: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Ecranele dvs. recente apar aici"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informații despre aplicație"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"blocare la aplicație"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixare pe ecran"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"căutare"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> nu a putut porni."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"S-a încărcat"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Economisirea bateriei este activată"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Reduce performanța și datele de fundal"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Dezactivați economisirea bateriei"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Conținutul este ascuns"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> va începe să captureze tot ceea ce se afișează pe ecran."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Nu se mai afișează"</string> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 2b77c80dcdde..858b787edeb2 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Текущие"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Уведомления"</string> <string name="battery_low_title" msgid="6456385927409742437">"Батарея почти разряжена"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"Осталось <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Уровень заряда батареи: <xliff:g id="NUMBER">%d%%</xliff:g>. Включен режим энергосбережения."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Осталось: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Осталось: <xliff:g id="PERCENTAGE">%s</xliff:g>. Включен режим энергосбережения."</string> <string name="invalid_charger" msgid="4549105996740522523">"Зарядка через порт USB не поддерживается.\nИспользуйте только зарядное устройство из комплекта поставки."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Зарядка через USB не поддерживается."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Используйте только зарядное устройство, поставляемое в комплекте с устройством."</string> @@ -226,8 +226,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Заставка"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Режим полета"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"100%%"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g>)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth выкл."</string> @@ -279,7 +277,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Предупреждение: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Здесь будут показаны недавние приложения"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Сведения о приложении"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"Блокировать в приложении"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Заблокировать в приложении"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"поиск"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Не удалось запустить приложение \"<xliff:g id="APP">%s</xliff:g>\""</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Батарея заряжена"</string> @@ -326,7 +324,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Включен режим энергосбережения"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Откл. фоновой передачи данных"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Отключить режим энергосбережения"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Содержимое скрыто"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"Приложение <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> получит доступ к изображению на экране устройства."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Больше не показывать"</string> diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml index 0df07ce95fa0..b0a6b47e15c4 100644 --- a/packages/SystemUI/res/values-si-rLK/strings.xml +++ b/packages/SystemUI/res/values-si-rLK/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"දැනට පවතින"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"දැනුම්දීම්"</string> <string name="battery_low_title" msgid="6456385927409742437">"බැටරිය අඩුය"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> ක් ඉතිරියි"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> ක් ඉතිරියි. බැටරිය සුරකින්නා සක්රීයයි."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ඉතිරිව තිබේ"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> ඉතිරිව තිබේ. බැටරිය සුරැකීම සක්රීයි."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB ආරෝපණය සහය නොදක්වයි.\nසපයන ලද ආරෝපකය පමණක් භාවිතා කරන්න."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB ආරෝපණය කිරීම සහාය නොදක්වයි."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"සපයන ලද අරෝපකය පමණක් භාවිතා කරන්න."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"දවල් හීනය"</string> <string name="ethernet_label" msgid="7967563676324087464">"ඊතර නෙට්"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"අහස්යානා ආකාරය"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"ආරෝපණය වෙමින්, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"අරෝපිතයි"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"බ්ලූටූත්"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"බ්ලූටූත් (උපාංග <xliff:g id="NUMBER">%d</xliff:g>)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"බ්ලූටූත් අක්රියයි"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> අවවාද කිරීම"</string> <string name="recents_empty_message" msgid="8682129509540827999">"මෙහි ඔබගේ මෑතක තිර පෙන්නුම් කරයි"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"යෙදුම් තොරතුරු"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"යෙදුමට අඟුළු දැමීම"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"තිර ඇමිණීම"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"සෙවීම"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ආරම්භ කළ නොහැක."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"අරෝපිතයි"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"බැටරිය සුරකින්නා සක්රීයයි"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"ක්රියාකාරිත්වය සහ පසුබිම් දත්ත අඩු කරන්න"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"බැටරි සුරැකීම අක්රිය කරන්න"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"සැඟවුණු සම්බන්ධතා"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"ඔබගේ තීරයේ දර්ශනය වන සෑම දෙයම <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ලබාගැනීම ආරම්භ කරන ලදි."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"නැවත නොපෙන්වන්න"</string> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index f9191ffae031..330331289d58 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Prebiehajúce"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Upozornenia"</string> <string name="battery_low_title" msgid="6456385927409742437">"Batéria je takmer vybitá"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"Zostáva: <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Zostáva: <xliff:g id="NUMBER">%d%%</xliff:g>. Šetrič batérie je zapnutý."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Zostáva <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Zostáva <xliff:g id="PERCENTAGE">%s</xliff:g>. Úspora batérie je zapnutá."</string> <string name="invalid_charger" msgid="4549105996740522523">"Nabíjanie pomocou rozhrania USB nie je podporované.\nPoužívajte iba nabíjačku, ktorá bola dodaná spolu so zariadením."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Nabíjanie prostredníctvom USB nie je podporované."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Používajte iba originálnu nabíjačku."</string> @@ -226,8 +226,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Šetrič obrazovky"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Režim v lietadle"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Nabíjanie, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Nabité"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Rozhranie Bluetooth (počet zariadení: <xliff:g id="NUMBER">%d</xliff:g>)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Rozhranie Bluetooth je vypnuté"</string> @@ -279,7 +277,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Upozornenie pri <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Vaše nedávne obrazovky sa zobrazia tu."</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informácie o aplikácii"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"Uzamknutie v aplikácii"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pripnutie k obrazovke"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"hľadať"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikáciu <xliff:g id="APP">%s</xliff:g> sa nepodarilo spustiť"</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nabitá"</string> @@ -326,7 +324,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Šetrič batérie je zapnutý"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Obmedzí výkonnosť a prenos údajov na pozadí"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Vypnúť šetrič batérie"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g> %%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Skrytý obsah"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"Aplikácia <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> začne zaznamenávať všetok obsah zobrazený na vašej obrazovke."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Nabudúce nezobrazovať"</string> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 140f3e68b038..b6437a2ca436 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Trenutno"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Obvestila"</string> <string name="battery_low_title" msgid="6456385927409742437">"Akumulator je skoraj izpraznjen"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> preostalo"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Še <xliff:g id="NUMBER">%d%%</xliff:g>. Varčevanje z energijo akumulatorja je vklopljeno."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Še <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Še <xliff:g id="PERCENTAGE">%s</xliff:g>. Vklopljeno je varčevanje z energijo akumulatorja."</string> <string name="invalid_charger" msgid="4549105996740522523">"Polnjenje po povezavi USB ni podprto.\nUporabite priloženi polnilnik."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Polnjenje prek USB-ja ni podprto."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Uporabljajte samo priloženi polnilnik."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Sanjarjenje"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Način za letalo"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Polnjenje, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Napolnjeno"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (št. naprav: <xliff:g id="NUMBER">%d</xliff:g>)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth izklopljen"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Opozorilo – <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Vaši nedavni zasloni so prikazani tu"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Podatki o aplikaciji"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"zakleni v aplikacijo"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pripenjanje zaslona"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"iskanje"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikacije <xliff:g id="APP">%s</xliff:g> ni bilo mogoče zagnati."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Akumulator napolnjen"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Varčevanje z energijo akumulatorja je vklopljeno"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Omeji zmogljivost delovanja in prenos podatkov v ozadju"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Izklop varčevanja z energijo akumulatorja"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Vsebina je skrita"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"Aplikacija <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> bo začela zajemati vse, kar je prikazano na zaslonu."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Tega ne prikaži več"</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 4c1d19415da5..d47cf4884d88 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Текуће"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Обавештења"</string> <string name="battery_low_title" msgid="6456385927409742437">"Ниво напуњености батерије је низак"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"преостало је <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Преостало је још <xliff:g id="NUMBER">%d%%</xliff:g>. Штедња батерије је укључена."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Још <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Још <xliff:g id="PERCENTAGE">%s</xliff:g>. Укључена је штедња батерије."</string> <string name="invalid_charger" msgid="4549105996740522523">"Пуњење преко USB-а није подржано.\nКористите само приложени пуњач."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Пуњење преко USB-а није подржано."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Користите само пуњач који сте добили."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Сањарење"</string> <string name="ethernet_label" msgid="7967563676324087464">"Етернет"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Режим рада у авиону"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Пуњење, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Напуњено"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> уређаја)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth искључен"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Упозорење за <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Недавни екрани се појављују овде"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Информације о апликацији"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"закључај апликацију"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"качење екрана"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"претражи"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Покретање апликације <xliff:g id="APP">%s</xliff:g> није успело."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Напуњена је"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Штедња батерије је укључена"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Смањује перформансе и позадинске податке"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Искључи штедњу батерије"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Садржај је сакривен"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ће почети да снима све што се приказује на екрану."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Не приказуј поново"</string> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index c59f6a1f518a..ca0cfc6c0507 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Pågående"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meddelanden"</string> <string name="battery_low_title" msgid="6456385927409742437">"Lågt batteri"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> återstår"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> kvar. Batterisparläget har aktiverats."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> kvar"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> kvar. Batterisparläget är aktiverat."</string> <string name="invalid_charger" msgid="4549105996740522523">"Det går inte att ladda via USB.\nAnvänd endast den laddare som levererades med telefonen."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Det finns inget stöd för laddning via USB."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Använd endast den medföljande laddaren."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Dagdröm"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flygplansläge"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Laddar, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Laddat"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> enheter)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth av"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Varning <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Dina senaste skärmar visas här"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Appinformation"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lås till app"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fästa skärmen"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"sök"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Det gick inte att starta appen <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Laddat"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Batterisparläget har aktiverats"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Minskar prestanda och bakgrundsdata"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Inaktivera batterisparläget"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Innehåll har dolts"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tar en bild av allt som visas på skärmen."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Visa inte igen"</string> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 19cb12543ad4..58e0c411d7ca 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Inaendelea"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Arifa"</string> <string name="battery_low_title" msgid="6456385927409742437">"Betri imeisha"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"Imebakisha <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Imesalia <xliff:g id="NUMBER">%d%%</xliff:g>. Kiokoa betri kimewashwa."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> iliyosalia"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> iliyosalia. Kiokoa betri kimewashwa."</string> <string name="invalid_charger" msgid="4549105996740522523">"Chaji ya USB haihamiliwi.\n Tumia chaka iliyopeanwa."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Kuchaji kwa kutumia USB hakutumiki."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Tumia chaja iliyonunuliwa pamoja na kifaa pekee."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Hali Tulivu"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Hali ya ndege"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Inachaji, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Betri imejaa"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (Vifaa <xliff:g id="NUMBER">%d</xliff:g>)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Imezimwa"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Onyo <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Skrini zako za hivi majuzi huonekana hapa"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Maelezo ya Programu"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lazimisha kutumia programu"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"kudumisha programu moja"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"tafuta"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Haikuweza kuanzisha <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Betri imejaa"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Kiokoa betri kimewashwa"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Hupunguza utendaji na data ya chini chini"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Zima kiokoa betri"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Maudhui yamefichwa"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> itaanza kupiga picha kila kitu kinachoonyeshwa kwenye skrini yako."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Usionyeshe tena"</string> diff --git a/packages/SystemUI/res/values-sw360dp/dimens.xml b/packages/SystemUI/res/values-sw360dp/dimens.xml new file mode 100644 index 000000000000..dfd97435a288 --- /dev/null +++ b/packages/SystemUI/res/values-sw360dp/dimens.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<resources> + + <!-- The width of the view containing navigation buttons --> + <dimen name="navigation_key_width">80dip</dimen> + + <!-- The width of the view containing the menu/ime navigation bar icons --> + <dimen name="navigation_extra_key_width">40dip</dimen> + + <!-- The padding on the side of the navigation bar. Must be greater than or equal to + navigation_extra_key_width --> + <dimen name="navigation_side_padding">40dip</dimen> + +</resources> + diff --git a/packages/SystemUI/res/values-sw400dp/dimens.xml b/packages/SystemUI/res/values-sw400dp/dimens.xml new file mode 100644 index 000000000000..80e82c4fd594 --- /dev/null +++ b/packages/SystemUI/res/values-sw400dp/dimens.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<resources> + + <!-- The width of the view containing navigation buttons --> + <dimen name="navigation_key_width">80dip</dimen> + + <!-- The padding on the side of the navigation bar. Must be greater than or equal to + navigation_extra_key_width --> + <dimen name="navigation_side_padding">50dp</dimen> + +</resources> + diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml index 10410d3dfb75..847529c5b748 100644 --- a/packages/SystemUI/res/values-ta-rIN/strings.xml +++ b/packages/SystemUI/res/values-ta-rIN/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"செயலில் இருக்கும்"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"அறிவிப்புகள்"</string> <string name="battery_low_title" msgid="6456385927409742437">"பேட்டரி குறைவு"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> மீதமுள்ளது"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> உள்ளது. பேட்டரி சேமிப்பான் இயக்கத்தில் உள்ளது."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> உள்ளது"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> உள்ளது. பேட்டரி சேமிப்பான் இயக்கத்தில் உள்ளது."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB மூலம் சார்ஜ் செய்வது ஆதரிக்கப்படவில்லை.\nவழங்கப்பட்ட சார்ஜரை மட்டும் பயன்படுத்தவும்."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB சார்ஜிங் ஆதரிக்கப்படவில்லை."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"வழங்கப்பட்ட சார்ஜரை மட்டும் பயன்படுத்துக."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"பகல்கனா"</string> <string name="ethernet_label" msgid="7967563676324087464">"ஈதர்நெட்"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"விமானப் பயன்முறை"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"சார்ஜ் ஏற்றுகிறது, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"சார்ஜ் செய்யப்பட்டது"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"புளூடூத்"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"புளூடூத் (<xliff:g id="NUMBER">%d</xliff:g> சாதனங்கள்)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"புளூடூத் ஐ முடக்கு"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> எச்சரிக்கை"</string> <string name="recents_empty_message" msgid="8682129509540827999">"சமீபத்திய திரைகள் இங்கு தோன்றும்"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"பயன்பாட்டு தகவல்"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"லாக்-டு-ஆப்"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"திரையை பின் செய்தல்"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"தேடு"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ஐத் தொடங்க முடியவில்லை."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"சார்ஜ் செய்யப்பட்டது"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"பேட்டரி சேமிப்பான் இயக்கத்தில் உள்ளது"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"செயல்திறனையும் பின்புலத் தரவையும் குறைக்கிறது"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"பேட்டரி சேமிப்பானை முடக்கு"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"மறைந்துள்ள உள்ளடக்கம்"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"திரையில் காட்டப்படும் அனைத்தையும் <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> படமெடுக்கும்."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"மீண்டும் காட்டாதே"</string> diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml index 14f440f55aae..393569afb38c 100644 --- a/packages/SystemUI/res/values-te-rIN/strings.xml +++ b/packages/SystemUI/res/values-te-rIN/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"కొనసాగుతున్నవి"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"నోటిఫికేషన్లు"</string> <string name="battery_low_title" msgid="6456385927409742437">"బ్యాటరీ తక్కువగా ఉంది"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> మిగిలి ఉంది"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> మిగిలి ఉంది. బ్యాటరీ సేవర్ ఆన్లో ఉంది."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> మిగిలి ఉంది"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> మిగిలి ఉంది. బ్యాటరీ సేవర్ ఆన్లో ఉంది."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB ఛార్జింగ్కు మద్దతు లేదు.\nఅందించిన ఛార్జర్ను మాత్రమే ఉపయోగించండి."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB ఛార్జింగ్కి మద్దతు లేదు."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"అందించిన ఛార్జర్ను మాత్రమే ఉపయోగించండి."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"డేడ్రీమ్"</string> <string name="ethernet_label" msgid="7967563676324087464">"ఈథర్నెట్"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"ఎయిర్ప్లేన్ మోడ్"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"ఛార్జ్ చేయబడుతోంది, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"ఛార్జ్ చేయబడింది"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"బ్లూటూత్"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"బ్లూటూత్ (<xliff:g id="NUMBER">%d</xliff:g> పరికరాలు)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"బ్లూటూత్ ఆఫ్లో ఉంది"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> హెచ్చరిక"</string> <string name="recents_empty_message" msgid="8682129509540827999">"మీ ఇటీవలి స్క్రీన్లు ఇక్కడ కనిపిస్తాయి"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"అనువర్తన సమాచారం"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"లాక్ టు యాప్"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"స్క్రీన్ పిన్నింగ్"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"శోధించు"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ని ప్రారంభించడం సాధ్యపడలేదు."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ఛార్జ్ చేయబడింది"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"బ్యాటర్ సేవర్ ఆన్ చేయబడింది"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"పనితీరుని మరియు నేపథ్య డేటాను తగ్గిస్తుంది"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"బ్యాటరీ సేవర్ను ఆఫ్ చేయి"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"కంటెంట్లు దాచబడ్డాయి"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> మీ స్క్రీన్పై కనిపించే ప్రతిదాన్ని క్యాప్చర్ చేయడం ప్రారంభిస్తుంది."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"మళ్లీ చూపవద్దు"</string> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 80657c7a2429..673e0e485b73 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ดำเนินอยู่"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"การแจ้งเตือน"</string> <string name="battery_low_title" msgid="6456385927409742437">"แบตเตอรี่เหลือน้อย"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"เหลืออีก <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"แบตเตอรี่เหลือ <xliff:g id="NUMBER">%d%%</xliff:g> เปิดโหมดประหยัดแบตเตอรี่อยู่"</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"เหลืออีก <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"เหลืออีก <xliff:g id="PERCENTAGE">%s</xliff:g> เปิดประหยัดแบตเตอรี่"</string> <string name="invalid_charger" msgid="4549105996740522523">"ไม่สนับสนุนการชาร์จแบบ USB\nใช้เฉพาะที่ชาร์จที่ให้มาเท่านั้น"</string> <string name="invalid_charger_title" msgid="3515740382572798460">"ไม่รองรับการชาร์จผ่าน USB"</string> <string name="invalid_charger_text" msgid="5474997287953892710">"ใช้เฉพาะที่ชาร์จที่ให้มา"</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"เดย์ดรีม"</string> <string name="ethernet_label" msgid="7967563676324087464">"อีเทอร์เน็ต"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"โหมดใช้บนเครื่องบิน"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"กำลังชาร์จ, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"ชาร์จแล้ว"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"บลูทูธ"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"บลูทูธ (<xliff:g id="NUMBER">%d</xliff:g> อุปกรณ์)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ปิดบลูทูธ"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"คำเตือน <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"หน้าจอล่าสุดของคุณแสดงที่นี่"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"ข้อมูลแอปพลิเคชัน"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"การล็อกแอป"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"การตรึงหน้าจอ"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"ค้นหา"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"ไม่สามารถเริ่มใช้ <xliff:g id="APP">%s</xliff:g>"</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ชาร์จแล้ว"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"เปิดโหมดประหยัดแบตเตอรี่อยู่"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"ลดการใช้แบตเตอรี่และข้อมูลแบ็กกราวด์"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"ปิดโหมดประหยัดแบตเตอรี่"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"เนื้อหาถูกซ่อนไว้"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> จะเริ่มจับภาพทุกอย่างที่แสดงบนหน้าจอ"</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"ไม่ต้องแสดงข้อความนี้อีก"</string> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index a1a7a4669818..e7db5f84c6da 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Nagpapatuloy"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Mga Notification"</string> <string name="battery_low_title" msgid="6456385927409742437">"Mahina na ang baterya"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> natitira"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> ang natitira. Naka-on ang tagatipid ng baterya."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> na lang ang natitira"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> na lang ang natitira. Naka-on ang battery saver."</string> <string name="invalid_charger" msgid="4549105996740522523">"Hindi sinusuportahan ang pag-charge sa USB.\nGamitin lang ang ibinigay na charger."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Hindi sinusuportahan ang pagtsa-charge gamit ang USB."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Gamitin lang ang ibinigay na charger."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Airplane mode"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Nagcha-charge, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Na-charge"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> (na) Device)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Naka-off ang Bluetooth"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Babala sa <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Lumalabas dito ang iyong mga kamakailang screen"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Impormasyon ng Application"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lock to app"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pagpi-pin sa screen"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"maghanap"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Hindi masimulan <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nasingil na"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Naka-on ang tagatipid ng baterya"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Binabawasan ang pagganap at data sa background"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"I-off ang pagtitipid ng baterya"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Nakatago ang mga content"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"Sisimulan ng i-capture ng <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ang lahat ng ipinapakita sa iyong screen."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Huwag ipakitang muli"</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index e1b4465cdc4b..e295be22d383 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Sürüyor"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Bildirimler"</string> <string name="battery_low_title" msgid="6456385927409742437">"Pil gücü düşük"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> kaldı"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> kaldı. Pil tasarrufu açık."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> kaldı"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> kaldı. Pil tasarrufu açık."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB üzerinden şarj desteklenmiyor.\nYalnızca ürünle birlikte verilen şarj cihazını kullanın."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB şarjı desteklenmiyor."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Yalnızca ürünle birlikte verilen şarj cihazını kullanın."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Hafif uyku"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Uçak modu"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Şarj oluyor, <xliff:g id="PERCENT">%%</xliff:g><xliff:g id="NUMBER">%d</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Şarj oldu"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Cihaz)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Kapalı"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> uyarısı"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Son ekranlarınız burada görünür"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Uygulama Bilgileri"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"uygulamaya kilitle"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekran sabitleme"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"ara"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> başlatılamadı."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Ödeme alındı"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Pil tasarrufu açık"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Performansı ve arka plan verilerini azaltır"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Pil tasarrufunu kapat"</string> - <string name="battery_level_template" msgid="1609636980292580020">"%%<xliff:g id="LEVEL">%d</xliff:g>"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"İçerik gizlendi"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, ekranınızda görüntülenen her şeyi kaydetmeye başlayacak."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Bir daha gösterme"</string> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index bdcfac3f4299..6798df19ef74 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Поточні"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Сповіщення"</string> <string name="battery_low_title" msgid="6456385927409742437">"Низький рівень заряду акумулятора"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"Залишилося <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Залишилося <xliff:g id="NUMBER">%d%%</xliff:g>. Режим заощадження заряду акумулятора ввімкнено."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Залишилося <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Залишилося <xliff:g id="PERCENTAGE">%s</xliff:g>. Режим заощадження заряду акумулятора ввімкнено."</string> <string name="invalid_charger" msgid="4549105996740522523">"Заряджання USB не підтримується.\nВикористовуйте лише наданий у комплекті зарядний пристрій."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Заряджання через USB не підтримується."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Використовуйте лише зарядний пристрій, який постачається в комплекті."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Заставка"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Режим польоту"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Заряджається, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Заряджено"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (пристроїв: <xliff:g id="NUMBER">%d</xliff:g>)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth вимкнено"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Застереження: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Ваші останні екрани відображаються тут"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Інформація про додаток"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"блокування в додатку"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"закріпити екран"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"пошук"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Не вдалося запустити <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Заряджено"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Режим заощадження заряду акумулятора ввімкнено"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Знижується продуктивність і обмежуються фонові дані"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Вимкнути режим заощадження заряду акумулятора"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Вміст сховано"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> отримає доступ до всіх даних, які відображаються на вашому екрані."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Більше не показувати"</string> diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml index d75796f240c5..6b05ac52feb3 100644 --- a/packages/SystemUI/res/values-ur-rPK/strings.xml +++ b/packages/SystemUI/res/values-ur-rPK/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"جاری"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"اطلاعات"</string> <string name="battery_low_title" msgid="6456385927409742437">"بیٹری کم ہے"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> باقی ہے"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> باقی ہے۔ بیٹری سیور آن ہے۔"</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی ہے"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی ہے۔ بیٹری سیور آن ہے۔"</string> <string name="invalid_charger" msgid="4549105996740522523">"USB چارجنگ تعاون یافتہ نہیں ہے.\nصرف فراہم کردہ چارجر کا ہی استعمال کریں۔"</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB چارجنگ تعاون یافتہ نہیں ہے۔"</string> <string name="invalid_charger_text" msgid="5474997287953892710">"صرف فراہم کردہ چارجر استعمال کریں۔"</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string> <string name="ethernet_label" msgid="7967563676324087464">"ایتھرنیٹ"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"ہوائی جہاز طرز"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"چارج ہو رہی ہے، <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"چارج ہوگئی"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"بلوٹوتھ"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"بلوٹوتھ (<xliff:g id="NUMBER">%d</xliff:g> آلات)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"بلوٹوتھ آف ہے"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> وارننگ"</string> <string name="recents_empty_message" msgid="8682129509540827999">"آپ کی حالیہ اسکرینز یہاں ظاہر ہوتی ہیں"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"ایپلیکیشن کی معلومات"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"لاک ٹو ایپ"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"اسکرین کو پن کرنا"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"تلاش کریں"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> کو شروع نہیں کیا جا سکا۔"</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"چارج ہوگئی"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"بیٹری سیور آن ہے"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"کارکردگی اور پس منظر کا ڈیٹا کم کر دیتا ہے"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"بیٹری کی بچت آف کریں"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"مواد مخفی ہیں"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> آپ کی اسکرین پر ڈسپلے ہونے والی ہر چیز کو کیپچر کرنا شروع کر دیگی۔"</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"دوبارہ نہ دکھائیں"</string> diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml index f8d0519e3363..c561400cd747 100644 --- a/packages/SystemUI/res/values-uz-rUZ/strings.xml +++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Joriy"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Eslatmalar"</string> <string name="battery_low_title" msgid="6456385927409742437">"Batareya quvvati kam"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> qolmoqda"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> qoldi. Quvvat tejash funksiyasi yoqilgan."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> qoldi"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> qoldi. Quvvat tejash funksiyasi yoqilgan."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB orqali zaryadlab bo‘lmaydi.\nFaqat taklif qilingan zaryadlagichdan foydalaning."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB orqali quvvat oldirish qo‘llab-quvvatlanmaydi."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Faqat qurilma bilan kelgan quvvatlash moslamasidan foydalaning."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Tush kurish"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Parvoz rejimi"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Zaryadlanmoqda: <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Zaryad to‘la"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g>ta qurilma)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth o‘chirilgan"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Ogohlantirish: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Siz yaqinda ishlatgan ilova ekranlari bu yerda ko‘rinadi"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Ilova haqida ma’lumot"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"ilovaga qulflash"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekranni qadab qo‘yish"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"qidirish"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"“<xliff:g id="APP">%s</xliff:g>” ilovasini ishga tushirib bo‘lmadi."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Batareya quvvati to‘ldi"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Quvvat tejash yoqilgan"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Unumdorlikni pasaytiradi va fonda int-dan foyd-ni cheklaydi"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Quvvat tejash funksiyasini o‘chiring"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Kontent yashirildi"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ilovasi qurilma ekranidagi har qanday tasvirni ko‘rishni boshlaydi."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Boshqa ko‘rsatilmasin"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index e4c8ee20dfec..0572930991e8 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Đang diễn ra"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Thông báo"</string> <string name="battery_low_title" msgid="6456385927409742437">"Pin yếu"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> còn lại"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"Còn lại <xliff:g id="NUMBER">%d%%</xliff:g>. Trình tiết kiệm pin đang bật."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"Còn lại <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Còn lại <xliff:g id="PERCENTAGE">%s</xliff:g>. Trình tiết kiệm pin đang bật."</string> <string name="invalid_charger" msgid="4549105996740522523">"Không hỗ trợ sạc qua USB.\nChỉ sử dụng bộ sạc được cung cấp."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Sạc qua USB không được hỗ trợ."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Chỉ sử dụng bộ sạc được cung cấp."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Chế độ ngủ"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Chế độ trên máy bay"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Đang sạc, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Đã sạc"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> thiết bị)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Đã tắt Bluetooth"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Cảnh báo <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Màn hình gần đây của bạn sẽ xuất hiện tại đây"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Thông tin ứng dụng"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"khóa trong ứng dụng"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"khóa màn hình"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"tìm kiếm"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Không thể khởi động <xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Đã sạc"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Trình tiết kiệm pin đang bật"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Giảm hiệu suất và dữ liệu nền"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Tắt trình tiết kiệm pin"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Nội dung bị ẩn"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sẽ bắt đầu chụp mọi thứ hiển thị trên màn hình."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Không hiển thị lại"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index cf3f57c7caad..8895799b2c10 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"正在进行的"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string> <string name="battery_low_title" msgid="6456385927409742437">"电池电量偏低"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"还剩<xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"电量还剩<xliff:g id="NUMBER">%d%%</xliff:g>。节电助手已开启。"</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"剩余<xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"剩余<xliff:g id="PERCENTAGE">%s</xliff:g>。节电助手已开启。"</string> <string name="invalid_charger" msgid="4549105996740522523">"不支持USB充电功能。\n只能使用随附的充电器充电。"</string> <string name="invalid_charger_title" msgid="3515740382572798460">"不支持USB充电。"</string> <string name="invalid_charger_text" msgid="5474997287953892710">"仅限使用设备随附的充电器。"</string> @@ -226,8 +226,6 @@ <string name="start_dreams" msgid="7219575858348719790">"互动屏保"</string> <string name="ethernet_label" msgid="7967563676324087464">"有线网络"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"飞行模式"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"正在充电:<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"充电完成"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"蓝牙"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"蓝牙(<xliff:g id="NUMBER">%d</xliff:g> 台设备)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"蓝牙:关闭"</string> @@ -279,7 +277,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g>警告"</string> <string name="recents_empty_message" msgid="8682129509540827999">"您最近浏览过的屏幕会显示在此处"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"应用信息"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"固定屏幕"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"固定屏幕"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"搜索"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"无法启动<xliff:g id="APP">%s</xliff:g>。"</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"充电完成"</string> @@ -326,7 +324,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"节电助手已开启"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"降低性能并限制后台流量"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"关闭节电助手"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"内容已隐藏"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>将开始截取您的屏幕上显示的所有内容。"</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"不再显示"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 5a76eecdc298..fe8fe85cebc8 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"持續進行"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string> <string name="battery_low_title" msgid="6456385927409742437">"電量低"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"剩餘 <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"電量尚餘 <xliff:g id="NUMBER">%d%%</xliff:g>,省電模式已開啟。"</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"剩餘 <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"剩餘 <xliff:g id="PERCENTAGE">%s</xliff:g>。開啟省電模式。"</string> <string name="invalid_charger" msgid="4549105996740522523">"不支援 USB 充電。\n僅能使用隨附的充電器。"</string> <string name="invalid_charger_title" msgid="3515740382572798460">"不支援 USB 充電功能。"</string> <string name="invalid_charger_text" msgid="5474997287953892710">"僅限使用裝置隨附的充電器。"</string> @@ -226,8 +226,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string> <string name="ethernet_label" msgid="7967563676324087464">"以太網"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"飛行模式"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"充電中 (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"充電完成"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"藍牙"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"藍牙 (<xliff:g id="NUMBER">%d</xliff:g> 部裝置)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"藍牙關閉"</string> @@ -279,7 +277,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> 警告"</string> <string name="recents_empty_message" msgid="8682129509540827999">"您最近的螢幕顯示在這裡"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"應用程式資料"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"應用程式鎖定"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"螢幕固定"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"無法啟動「<xliff:g id="APP">%s</xliff:g>」。"</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"已完成充電"</string> @@ -326,7 +324,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"省電模式已開啟"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"降低效能並限制背景數據傳輸"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"關閉省電模式"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"內容已隱藏"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 將開始擷取您的螢幕上顯示的內容。"</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"不用再顯示"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 2f48a15cec49..773ce0f4caa7 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"進行中"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string> <string name="battery_low_title" msgid="6456385927409742437">"電池電力不足"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"還剩 <xliff:g id="NUMBER">%d%%</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"電力剩下 <xliff:g id="NUMBER">%d%%</xliff:g>,節約耗電量模式已啟用。"</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"僅剩 <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"僅剩 <xliff:g id="PERCENTAGE">%s</xliff:g>。節約耗電量模式已開啟。"</string> <string name="invalid_charger" msgid="4549105996740522523">"不支援 USB 充電。\n僅能使用隨附的充電器。"</string> <string name="invalid_charger_title" msgid="3515740382572798460">"不支援 USB 充電功能。"</string> <string name="invalid_charger_text" msgid="5474997287953892710">"僅限使用裝置隨附的充電器。"</string> @@ -226,8 +226,6 @@ <string name="start_dreams" msgid="7219575858348719790">"休眠模式"</string> <string name="ethernet_label" msgid="7967563676324087464">"乙太網路"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"飛航模式"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"充電中 (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"充電完成"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"藍牙"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"藍牙 (<xliff:g id="NUMBER">%d</xliff:g> 個裝置)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"關閉藍牙"</string> @@ -279,7 +277,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> 警告"</string> <string name="recents_empty_message" msgid="8682129509540827999">"您最近的螢幕會顯示在這裡"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"應用程式資訊"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"應用程式鎖定"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"螢幕固定"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"無法啟動「<xliff:g id="APP">%s</xliff:g>」。"</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"已充飽"</string> @@ -326,7 +324,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"節約耗電量模式已啟用"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"降低效能並限制背景數據傳輸"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"關閉節約耗電量模式"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"內容已隱藏"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 將開始擷取您的螢幕上顯示的內容。"</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"不要再顯示"</string> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index ad25dabe7096..282acaa6abb2 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -33,8 +33,8 @@ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Okuqhubekayo"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Izaziso"</string> <string name="battery_low_title" msgid="6456385927409742437">"Ibhethri liphansi"</string> - <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> okusele"</string> - <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"<xliff:g id="NUMBER">%d%%</xliff:g> esele. Isilondolozi Sebhethri sivuliwe."</string> + <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> okusele"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> okusele. Isilondolozi sebhethri sivulekile."</string> <string name="invalid_charger" msgid="4549105996740522523">"Ukushaja i-USB akusekelwe.\nSebenzisa kuphela ishaja enikeziwe."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"Ukushaja kwe-USB akusekelwe."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Sebenzisa kuphela ishaja enikeziwe."</string> @@ -224,8 +224,6 @@ <string name="start_dreams" msgid="7219575858348719790">"Ukuphupha emini"</string> <string name="ethernet_label" msgid="7967563676324087464">"I-Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Isimo sendiza"</string> - <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Iyashaja <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Kushajiwe"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"I-Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"I-Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> amadivayisi)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"I-Bluetooth ivaliwe"</string> @@ -277,7 +275,7 @@ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> isexwayiso"</string> <string name="recents_empty_message" msgid="8682129509540827999">"Izikrini zakho zakamuva zivela lapha"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Ulwazi lohlelo lokusebenza"</string> - <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"ukukhiya kuhlelo lokusebenza"</string> + <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ukuphina isikrini"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"sesha"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Ayikwazanga ukuqala i-<xliff:g id="APP">%s</xliff:g>."</string> <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Kushajiwe"</string> @@ -324,7 +322,6 @@ <string name="battery_saver_notification_title" msgid="237918726750955859">"Isilondolozi sebhethri sivuliwe"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"Sehlisa ukusebenza nedatha yasemuva"</string> <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Vala isilondolozi sebhethri"</string> - <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string> <string name="notification_hidden_text" msgid="1135169301897151909">"Okuqukethwe kufihliwe"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> izoqala ukuthwebula yonke into eboniswa kusikrini sakho."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"Ungabonisi futhi"</string> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index cd82c45b8d30..4da54e30b906 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -224,13 +224,16 @@ <integer name="doze_pickup_vibration_threshold">2000</integer> <!-- Doze: pulse parameter - how long does it take to fade in? --> - <integer name="doze_pulse_duration_in">1000</integer> + <integer name="doze_pulse_duration_in">900</integer> + + <!-- Doze: pulse parameter - delay for fading so the screen can wake up before --> + <integer name="doze_pulse_delay_in">200</integer> <!-- Doze: pulse parameter - once faded in, how long does it stay visible? --> <integer name="doze_pulse_duration_visible">3000</integer> <!-- Doze: pulse parameter - how long does it take to fade out? --> - <integer name="doze_pulse_duration_out">1000</integer> + <integer name="doze_pulse_duration_out">600</integer> <!-- Doze: alpha to apply to small icons when dozing --> <integer name="doze_small_icon_alpha">222</integer><!-- 87% of 0xff --> @@ -238,8 +241,11 @@ <!-- Volume: time to delay dismissing the volume panel after a click is performed --> <integer name="volume_panel_dismiss_delay">200</integer> - <!-- Tiles with feature timeouts: number of days to show after feature is used. --> - <integer name="days_to_show_timeout_tiles">30</integer> + <!-- Hotspot tile: number of days to show after feature is used. --> + <integer name="days_to_show_hotspot_tile">30</integer> + + <!-- Color inversion tile: number of days to show after feature is used. --> + <integer name="days_to_show_color_inversion_tile">7</integer> <!-- Number of times to show the strong alarm warning text in the volume dialog --> <integer name="zen_mode_alarm_warning_threshold">5</integer> @@ -249,5 +255,8 @@ <!-- Zen toast visibility duration --> <integer name="zen_toast_visible_duration">500</integer> + + <!-- Enable the default volume dialog --> + <bool name="enable_volume_ui">true</bool> </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 4f41cd560ae4..6e6f3025545f 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -103,11 +103,15 @@ <!-- The padding on the global screenshot background image --> <dimen name="global_screenshot_bg_padding">20dp</dimen> - <!-- The width of the view containing non-menu status bar icons --> - <dimen name="navigation_key_width">80dip</dimen> + <!-- The width of the view containing navigation buttons --> + <dimen name="navigation_key_width">70dp</dimen> <!-- The width of the view containing the menu/ime navigation bar icons --> - <dimen name="navigation_extra_key_width">40dip</dimen> + <dimen name="navigation_extra_key_width">36dp</dimen> + + <!-- The padding on the side of the navigation bar. Must be greater than or equal to + navigation_extra_key_width --> + <dimen name="navigation_side_padding">36dp</dimen> <!-- Default distance beyond which snaps to the matching target --> <dimen name="navbar_search_snap_margin">40dip</dimen> @@ -239,7 +243,7 @@ <dimen name="recents_search_bar_space_height">64dp</dimen> <!-- The side padding for the task stack as a percentage of the width. --> - <item name="recents_stack_width_padding_percentage" format="float" type="dimen">0.04444</item> + <item name="recents_stack_width_padding_percentage" format="float" type="dimen">0.03333</item> <!-- The overscroll percentage allowed on the stack. --> <item name="recents_stack_overscroll_percentage" format="float" type="dimen">0.0875</item> @@ -358,6 +362,9 @@ <!-- radius of the corners of the material rounded rect background --> <dimen name="notification_material_rounded_rect_radius">2dp</dimen> + <!-- radius of the corners of the material rounded rect background but negative--> + <dimen name="notification_material_rounded_rect_radius_negative">-2dp</dimen> + <!-- end margin for multi user switch in expanded quick settings --> <dimen name="multi_user_switch_expanded_margin">8dp</dimen> @@ -505,4 +512,10 @@ <dimen name="fake_shadow_inset">1dp</dimen> <dimen name="fake_shadow_size">8dp</dimen> + + <!-- Padding between signal cluster and battery icon --> + <dimen name="signal_cluster_battery_padding">7dp</dimen> + + <!-- Padding for signal cluster and battery icon when there are not icons in signal cluster --> + <dimen name="no_signal_cluster_battery_padding">3dp</dimen> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 71b9b61566f1..7a0d655514e4 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -62,12 +62,12 @@ <string name="battery_low_title">Battery is low</string> <!-- A message that appears when the battery level is getting low in a dialog. This is - appened to the subtitle of the low battery alert. "number" is the percentage of battery + appened to the subtitle of the low battery alert. "percentage" is the percentage of battery remaining [CHAR LIMIT=none]--> - <string name="battery_low_percent_format"><xliff:g id="number">%d%%</xliff:g> remaining</string> + <string name="battery_low_percent_format"><xliff:g id="percentage">%s</xliff:g> remaining</string> <!-- Same as battery_low_percent_format, with a notice about battery saver if on. [CHAR LIMIT=none]--> - <string name="battery_low_percent_format_saver_started"><xliff:g id="number">%d%%</xliff:g> remaining. Battery saver is on.</string> + <string name="battery_low_percent_format_saver_started"><xliff:g id="percentage">%s</xliff:g> remaining. Battery saver is on.</string> <!-- A message that appears when a USB charger is plugged in and the device does not support charging on it. That is, a charger that fits into the USB port and goes into @@ -115,11 +115,6 @@ <!-- Label in system panel saying the device will show notifications [CHAR LIMIT=30] --> <string name="status_bar_settings_notifications">Notifications</string> - <!-- Text to display next to the graphical battery meter. [CHAR LIMIT=3] --> - <string name="status_bar_settings_battery_meter_format" translatable="false"> - <xliff:g id="number">%d</xliff:g><xliff:g id="percent">%%</xliff:g> - </string> - <!-- Separator for PLMN and SPN in network name. --> <string name="status_bar_network_name_separator" translatable="false">|</string> @@ -559,10 +554,6 @@ <!-- QuickSettings: Airplane mode [CHAR LIMIT=NONE] --> <string name="quick_settings_airplane_mode_label">Airplane mode</string> - <!-- QuickSettings: Battery Charging [CHAR LIMIT=NONE] --> - <string name="quick_settings_battery_charging_label">Charging, <xliff:g id="number">%d</xliff:g><xliff:g id="percent">%%</xliff:g></string> - <!-- QuickSettings: Battery Charged [CHAR LIMIT=NONE] --> - <string name="quick_settings_battery_charged_label">Charged</string> <!-- QuickSettings: Bluetooth [CHAR LIMIT=NONE] --> <string name="quick_settings_bluetooth_label">Bluetooth</string> <!-- QuickSettings: Bluetooth (Multiple) [CHAR LIMIT=NONE] --> @@ -666,8 +657,8 @@ <string name="recents_empty_message">Your recent screens appear here</string> <!-- Recents: The info panel app info button string. [CHAR LIMIT=NONE] --> <string name="recents_app_info_button_label">Application Info</string> - <!-- Recents: The lock-to-app button. [CHAR LIMIT=NONE] --> - <string name="recents_lock_to_app_button_label">lock to app</string> + <!-- Recents: The screen pinning button. [CHAR LIMIT=NONE] --> + <string name="recents_lock_to_app_button_label">screen pinning</string> <!-- Recents: Temporary string for the button in the recents search bar. [CHAR LIMIT=NONE] --> <string name="recents_search_bar_label">search</string> <!-- Recents: Launch error string. [CHAR LIMIT=NONE] --> @@ -813,9 +804,6 @@ <!-- Battery saver notification action text. [CHAR LIMIT=60] --> <string name="battery_saver_notification_action_text">Turn off battery saver</string> - <!-- Battery level for expanded quick settings [CHAR LIMIT=2] --> - <string name="battery_level_template"><xliff:g id="level" example="45">%d</xliff:g>%%</string> - <!-- Text shown in place of notification contents when the notification is hidden on a secure lockscreen --> <string name="notification_hidden_text">Contents hidden</string> diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java index 0f8fe1cdc9cb..d42ac612be9f 100644 --- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java +++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java @@ -351,6 +351,9 @@ public class ExpandHelper implements Gefingerpoken { mVelocityTracker.addMovement(event); break; case MotionEvent.ACTION_MOVE: + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } mVelocityTracker.addMovement(event); break; default: diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java index 0d393bf706fa..f206e5633819 100644 --- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -311,11 +311,14 @@ public class SwipeHelper implements Gefingerpoken { final View animView = mCallback.getChildContentView(view); final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view); float newPos; + boolean isLayoutRtl = view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; if (velocity < 0 || (velocity == 0 && getTranslation(animView) < 0) // if we use the Menu to dismiss an item in landscape, animate up - || (velocity == 0 && getTranslation(animView) == 0 && mSwipeDirection == Y)) { + || (velocity == 0 && getTranslation(animView) == 0 && mSwipeDirection == Y) + // if the language is rtl we prefer swiping to the left + || (velocity == 0 && getTranslation(animView) == 0 && isLayoutRtl)) { newPos = -getSize(animView); } else { newPos = getSize(animView); diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java index f184ad2653cb..4391bfc88246 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java @@ -43,6 +43,7 @@ import com.android.systemui.statusbar.phone.PhoneStatusBar; import com.android.systemui.statusbar.phone.SystemUIDialog; import java.io.PrintWriter; +import java.text.NumberFormat; public class PowerNotificationWarnings implements PowerUI.WarningsUI { private static final String TAG = PowerUI.TAG + ".Notification"; @@ -65,6 +66,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { private static final String ACTION_SHOW_BATTERY_SETTINGS = "PNW.batterySettings"; private static final String ACTION_START_SAVER = "PNW.startSaver"; private static final String ACTION_STOP_SAVER = "PNW.stopSaver"; + private static final String ACTION_DISMISSED_WARNING = "PNW.dismissedWarning"; private static final AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) @@ -143,7 +145,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { showSaverNotification(); mShowing = SHOWING_SAVER; } else { - mNoMan.cancel(TAG_NOTIFICATION, ID_NOTIFICATION); + mNoMan.cancelAsUser(TAG_NOTIFICATION, ID_NOTIFICATION, UserHandle.ALL); mShowing = SHOWING_NOTHING; } } @@ -157,7 +159,6 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { .setContentTitle(mContext.getString(R.string.invalid_charger_title)) .setContentText(mContext.getString(R.string.invalid_charger_text)) .setPriority(Notification.PRIORITY_MAX) - .setCategory(Notification.CATEGORY_SYSTEM) .setVisibility(Notification.VISIBILITY_PUBLIC) .setColor(mContext.getResources().getColor( com.android.internal.R.color.system_notification_accent_color)); @@ -165,22 +166,23 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { if (n.headsUpContentView != null) { n.headsUpContentView.setViewVisibility(com.android.internal.R.id.right_icon, View.GONE); } - mNoMan.notifyAsUser(TAG_NOTIFICATION, ID_NOTIFICATION, n, UserHandle.CURRENT); + mNoMan.notifyAsUser(TAG_NOTIFICATION, ID_NOTIFICATION, n, UserHandle.ALL); } private void showWarningNotification() { final int textRes = mSaver ? R.string.battery_low_percent_format_saver_started : R.string.battery_low_percent_format; + final String percentage = NumberFormat.getPercentInstance().format((double) mBatteryLevel / 100.0); final Notification.Builder nb = new Notification.Builder(mContext) .setSmallIcon(R.drawable.ic_power_low) // Bump the notification when the bucket dropped. .setWhen(mBucketDroppedNegativeTimeMs) .setShowWhen(false) .setContentTitle(mContext.getString(R.string.battery_low_title)) - .setContentText(mContext.getString(textRes, mBatteryLevel)) + .setContentText(mContext.getString(textRes, percentage)) .setOnlyAlertOnce(true) + .setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_WARNING)) .setPriority(Notification.PRIORITY_MAX) - .setCategory(Notification.CATEGORY_SYSTEM) .setVisibility(Notification.VISIBILITY_PUBLIC) .setColor(mContext.getResources().getColor( com.android.internal.R.color.battery_saver_mode_color)); @@ -202,7 +204,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { if (n.headsUpContentView != null) { n.headsUpContentView.setViewVisibility(com.android.internal.R.id.right_icon, View.GONE); } - mNoMan.notifyAsUser(TAG_NOTIFICATION, ID_NOTIFICATION, n, UserHandle.CURRENT); + mNoMan.notifyAsUser(TAG_NOTIFICATION, ID_NOTIFICATION, n, UserHandle.ALL); } private void showSaverNotification() { @@ -212,7 +214,6 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { .setContentText(mContext.getString(R.string.battery_saver_notification_text)) .setOngoing(true) .setShowWhen(false) - .setCategory(Notification.CATEGORY_SYSTEM) .setVisibility(Notification.VISIBILITY_PUBLIC) .setColor(mContext.getResources().getColor( com.android.internal.R.color.battery_saver_mode_color)); @@ -220,7 +221,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { if (hasSaverSettings()) { nb.setContentIntent(pendingActivity(mOpenSaverSettings)); } - mNoMan.notifyAsUser(TAG_NOTIFICATION, ID_NOTIFICATION, nb.build(), UserHandle.CURRENT); + mNoMan.notifyAsUser(TAG_NOTIFICATION, ID_NOTIFICATION, nb.build(), UserHandle.ALL); } private void addStopSaverAction(Notification.Builder nb) { @@ -341,6 +342,11 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { updateNotification(); } + @Override + public void userSwitched() { + updateNotification(); + } + private void showStartSaverConfirmation() { if (mSaverConfirmation != null) return; final SystemUIDialog d = new SystemUIDialog(mContext); @@ -370,7 +376,8 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { filter.addAction(ACTION_SHOW_BATTERY_SETTINGS); filter.addAction(ACTION_START_SAVER); filter.addAction(ACTION_STOP_SAVER); - mContext.registerReceiver(this, filter, null, mHandler); + filter.addAction(ACTION_DISMISSED_WARNING); + mContext.registerReceiverAsUser(this, UserHandle.ALL, filter, null, mHandler); } @Override @@ -387,6 +394,8 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { dismissSaverNotification(); dismissLowBatteryNotification(); setSaverMode(false); + } else if (action.equals(ACTION_DISMISSED_WARNING)) { + dismissLowBatteryWarning(); } } } diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java index d3c7dee9e5bb..945974042edf 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java @@ -137,6 +137,7 @@ public class PowerUI extends SystemUI { filter.addAction(Intent.ACTION_BATTERY_CHANGED); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); + filter.addAction(Intent.ACTION_USER_SWITCHED); filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING); filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED); mContext.registerReceiver(this, filter, null, mHandler); @@ -207,6 +208,8 @@ public class PowerUI extends SystemUI { mScreenOffTime = SystemClock.elapsedRealtime(); } else if (Intent.ACTION_SCREEN_ON.equals(action)) { mScreenOffTime = -1; + } else if (Intent.ACTION_USER_SWITCHED.equals(action)) { + mWarnings.userSwitched(); } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)) { updateSaverMode(); } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGING.equals(action)) { @@ -256,6 +259,7 @@ public class PowerUI extends SystemUI { void updateLowBatteryWarning(); boolean isInvalidChargerWarningShowing(); void dump(PrintWriter pw); + void userSwitched(); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java index eb4560da1a89..111484b191d4 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java @@ -55,7 +55,6 @@ public class QSDetailClipper { if (listener != null) { mAnimator.addListener(listener); } - mDetail.setLayerType(View.LAYER_TYPE_HARDWARE, null); if (in) { mBackground.startTransition((int)(mAnimator.getDuration() * 0.6)); mAnimator.addListener(mVisibleOnStart); @@ -82,7 +81,6 @@ public class QSDetailClipper { } public void onAnimationEnd(Animator animation) { - mDetail.setLayerType(View.LAYER_TYPE_NONE, null); mAnimator = null; } }; @@ -90,7 +88,6 @@ public class QSDetailClipper { private final AnimatorListenerAdapter mGoneOnEnd = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - mDetail.setLayerType(View.LAYER_TYPE_NONE, null); mDetail.setVisibility(View.GONE); mBackground.resetTransition(); mAnimator = null; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index fdebdd3b8828..54a84141b341 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -542,7 +542,10 @@ public class QSPanel extends ViewGroup { @Override public void onAnimationEnd(Animator animation) { - setGridContentVisibility(false); + // Only hide content if still in detail state. + if (mDetailRecord != null) { + setGridContentVisibility(false); + } } }; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java index 3574877782a1..d5c90d0668bb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java @@ -132,6 +132,7 @@ public class QSTileView extends ViewGroup { mDualLabel = new QSDualTileLabel(mContext); mDualLabel.setId(android.R.id.title); mDualLabel.setBackgroundResource(R.drawable.btn_borderless_rect); + mDualLabel.setFirstLineCaret(res.getDrawable(R.drawable.qs_dual_tile_caret)); mDualLabel.setTextColor(res.getColor(R.color.qs_tile_text)); mDualLabel.setPadding(0, mDualTileVerticalPaddingPx, 0, mDualTileVerticalPaddingPx); mDualLabel.setTypeface(CONDENSED); diff --git a/packages/SystemUI/src/com/android/systemui/qs/UsageTracker.java b/packages/SystemUI/src/com/android/systemui/qs/UsageTracker.java index ad79aba44bf0..a1092a363413 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/UsageTracker.java +++ b/packages/SystemUI/src/com/android/systemui/qs/UsageTracker.java @@ -22,7 +22,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; -import com.android.systemui.R; import com.android.systemui.statusbar.policy.Listenable; public class UsageTracker implements Listenable { @@ -35,11 +34,10 @@ public class UsageTracker implements Listenable { private boolean mRegistered; - public UsageTracker(Context context, Class<?> tile) { + public UsageTracker(Context context, Class<?> tile, int timeoutResource) { mContext = context; mPrefKey = tile.getSimpleName() + "LastUsed"; - mTimeToShowTile = MILLIS_PER_DAY * mContext.getResources() - .getInteger(R.integer.days_to_show_timeout_tiles); + mTimeToShowTile = MILLIS_PER_DAY * mContext.getResources().getInteger(timeoutResource); mResetAction = "com.android.systemui.qs." + tile.getSimpleName() + ".usage_reset"; } 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 e99b4c5b072a..84bfb8fddca1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java @@ -77,7 +77,7 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> { @Override protected void handleSecondaryClick() { - mHost.startSettingsActivity(BLUETOOTH_SETTINGS); + showDetail(true); } @Override 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 01849c106e31..7ba1dc03b295 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java @@ -44,7 +44,8 @@ public class ColorInversionTile extends QSTile<QSTile.BooleanState> { } } }; - mUsageTracker = new UsageTracker(host.getContext(), ColorInversionTile.class); + mUsageTracker = new UsageTracker(host.getContext(), ColorInversionTile.class, + R.integer.days_to_show_color_inversion_tile); if (mSetting.getValue() != 0 && !mUsageTracker.isRecentlyUsed()) { mUsageTracker.trackUsage(); } 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 ce99cc33221a..b30a1d3c4d91 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java @@ -34,7 +34,7 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> { public HotspotTile(Host host) { super(host); mController = host.getHotspotController(); - mUsageTracker = new UsageTracker(host.getContext(), HotspotTile.class); + mUsageTracker = newUsageTracker(host.getContext()); mUsageTracker.setListening(true); } @@ -84,6 +84,10 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> { } } + private static UsageTracker newUsageTracker(Context context) { + return new UsageTracker(context, HotspotTile.class, R.integer.days_to_show_hotspot_tile); + } + private final class Callback implements HotspotController.Callback { @Override public void onHotspotChanged(boolean enabled) { @@ -101,7 +105,7 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> { @Override public void onReceive(Context context, Intent intent) { if (mUsageTracker == null) { - mUsageTracker = new UsageTracker(context, HotspotTile.class); + mUsageTracker = newUsageTracker(context); } mUsageTracker.trackUsage(); } 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 09858128ffcf..20c4ee8c406f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java @@ -87,7 +87,15 @@ public class WifiTile extends QSTile<QSTile.SignalState> { @Override protected void handleSecondaryClick() { - mHost.startSettingsActivity(WIFI_SETTINGS); + if (!mController.canConfigWifi()) { + mHost.startSettingsActivity(new Intent(Settings.ACTION_WIFI_SETTINGS)); + return; + } + if (!mState.enabled) { + mController.setWifiEnabled(true); + mState.enabled = true; + } + showDetail(true); } @Override @@ -279,7 +287,9 @@ public class WifiTile extends QSTile<QSTile.SignalState> { if (item == null || item.tag == null) return; final AccessPoint ap = (AccessPoint) item.tag; if (!ap.isConnected) { - mController.connect(ap); + if (mController.connect(ap)) { + mHost.collapsePanels(); + } } showDetail(false); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java index 1283dcd92827..76e818140740 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java +++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java @@ -54,17 +54,15 @@ import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; /** A proxy implementation for the recents component */ -public class AlternateRecentsComponent implements ActivityOptions.OnAnimationStartedListener { +public class AlternateRecentsComponent { final public static String EXTRA_FROM_HOME = "recents.triggeredOverHome"; final public static String EXTRA_FROM_SEARCH_HOME = "recents.triggeredOverSearchHome"; final public static String EXTRA_FROM_APP_THUMBNAIL = "recents.animatingWithThumbnail"; - final public static String EXTRA_FROM_APP_FULL_SCREENSHOT = "recents.thumbnail"; final public static String EXTRA_FROM_TASK_ID = "recents.activeTaskId"; final public static String EXTRA_TRIGGERED_FROM_ALT_TAB = "recents.triggeredFromAltTab"; final public static String EXTRA_TRIGGERED_FROM_HOME_KEY = "recents.triggeredFromHomeKey"; - final public static String ACTION_START_ENTER_ANIMATION = "action_start_enter_animation"; final public static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity"; final public static String ACTION_HIDE_RECENTS_ACTIVITY = "action_hide_recents_activity"; @@ -74,15 +72,12 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta final static String sRecentsPackage = "com.android.systemui"; final static String sRecentsActivity = "com.android.systemui.recents.RecentsActivity"; - static Bitmap sLastScreenshot; static RecentsComponent.Callbacks sRecentsComponentCallbacks; Context mContext; LayoutInflater mInflater; SystemServicesProxy mSystemServicesProxy; - Handler mHandler; boolean mBootCompleted; - boolean mStartAnimationTriggered; // Task launching RecentsConfiguration mConfig; @@ -108,7 +103,6 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta mInflater = LayoutInflater.from(context); mContext = context; mSystemServicesProxy = new SystemServicesProxy(context); - mHandler = new Handler(); mTaskStackBounds = new Rect(); } @@ -132,6 +126,9 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta } } } + + // When we start, preload the metadata associated with the previous tasks + RecentsTaskLoader.getInstance().preload(mContext); } public void onBootCompleted() { @@ -256,7 +253,6 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta public void onConfigurationChanged(Configuration newConfig) { // Reload the header bar layout reloadHeaderBarLayout(); - sLastScreenshot = null; } /** Prepares the header bar layout. */ @@ -330,7 +326,8 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta // If the user has toggled it too quickly, then just eat up the event here (it's better than // showing a janky screenshot). // NOTE: Ideally, the screenshot mechanism would take the window transform into account - if (System.currentTimeMillis() - mLastToggleTime < sMinToggleDelay) { + long currentTime = System.currentTimeMillis(); + if ((currentTime > mLastToggleTime) && (currentTime - mLastToggleTime) < sMinToggleDelay) { return; } @@ -367,47 +364,30 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta * Creates the activity options for a unknown state->recents transition. */ ActivityOptions getUnknownTransitionActivityOptions() { - mStartAnimationTriggered = false; return ActivityOptions.makeCustomAnimation(mContext, R.anim.recents_from_unknown_enter, - R.anim.recents_from_unknown_exit, mHandler, this); + R.anim.recents_from_unknown_exit); } /** * Creates the activity options for a home->recents transition. */ ActivityOptions getHomeTransitionActivityOptions(boolean fromSearchHome) { - mStartAnimationTriggered = false; if (fromSearchHome) { return ActivityOptions.makeCustomAnimation(mContext, R.anim.recents_from_search_launcher_enter, - R.anim.recents_from_search_launcher_exit, mHandler, this); + R.anim.recents_from_search_launcher_exit); } return ActivityOptions.makeCustomAnimation(mContext, R.anim.recents_from_launcher_enter, - R.anim.recents_from_launcher_exit, mHandler, this); + R.anim.recents_from_launcher_exit); } /** - * Creates the activity options for an app->recents transition. If this method sets the static - * screenshot, then we will use that for the transition. + * Creates the activity options for an app->recents transition. */ ActivityOptions getThumbnailTransitionActivityOptions(ActivityManager.RunningTaskInfo topTask, boolean isTopTaskHome) { - if (Constants.DebugFlags.App.EnableScreenshotAppTransition) { - // Recycle the last screenshot - consumeLastScreenshot(); - - // Take the full screenshot - sLastScreenshot = mSystemServicesProxy.takeAppScreenshot(); - if (sLastScreenshot != null) { - mStartAnimationTriggered = false; - return ActivityOptions.makeCustomAnimation(mContext, - R.anim.recents_from_app_enter, - R.anim.recents_from_app_exit, mHandler, this); - } - } - // Update the destination rect Task toTask = new Task(); TaskViewTransform toTransform = getThumbnailTransitionTransform(topTask.id, isTopTaskHome, @@ -428,10 +408,9 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta c.setBitmap(null); } - mStartAnimationTriggered = false; return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mStatusBarView, thumbnail, toTaskRect.left, toTaskRect.top, toTaskRect.width(), - toTaskRect.height(), this); + toTaskRect.height(), null); } // If both the screenshot and thumbnail fails, then just fall back to the default transition @@ -493,11 +472,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta // Try starting with a thumbnail transition ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, isTopTaskHome); if (opts != null) { - if (sLastScreenshot != null) { - startAlternateRecentsActivity(topTask, opts, EXTRA_FROM_APP_FULL_SCREENSHOT); - } else { - startAlternateRecentsActivity(topTask, opts, EXTRA_FROM_APP_THUMBNAIL); - } + startAlternateRecentsActivity(topTask, opts, EXTRA_FROM_APP_THUMBNAIL); } else { // Fall through below to the non-thumbnail transition useThumbnailTransition = false; @@ -535,7 +510,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta } else { // Otherwise we do the normal fade from an unknown source ActivityOptions opts = getUnknownTransitionActivityOptions(); - startAlternateRecentsActivity(topTask, opts, null); + startAlternateRecentsActivity(topTask, opts, EXTRA_FROM_HOME); } } mLastToggleTime = System.currentTimeMillis(); @@ -561,19 +536,6 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta } } - /** Returns the last screenshot taken, this will be called by the RecentsActivity. */ - public static Bitmap getLastScreenshot() { - return sLastScreenshot; - } - - /** Recycles the last screenshot taken, this will be called by the RecentsActivity. */ - public static void consumeLastScreenshot() { - if (sLastScreenshot != null) { - sLastScreenshot.recycle(); - sLastScreenshot = null; - } - } - /** Sets the RecentsComponent callbacks. */ public void setRecentsComponentCallback(RecentsComponent.Callbacks cb) { sRecentsComponentCallbacks = cb; @@ -585,42 +547,4 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta sRecentsComponentCallbacks.onVisibilityChanged(visible); } } - - /**** OnAnimationStartedListener Implementation ****/ - - @Override - public void onAnimationStarted() { - // Notify recents to start the enter animation - if (!mStartAnimationTriggered) { - // There can be a race condition between the start animation callback and - // the start of the new activity (where we register the receiver that listens - // to this broadcast, so we add our own receiver and if that gets called, then - // we know the activity has not yet started and we can retry sending the broadcast. - BroadcastReceiver fallbackReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (getResultCode() == Activity.RESULT_OK) { - mStartAnimationTriggered = true; - return; - } - - // Schedule for the broadcast to be sent again after some time - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - onAnimationStarted(); - } - }, 75); - } - }; - - // Send the broadcast to notify Recents that the animation has started - Intent intent = new Intent(ACTION_START_ENTER_ANIMATION); - intent.setPackage(mContext.getPackageName()); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | - Intent.FLAG_RECEIVER_FOREGROUND); - mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null, - fallbackReceiver, null, Activity.RESULT_CANCELED, null, null); - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java index 85cf07798f2b..9b84d2e8aa5e 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java +++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java @@ -25,8 +25,6 @@ public class Constants { public static final boolean Verbose = false; public static class App { - // Enables the screenshot app->Recents transition - public static final boolean EnableScreenshotAppTransition = false; // Enables debug drawing for the transition thumbnail public static final boolean EnableTransitionThumbnailDebugMode = false; // Enables the filtering of tasks according to their grouping diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 01ba5a28072d..d2c55f71ca46 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -28,6 +28,8 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; import android.os.UserHandle; import android.util.Pair; import android.view.KeyEvent; @@ -102,8 +104,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView @Override public void run() { // Mark Recents as no longer visible - AlternateRecentsComponent.notifyVisibilityChanged(false); - mVisible = false; + onRecentsActivityVisibilityChanged(false); // Finish Recents if (mLaunchIntent != null) { if (mLaunchOpts != null) { @@ -141,14 +142,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView } else if (action.equals(AlternateRecentsComponent.ACTION_TOGGLE_RECENTS_ACTIVITY)) { // If we are toggling Recents, then first unfilter any filtered stacks first dismissRecentsToFocusedTaskOrHome(true); - } else if (action.equals(AlternateRecentsComponent.ACTION_START_ENTER_ANIMATION)) { - // Try and start the enter animation (or restart it on configuration changed) - ReferenceCountedTrigger t = new ReferenceCountedTrigger(context, null, null, null); - mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t)); - onEnterAnimationTriggered(); - // Notify the fallback receiver that we have successfully got the broadcast - // See AlternateRecentsComponent.onAnimationStarted() - setResultCode(Activity.RESULT_OK); } } }; @@ -163,6 +156,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView if (action.equals(Intent.ACTION_SCREEN_OFF)) { // When the screen turns off, dismiss Recents to Home dismissRecentsToHome(false); + // Start preloading some tasks in the background + RecentsTaskLoader.getInstance().preload(RecentsActivity.this); } else if (action.equals(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED)) { // When the search activity changes, update the Search widget refreshSearchWidget(); @@ -189,8 +184,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView AlternateRecentsComponent.EXTRA_FROM_HOME, false); mConfig.launchedFromAppWithThumbnail = launchIntent.getBooleanExtra( AlternateRecentsComponent.EXTRA_FROM_APP_THUMBNAIL, false); - mConfig.launchedFromAppWithScreenshot = launchIntent.getBooleanExtra( - AlternateRecentsComponent.EXTRA_FROM_APP_FULL_SCREENSHOT, false); mConfig.launchedToTaskId = launchIntent.getIntExtra( AlternateRecentsComponent.EXTRA_FROM_TASK_ID, -1); mConfig.launchedWithAltTab = launchIntent.getBooleanExtra( @@ -435,6 +428,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView } } + /** Called when the configuration changes. */ void onConfigurationChange() { // Update RecentsConfiguration mConfig = RecentsConfiguration.reinitialize(this, @@ -443,7 +437,16 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView // Try and start the enter animation (or restart it on configuration changed) ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null); mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t)); - onEnterAnimationTriggered(); + // Animate the SystemUI scrim views + mScrimViews.startEnterRecentsAnimation(); + } + + /** Handles changes to the activity visibility. */ + void onRecentsActivityVisibilityChanged(boolean visible) { + if (!visible) { + AlternateRecentsComponent.notifyVisibilityChanged(visible); + } + mVisible = visible; } @Override @@ -471,7 +474,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView IntentFilter filter = new IntentFilter(); filter.addAction(AlternateRecentsComponent.ACTION_HIDE_RECENTS_ACTIVITY); filter.addAction(AlternateRecentsComponent.ACTION_TOGGLE_RECENTS_ACTIVITY); - filter.addAction(AlternateRecentsComponent.ACTION_START_ENTER_ANIMATION); registerReceiver(mServiceBroadcastReceiver, filter); // Register any broadcast receivers for the task loader @@ -483,7 +485,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView super.onResume(); // Mark Recents as visible - mVisible = true; + onRecentsActivityVisibilityChanged(true); } @Override @@ -514,6 +516,16 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView } @Override + public void onEnterAnimationComplete() { + // Try and start the enter animation (or restart it on configuration changed) + ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null); + mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t)); + + // Animate the SystemUI scrim views + mScrimViews.startEnterRecentsAnimation(); + } + + @Override public void onTrimMemory(int level) { RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); if (loader != null) { @@ -594,12 +606,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView } } - /** Called when the enter recents animation is triggered. */ - public void onEnterAnimationTriggered() { - // Animate the SystemUI scrim views - mScrimViews.startEnterRecentsAnimation(); - } - /**** RecentsView.RecentsViewCallbacks Implementation ****/ @Override @@ -611,8 +617,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView @Override public void onTaskViewClicked() { // Mark recents as no longer visible - AlternateRecentsComponent.notifyVisibilityChanged(false); - mVisible = false; + onRecentsActivityVisibilityChanged(false); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java index 2aca576b805b..bfea3f754f7d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java @@ -307,7 +307,6 @@ public class RecentsConfiguration { launchedWithAltTab = false; launchedWithNoRecentTasks = false; launchedFromAppWithThumbnail = false; - launchedFromAppWithScreenshot = false; launchedFromHome = false; launchedToTaskId = -1; } diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java index f01d17c611c9..a0dee07e374a 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java @@ -16,6 +16,7 @@ package com.android.systemui.recents.misc; +import android.animation.Animator; import android.content.Intent; import android.graphics.Color; import android.graphics.Matrix; @@ -188,4 +189,15 @@ public class Utilities { int flags = intent.getFlags(); return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) == Intent.FLAG_ACTIVITY_NEW_DOCUMENT; } + + /** + * Cancels an animation ensuring that if it has listeners, onCancel and onEnd + * are not called. + */ + public static void cancelAnimationWithoutCallbacks(Animator animator) { + if (animator != null) { + animator.removeAllListeners(); + animator.cancel(); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java index 7ccefc6ed5f7..97e091613530 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java @@ -21,15 +21,16 @@ import android.util.LruCache; import java.util.HashMap; /** - * An LRU cache that support querying the keys as well as values. By using the Task's key, we can - * prevent holding onto a reference to the Task resource data, while keeping the cache data in - * memory where necessary. + * An LRU cache that internally support querying the keys as well as values. We use this to keep + * track of the task metadata to determine when to invalidate the cache when tasks have been + * updated. Generally, this cache will return the last known cache value for the requested task + * key. */ public class KeyStoreLruCache<V> { // We keep a set of keys that are associated with the LRU cache, so that we can find out // information about the Task that was previously in the cache. HashMap<Integer, Task.TaskKey> mTaskKeys = new HashMap<Integer, Task.TaskKey>(); - // The cache implementation + // The cache implementation, mapping task id -> value LruCache<Integer, V> mCache; public KeyStoreLruCache(int cacheSize) { diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java index 60e89bf880a6..e48e5f053f5f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java @@ -19,6 +19,7 @@ package com.android.systemui.recents.model; import android.content.ComponentName; import android.content.Context; import android.os.Looper; +import android.os.UserHandle; import com.android.internal.content.PackageMonitor; import com.android.systemui.recents.misc.SystemServicesProxy; @@ -26,16 +27,16 @@ import java.util.HashSet; import java.util.List; /** - * The package monitor listens for changes from PackageManager to update the contents of the Recents - * list. + * The package monitor listens for changes from PackageManager to update the contents of the + * Recents list. */ public class RecentsPackageMonitor extends PackageMonitor { public interface PackageCallbacks { - public void onComponentRemoved(HashSet<ComponentName> cns); + public void onPackagesChanged(RecentsPackageMonitor monitor, String packageName, + int userId); } PackageCallbacks mCb; - List<Task.TaskKey> mTasks; SystemServicesProxy mSystemServicesProxy; /** Registers the broadcast receivers with the specified callbacks. */ @@ -43,7 +44,9 @@ public class RecentsPackageMonitor extends PackageMonitor { mSystemServicesProxy = new SystemServicesProxy(context); mCb = cb; try { - register(context, Looper.getMainLooper(), true); + // We register for events from all users, but will cross-reference them with + // packages for the current user and any profiles they have + register(context, Looper.getMainLooper(), UserHandle.ALL, true); } catch (IllegalStateException e) { e.printStackTrace(); } @@ -59,29 +62,15 @@ public class RecentsPackageMonitor extends PackageMonitor { } mSystemServicesProxy = null; mCb = null; - mTasks.clear(); - } - - /** Sets the list of tasks to match against package broadcast changes. */ - void setTasks(List<Task.TaskKey> tasks) { - mTasks = tasks; } @Override public void onPackageRemoved(String packageName, int uid) { if (mCb == null) return; - // Identify all the tasks that should be removed as a result of the package being removed. - // Using a set to ensure that we callback once per unique component. - HashSet<ComponentName> componentsToRemove = new HashSet<ComponentName>(); - for (Task.TaskKey t : mTasks) { - ComponentName cn = t.baseIntent.getComponent(); - if (cn.getPackageName().equals(packageName)) { - componentsToRemove.add(cn); - } - } - // Notify our callbacks that the components no longer exist - mCb.onComponentRemoved(componentsToRemove); + // Notify callbacks that a package has changed + final int eventUserId = getChangingUserId(); + mCb.onPackagesChanged(this, packageName, eventUserId); } @Override @@ -94,25 +83,38 @@ public class RecentsPackageMonitor extends PackageMonitor { public void onPackageModified(String packageName) { if (mCb == null) return; + // Notify callbacks that a package has changed + final int eventUserId = getChangingUserId(); + mCb.onPackagesChanged(this, packageName, eventUserId); + } + + /** + * Computes the components that have been removed as a result of a change in the specified + * package. + */ + public HashSet<ComponentName> computeComponentsRemoved(List<Task.TaskKey> taskKeys, + String packageName, int userId) { // Identify all the tasks that should be removed as a result of the package being removed. // Using a set to ensure that we callback once per unique component. - HashSet<ComponentName> componentsKnownToExist = new HashSet<ComponentName>(); - HashSet<ComponentName> componentsToRemove = new HashSet<ComponentName>(); - for (Task.TaskKey t : mTasks) { + HashSet<ComponentName> existingComponents = new HashSet<ComponentName>(); + HashSet<ComponentName> removedComponents = new HashSet<ComponentName>(); + for (Task.TaskKey t : taskKeys) { + // Skip if this doesn't apply to the current user + if (t.userId != userId) continue; + ComponentName cn = t.baseIntent.getComponent(); if (cn.getPackageName().equals(packageName)) { - if (componentsKnownToExist.contains(cn)) { + if (existingComponents.contains(cn)) { // If we know that the component still exists in the package, then skip continue; } - if (mSystemServicesProxy.getActivityInfo(cn) != null) { - componentsKnownToExist.add(cn); + if (mSystemServicesProxy.getActivityInfo(cn, userId) != null) { + existingComponents.add(cn); } else { - componentsToRemove.add(cn); + removedComponents.add(cn); } } } - // Notify our callbacks that the components no longer exist - mCb.onComponentRemoved(componentsToRemove); + return removedComponents; } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java index d40e8474e573..b4f62d5ef490 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java @@ -171,6 +171,9 @@ class TaskResourceLoader implements Runnable { } } else { SystemServicesProxy ssp = mSystemServicesProxy; + // If we've stopped the loader, then fall thorugh to the above logic to wait on + // the load thread + if (ssp == null) continue; // Load the next item from the queue final Task t = mLoadQueue.nextTask(); @@ -418,17 +421,25 @@ public class RecentsTaskLoader { root.setStack(stack); // Start the task loader and add all the tasks we need to load - mLoader.start(context); mLoadQueue.addTasks(tasksToLoad); - - // Update the package monitor with the list of packages to listen for - mPackageMonitor.setTasks(taskKeys); + mLoader.start(context); return root; } + /** Preloads the set of recent tasks (not including thumbnails). */ + public void preload(Context context) { + ArrayList<Task> tasksToLoad = new ArrayList<Task>(); + getTaskStack(mSystemServicesProxy, context.getResources(), + -1, -1, true, true, null, tasksToLoad); + + // Start the task loader and add all the tasks we need to load + mLoadQueue.addTasks(tasksToLoad); + mLoader.start(context); + } + /** Creates a lightweight stack of the current recent tasks, without thumbnails and icons. */ - public TaskStack getTaskStack(SystemServicesProxy ssp, Resources res, + public synchronized TaskStack getTaskStack(SystemServicesProxy ssp, Resources res, int preloadTaskId, int preloadTaskCount, boolean loadTaskThumbnails, boolean isTopTaskHome, List<Task.TaskKey> taskKeysOut, List<Task> tasksToLoadOut) { diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java index a7e2b0b4f3a3..55dfe4561de8 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java @@ -129,7 +129,7 @@ public class Task { TaskCallbacks mCb; public Task() { - // Only used by RecentsService for task rect calculations. + // Do nothing } public Task(TaskKey key, boolean isActive, int taskAffiliation, int taskAffiliationColor, diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java index 1e47b504baf4..a37b9e63f30f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java @@ -255,6 +255,17 @@ public class TaskStack { return mTaskList.getTasks().get(mTaskList.size() - 1); } + /** Gets the task keys */ + public ArrayList<Task.TaskKey> getTaskKeys() { + ArrayList<Task.TaskKey> taskKeys = new ArrayList<Task.TaskKey>(); + ArrayList<Task> tasks = mTaskList.getTasks(); + int taskCount = tasks.size(); + for (int i = 0; i < taskCount; i++) { + taskKeys.add(tasks.get(i).key); + } + return taskKeys; + } + /** Gets the tasks */ public ArrayList<Task> getTasks() { return mTaskList.getTasks(); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java index d2fdaff2b88f..5f8f3f26b594 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java @@ -17,12 +17,10 @@ package com.android.systemui.recents.views; import android.animation.ObjectAnimator; -import android.animation.ValueAnimator; import android.graphics.Outline; import android.graphics.Rect; import android.view.View; import android.view.ViewOutlineProvider; - import com.android.systemui.recents.RecentsConfiguration; /* An outline provider that has a clip and outline that can be animated. */ @@ -31,35 +29,27 @@ public class AnimateableViewBounds extends ViewOutlineProvider { RecentsConfiguration mConfig; TaskView mSourceView; - Rect mTmpRect = new Rect(); Rect mClipRect = new Rect(); Rect mClipBounds = new Rect(); - Rect mOutlineClipRect = new Rect(); int mCornerRadius; float mAlpha = 1f; final float mMinAlpha = 0.25f; - ObjectAnimator mClipTopAnimator; - ObjectAnimator mClipRightAnimator; ObjectAnimator mClipBottomAnimator; public AnimateableViewBounds(TaskView source, int cornerRadius) { mConfig = RecentsConfiguration.getInstance(); mSourceView = source; mCornerRadius = cornerRadius; - setClipTop(getClipTop()); - setClipRight(getClipRight()); setClipBottom(getClipBottom()); - setOutlineClipBottom(getOutlineClipBottom()); } @Override public void getOutline(View view, Outline outline) { outline.setAlpha(mMinAlpha + mAlpha / (1f - mMinAlpha)); - outline.setRoundRect(Math.max(mClipRect.left, mOutlineClipRect.left), - Math.max(mClipRect.top, mOutlineClipRect.top), - mSourceView.getWidth() - Math.max(mClipRect.right, mOutlineClipRect.right), - mSourceView.getHeight() - Math.max(mClipRect.bottom, mOutlineClipRect.bottom), + outline.setRoundRect(mClipRect.left, mClipRect.top, + mSourceView.getWidth() - mClipRect.right, + mSourceView.getHeight() - mClipRect.bottom, mCornerRadius); } @@ -71,73 +61,6 @@ public class AnimateableViewBounds extends ViewOutlineProvider { } } - /** Animates the top clip. */ - void animateClipTop(int top, int duration, ValueAnimator.AnimatorUpdateListener updateListener) { - if (mClipTopAnimator != null) { - mClipTopAnimator.removeAllListeners(); - mClipTopAnimator.cancel(); - } - mClipTopAnimator = ObjectAnimator.ofInt(this, "clipTop", top); - mClipTopAnimator.setDuration(duration); - mClipTopAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator); - if (updateListener != null) { - mClipTopAnimator.addUpdateListener(updateListener); - } - mClipTopAnimator.start(); - } - - /** Sets the top clip. */ - public void setClipTop(int top) { - if (top != mClipRect.top) { - mClipRect.top = top; - mSourceView.invalidateOutline(); - updateClipBounds(); - } - } - - /** Returns the top clip. */ - public int getClipTop() { - return mClipRect.top; - } - - /** Animates the right clip. */ - void animateClipRight(int right, int duration) { - if (mClipRightAnimator != null) { - mClipRightAnimator.removeAllListeners(); - mClipRightAnimator.cancel(); - } - mClipRightAnimator = ObjectAnimator.ofInt(this, "clipRight", right); - mClipRightAnimator.setDuration(duration); - mClipRightAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator); - mClipRightAnimator.start(); - } - - /** Sets the right clip. */ - public void setClipRight(int right) { - if (right != mClipRect.right) { - mClipRect.right = right; - mSourceView.invalidateOutline(); - updateClipBounds(); - } - } - - /** Returns the right clip. */ - public int getClipRight() { - return mClipRect.right; - } - - /** Animates the bottom clip. */ - void animateClipBottom(int bottom, int duration) { - if (mClipBottomAnimator != null) { - mClipBottomAnimator.removeAllListeners(); - mClipBottomAnimator.cancel(); - } - mClipBottomAnimator = ObjectAnimator.ofInt(this, "clipBottom", bottom); - mClipBottomAnimator.setDuration(duration); - mClipBottomAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator); - mClipBottomAnimator.start(); - } - /** Sets the bottom clip. */ public void setClipBottom(int bottom) { if (bottom != mClipRect.bottom) { @@ -145,7 +68,7 @@ public class AnimateableViewBounds extends ViewOutlineProvider { mSourceView.invalidateOutline(); updateClipBounds(); if (!mConfig.useHardwareLayers) { - mSourceView.mThumbnailView.updateVisibility( + mSourceView.mThumbnailView.updateThumbnailVisibility( bottom - mSourceView.getPaddingBottom()); } } @@ -156,19 +79,6 @@ public class AnimateableViewBounds extends ViewOutlineProvider { return mClipRect.bottom; } - /** Sets the outline bottom clip. */ - public void setOutlineClipBottom(int bottom) { - if (bottom != mOutlineClipRect.bottom) { - mOutlineClipRect.bottom = bottom; - mSourceView.invalidateOutline(); - } - } - - /** Gets the outline bottom clip. */ - public int getOutlineClipBottom() { - return mOutlineClipRect.bottom; - } - private void updateClipBounds() { mClipBounds.set(mClipRect.left, mClipRect.top, mSourceView.getWidth() - mClipRect.right, diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index 6c22a3b28798..6b0d3066720e 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -18,8 +18,6 @@ package com.android.systemui.recents.views; import android.app.ActivityOptions; import android.app.TaskStackBuilder; -import android.content.ActivityNotFoundException; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; @@ -35,7 +33,6 @@ import android.view.WindowInsets; import android.widget.FrameLayout; import com.android.systemui.recents.Constants; import com.android.systemui.recents.RecentsConfiguration; -import com.android.systemui.recents.misc.Console; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.recents.misc.Utilities; import com.android.systemui.recents.model.RecentsPackageMonitor; @@ -44,7 +41,6 @@ import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.TaskStack; import java.util.ArrayList; -import java.util.HashSet; /** * This view is the the top level layout that contains TaskStacks (which are laid out according @@ -339,7 +335,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV View child = getChildAt(i); if (child != mSearchBar) { TaskStackView stackView = (TaskStackView) child; - stackView.focusNextTask(forward); + stackView.focusNextTask(forward, true); break; } } @@ -566,14 +562,14 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV /**** RecentsPackageMonitor.PackageCallbacks Implementation ****/ @Override - public void onComponentRemoved(HashSet<ComponentName> cns) { + public void onPackagesChanged(RecentsPackageMonitor monitor, String packageName, int userId) { // Propagate this event down to each task stack view int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); if (child != mSearchBar) { TaskStackView stackView = (TaskStackView) child; - stackView.onComponentRemoved(cns); + stackView.onPackagesChanged(monitor, packageName, userId); } } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index 40134da79af2..dee26e6e45ca 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -24,7 +24,6 @@ import android.graphics.Rect; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; -import android.view.ViewTreeObserver; import android.view.accessibility.AccessibilityEvent; import android.widget.FrameLayout; import com.android.systemui.R; @@ -415,7 +414,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } /** Focuses the task at the specified index in the stack */ - void focusTask(int taskIndex, boolean scrollToNewPosition) { + void focusTask(int taskIndex, boolean scrollToNewPosition, final boolean animateFocusedState) { // Return early if the task is already focused if (taskIndex == mFocusedTaskIndex) return; @@ -427,7 +426,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal TaskView tv = getChildViewForTask(t); Runnable postScrollRunnable = null; if (tv != null) { - tv.setFocusedTask(); + tv.setFocusedTask(animateFocusedState); } else { postScrollRunnable = new Runnable() { @Override @@ -435,7 +434,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal Task t = mStack.getTasks().get(mFocusedTaskIndex); TaskView tv = getChildViewForTask(t); if (tv != null) { - tv.setFocusedTask(); + tv.setFocusedTask(animateFocusedState); } } }; @@ -455,18 +454,50 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } } - /** Focuses the next task in the stack */ - void focusNextTask(boolean forward) { + /** + * Ensures that there is a task focused, if nothign is focused, then we will use the task + * at the center of the visible stack. + */ + public boolean ensureFocusedTask() { + if (mFocusedTaskIndex < 0) { + // If there is no task focused, then find the task that is closes to the center + // of the screen and use that as the currently focused task + int x = mLayoutAlgorithm.mStackVisibleRect.centerX(); + int y = mLayoutAlgorithm.mStackVisibleRect.centerY(); + int childCount = getChildCount(); + for (int i = childCount - 1; i >= 0; i--) { + TaskView tv = (TaskView) getChildAt(i); + tv.getHitRect(mTmpRect); + if (mTmpRect.contains(x, y)) { + mFocusedTaskIndex = mStack.indexOfTask(tv.getTask()); + break; + } + } + // If we can't find the center task, then use the front most index + if (mFocusedTaskIndex < 0 && childCount > 0) { + mFocusedTaskIndex = childCount - 1; + } + } + return mFocusedTaskIndex >= 0; + } + + /** + * Focuses the next task in the stack. + * @param animateFocusedState determines whether to actually draw the highlight along with + * the change in focus, as well as whether to scroll to fit the + * task into view. + */ + public void focusNextTask(boolean forward, boolean animateFocusedState) { // Find the next index to focus int numTasks = mStack.getTaskCount(); if (numTasks == 0) return; - int nextFocusIndex = numTasks - 1; - if (0 <= mFocusedTaskIndex && mFocusedTaskIndex < numTasks) { - nextFocusIndex = Math.max(0, Math.min(numTasks - 1, - mFocusedTaskIndex + (forward ? -1 : 1))); + int direction = (forward ? -1 : 1); + int newIndex = mFocusedTaskIndex + direction; + if (newIndex >= 0 && newIndex <= (numTasks - 1)) { + newIndex = Math.max(0, Math.min(numTasks - 1, newIndex)); + focusTask(newIndex, true, animateFocusedState); } - focusTask(nextFocusIndex, true); } /** Dismisses the focused task. */ @@ -506,6 +537,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } @Override + public boolean onGenericMotionEvent(MotionEvent ev) { + return mTouchHandler.onGenericMotionEvent(ev); + } + + @Override public void computeScroll() { mStackScroller.computeScroll(); // Synchronize the views @@ -562,22 +598,18 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { TaskView tv = (TaskView) getChildAt(i); - if (tv.isFullScreenView()) { - tv.measure(widthMeasureSpec, heightMeasureSpec); + if (tv.getBackground() != null) { + tv.getBackground().getPadding(mTmpRect); } else { - if (tv.getBackground() != null) { - tv.getBackground().getPadding(mTmpRect); - } else { - mTmpRect.setEmpty(); - } - tv.measure( - MeasureSpec.makeMeasureSpec( - mLayoutAlgorithm.mTaskRect.width() + mTmpRect.left + mTmpRect.right, - MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec( - mLayoutAlgorithm.mTaskRect.height() + mTmpRect.top + mTmpRect.bottom + - tv.getMaxFooterHeight(), MeasureSpec.EXACTLY)); + mTmpRect.setEmpty(); } + tv.measure( + MeasureSpec.makeMeasureSpec( + mLayoutAlgorithm.mTaskRect.width() + mTmpRect.left + mTmpRect.right, + MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec( + mLayoutAlgorithm.mTaskRect.height() + mTmpRect.top + mTmpRect.bottom, + MeasureSpec.EXACTLY)); } setMeasuredDimension(width, height); @@ -594,20 +626,15 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { TaskView tv = (TaskView) getChildAt(i); - if (tv.isFullScreenView()) { - tv.layout(left, top, left + tv.getMeasuredWidth(), top + tv.getMeasuredHeight()); + if (tv.getBackground() != null) { + tv.getBackground().getPadding(mTmpRect); } else { - if (tv.getBackground() != null) { - tv.getBackground().getPadding(mTmpRect); - } else { - mTmpRect.setEmpty(); - } - tv.layout(mLayoutAlgorithm.mTaskRect.left - mTmpRect.left, - mLayoutAlgorithm.mTaskRect.top - mTmpRect.top, - mLayoutAlgorithm.mTaskRect.right + mTmpRect.right, - mLayoutAlgorithm.mTaskRect.bottom + mTmpRect.bottom + - tv.getMaxFooterHeight()); + mTmpRect.setEmpty(); } + tv.layout(mLayoutAlgorithm.mTaskRect.left - mTmpRect.left, + mLayoutAlgorithm.mTaskRect.top - mTmpRect.top, + mLayoutAlgorithm.mTaskRect.right + mTmpRect.right, + mLayoutAlgorithm.mTaskRect.bottom + mTmpRect.bottom); } if (mAwaitingFirstLayout) { @@ -653,9 +680,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal // When Alt-Tabbing, we scroll to and focus the previous task if (mConfig.launchedWithAltTab) { if (mConfig.launchedFromHome) { - focusTask(Math.max(0, mStack.getTaskCount() - 1), false); + focusTask(Math.max(0, mStack.getTaskCount() - 1), false, true); } else { - focusTask(Math.max(0, mStack.getTaskCount() - 2), false); + focusTask(Math.max(0, mStack.getTaskCount() - 2), false, true); } } } @@ -811,6 +838,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal TaskView frontTv = getChildViewForTask(newFrontMostTask); if (frontTv != null) { frontTv.onTaskBound(newFrontMostTask); + frontTv.fadeInActionButton(false); } } @@ -923,13 +951,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal // Rebind the task and request that this task's data be filled into the TaskView tv.onTaskBound(task); - // Mark the launch task as fullscreen - if (Constants.DebugFlags.App.EnableScreenshotAppTransition && mAwaitingFirstLayout) { - if (task.isLaunchTarget) { - tv.setIsFullScreen(true); - } - } - // Load the task data RecentsTaskLoader.getInstance().loadTaskData(task); @@ -1018,14 +1039,18 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal tv.getTask().activityLabel)); // Remove the task from the view mStack.removeTask(task); - // If the dismissed task was focused, then we should focus the next task in front + // If the dismissed task was focused, then we should focus the new task in the same index if (taskWasFocused) { ArrayList<Task> tasks = mStack.getTasks(); - int nextTaskIndex = Math.min(tasks.size() - 1, taskIndex); + int nextTaskIndex = Math.min(tasks.size() - 1, taskIndex - 1); if (nextTaskIndex >= 0) { Task nextTask = tasks.get(nextTaskIndex); TaskView nextTv = getChildViewForTask(nextTask); - nextTv.setFocusedTask(); + if (nextTv != null) { + // Focus the next task, and only animate the visible state if we are launched + // from Alt-Tab + nextTv.setFocusedTask(mConfig.launchedWithAltTab); + } } } } @@ -1038,11 +1063,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } @Override - public void onTaskViewFullScreenTransitionCompleted() { - requestSynchronizeStackViewsWithModel(); - } - - @Override public void onTaskViewFocusChanged(TaskView tv, boolean focused) { if (focused) { mFocusedTaskIndex = mStack.indexOfTask(tv.getTask()); @@ -1061,12 +1081,16 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal /**** RecentsPackageMonitor.PackageCallbacks Implementation ****/ @Override - public void onComponentRemoved(HashSet<ComponentName> cns) { + public void onPackagesChanged(RecentsPackageMonitor monitor, String packageName, int userId) { + // Compute which components need to be removed + HashSet<ComponentName> removedComponents = monitor.computeComponentsRemoved( + mStack.getTaskKeys(), packageName, userId); + // For other tasks, just remove them directly if they no longer exist ArrayList<Task> tasks = mStack.getTasks(); for (int i = tasks.size() - 1; i >= 0; i--) { final Task t = tasks.get(i); - if (cns.contains(t.key.baseIntent.getComponent())) { + if (removedComponents.contains(t.key.baseIntent.getComponent())) { TaskView tv = getChildViewForTask(t); if (tv != null) { // For visible children, defer removing the task until after the animation diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java index 31fc7014db3a..c549d2b45589 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java @@ -199,18 +199,14 @@ public class TaskStackViewLayoutAlgorithm { return transformOut; } - /** - * Returns the untransformed task view size. - */ + /** Returns the untransformed task view size. */ public Rect getUntransformedTaskViewSize() { Rect tvSize = new Rect(mTaskRect); tvSize.offsetTo(0, 0); return tvSize; } - /** - * Returns the scroll to such task top = 1f; - */ + /** Returns the scroll to such task top = 1f; */ float getStackScrollForTask(Task t) { return mTaskProgressMap.get(t.key); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java index 5852b88ae72e..04f7c6fca64b 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java @@ -23,6 +23,7 @@ import android.animation.ValueAnimator; import android.content.Context; import android.widget.OverScroller; import com.android.systemui.recents.RecentsConfiguration; +import com.android.systemui.recents.misc.Utilities; /* The scrolling logic for a TaskStackView */ public class TaskStackViewScroller { @@ -38,6 +39,7 @@ public class TaskStackViewScroller { OverScroller mScroller; ObjectAnimator mScrollAnimator; + float mFinalAnimatedScroll; public TaskStackViewScroller(Context context, RecentsConfiguration config, TaskStackViewLayoutAlgorithm layoutAlgorithm) { mConfig = config; @@ -128,10 +130,15 @@ public class TaskStackViewScroller { /** Animates the stack scroll */ void animateScroll(float curScroll, float newScroll, final Runnable postRunnable) { - // Abort any current animations + // Finish any current scrolling animations + if (mScrollAnimator != null && mScrollAnimator.isRunning()) { + setStackScroll(mFinalAnimatedScroll); + mScroller.startScroll(0, progressToScrollRange(mFinalAnimatedScroll), 0, 0, 0); + } stopScroller(); stopBoundScrollAnimation(); + mFinalAnimatedScroll = newScroll; mScrollAnimator = ObjectAnimator.ofFloat(this, "stackScroll", curScroll, newScroll); mScrollAnimator.setDuration(mConfig.taskStackScrollDuration); mScrollAnimator.setInterpolator(mConfig.linearOutSlowInInterpolator); @@ -155,10 +162,7 @@ public class TaskStackViewScroller { /** Aborts any current stack scrolls */ void stopBoundScrollAnimation() { - if (mScrollAnimator != null) { - mScrollAnimator.removeAllListeners(); - mScrollAnimator.cancel(); - } + Utilities.cancelAnimationWithoutCallbacks(mScrollAnimator); } /**** OverScroller ****/ 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 8f9b4c211a1e..2b173a965e22 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java @@ -17,6 +17,7 @@ package com.android.systemui.recents.views; import android.content.Context; +import android.view.InputDevice; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; @@ -189,7 +190,6 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { /** Handles touch events once we have intercepted them */ public boolean onTouchEvent(MotionEvent ev) { - // Short circuit if we have no children boolean hasChildren = (mSv.getChildCount() > 0); if (!hasChildren) { @@ -336,6 +336,30 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { return true; } + /** Handles generic motion events */ + public boolean onGenericMotionEvent(MotionEvent ev) { + if ((ev.getSource() & InputDevice.SOURCE_CLASS_POINTER) == + InputDevice.SOURCE_CLASS_POINTER) { + int action = ev.getAction(); + switch (action & MotionEvent.ACTION_MASK) { + case MotionEvent.ACTION_SCROLL: + // Find the front most task and scroll the next task to the front + float vScroll = ev.getAxisValue(MotionEvent.AXIS_VSCROLL); + if (vScroll > 0) { + if (mSv.ensureFocusedTask()) { + mSv.focusNextTask(true, false); + } + } else { + if (mSv.ensureFocusedTask()) { + mSv.focusNextTask(false, false); + } + } + return true; + } + } + return false; + } + /**** SwipeHelper Implementation ****/ @Override @@ -355,8 +379,6 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { tv.setClipViewInStack(false); // Disallow touch events from this task view tv.setTouchEnabled(false); - // Hide the footer - tv.animateFooterVisibility(false, mSv.mConfig.taskViewLockToAppShortAnimDuration); // Disallow parents from intercepting touch events final ViewParent parent = mSv.getParent(); if (parent != null) { @@ -387,8 +409,6 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { tv.setClipViewInStack(true); // Re-enable touch events from this task view tv.setTouchEnabled(true); - // Restore the footer - tv.animateFooterVisibility(true, mSv.mConfig.taskViewLockToAppShortAnimDuration); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java index 26581762dbca..7b4e10a74b3d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -21,23 +21,22 @@ import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.*; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.LayerDrawable; import android.util.AttributeSet; import android.view.View; import android.view.ViewOutlineProvider; +import android.view.ViewPropertyAnimator; import android.view.animation.AccelerateInterpolator; import android.widget.FrameLayout; import com.android.systemui.R; -import com.android.systemui.recents.AlternateRecentsComponent; import com.android.systemui.recents.Constants; import com.android.systemui.recents.RecentsConfiguration; -import com.android.systemui.recents.model.RecentsTaskLoader; +import com.android.systemui.recents.misc.Utilities; import com.android.systemui.recents.model.Task; +import com.android.systemui.statusbar.phone.PhoneStatusBar; /* A task view */ public class TaskView extends FrameLayout implements Task.TaskCallbacks, - TaskViewFooter.TaskFooterViewCallbacks, View.OnClickListener, View.OnLongClickListener { + View.OnClickListener, View.OnLongClickListener { /** The TaskView callbacks */ interface TaskViewCallbacks { @@ -46,7 +45,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, public void onTaskViewClicked(TaskView tv, Task task, boolean lockToTask); public void onTaskViewDismissed(TaskView tv); public void onTaskViewClipStateChanged(TaskView tv); - public void onTaskViewFullScreenTransitionCompleted(); public void onTaskViewFocusChanged(TaskView tv, boolean focused); } @@ -54,25 +52,22 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, float mTaskProgress; ObjectAnimator mTaskProgressAnimator; - ObjectAnimator mDimAnimator; float mMaxDimScale; - int mDim; + int mDimAlpha; AccelerateInterpolator mDimInterpolator = new AccelerateInterpolator(1f); - PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.MULTIPLY); + PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP); + Paint mDimLayerPaint = new Paint(); Task mTask; boolean mTaskDataLoaded; boolean mIsFocused; boolean mFocusAnimationsEnabled; - boolean mIsFullScreenView; boolean mClipViewInStack; AnimateableViewBounds mViewBounds; - Paint mLayerPaint = new Paint(); View mContent; TaskViewThumbnail mThumbnailView; TaskViewHeader mHeaderView; - TaskViewFooter mFooterView; View mActionButtonView; TaskViewCallbacks mCb; @@ -133,7 +128,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, mContent = findViewById(R.id.task_view_content); mHeaderView = (TaskViewHeader) findViewById(R.id.task_view_bar); mThumbnailView = (TaskViewThumbnail) findViewById(R.id.task_view_thumbnail); - mThumbnailView.enableTaskBarClip(mHeaderView); + mThumbnailView.updateClipToTaskBar(mHeaderView); mActionButtonView = findViewById(R.id.lock_to_app_fab); mActionButtonView.setOutlineProvider(new ViewOutlineProvider() { @Override @@ -142,9 +137,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, outline.setOval(0, 0, mActionButtonView.getWidth(), mActionButtonView.getHeight()); } }); - if (mFooterView != null) { - mFooterView.setCallbacks(this); - } } @Override @@ -159,29 +151,16 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, mContent.measure(MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY)); - // Measure the bar view, thumbnail, and footer + // Measure the bar view, and action button mHeaderView.measure(MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(mConfig.taskBarHeight, MeasureSpec.EXACTLY)); - if (mFooterView != null) { - mFooterView.measure( - MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(mConfig.taskViewLockToAppButtonHeight, - MeasureSpec.EXACTLY)); - } mActionButtonView.measure( MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(heightWithoutPadding, MeasureSpec.AT_MOST)); - if (mIsFullScreenView) { - // Measure the thumbnail height to be the full dimensions - mThumbnailView.measure( - MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(heightWithoutPadding, MeasureSpec.EXACTLY)); - } else { - // Measure the thumbnail to be square - mThumbnailView.measure( - MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY)); - } + // Measure the thumbnail to be square + mThumbnailView.measure( + MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY)); setMeasuredDimension(width, height); invalidateOutline(); } @@ -193,25 +172,12 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, void updateViewPropertiesToTaskTransform(TaskViewTransform toTransform, int duration, ValueAnimator.AnimatorUpdateListener updateCallback) { - // If we are a full screen view, then only update the Z to keep it in order - // XXX: Also update/animate the dim as well - if (mIsFullScreenView) { - if (!mConfig.fakeShadows && - toTransform.hasTranslationZChangedFrom(getTranslationZ())) { - setTranslationZ(toTransform.translationZ); - } - return; - } - // Apply the transform toTransform.applyToTaskView(this, duration, mConfig.fastOutSlowInInterpolator, false, !mConfig.fakeShadows, updateCallback); // Update the task progress - if (mTaskProgressAnimator != null) { - mTaskProgressAnimator.removeAllListeners(); - mTaskProgressAnimator.cancel(); - } + Utilities.cancelAnimationWithoutCallbacks(mTaskProgressAnimator); if (duration <= 0) { setTaskProgress(toTransform.p); } else { @@ -253,22 +219,12 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask, boolean occludesLaunchTarget, int offscreenY) { int initialDim = getDim(); - if (mConfig.launchedFromAppWithScreenshot) { + if (mConfig.launchedFromAppWithThumbnail) { if (isTaskViewLaunchTargetTask) { - // Hide the footer during the transition in, and animate it out afterwards? - if (mFooterView != null) { - mFooterView.animateFooterVisibility(false, 0); - } - } else { - // Don't do anything for the side views when animating in - } - - } else if (mConfig.launchedFromAppWithThumbnail) { - if (isTaskViewLaunchTargetTask) { - // Hide the action button if it exists - mActionButtonView.setAlpha(0f); // Set the dim to 0 so we can animate it in initialDim = 0; + // Hide the action button + mActionButtonView.setAlpha(0f); } else if (occludesLaunchTarget) { // Move the task view off screen (below) so we can animate it in setTranslationY(offscreenY); @@ -292,74 +248,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, final TaskViewTransform transform = ctx.currentTaskTransform; int startDelay = 0; - if (mConfig.launchedFromAppWithScreenshot) { - if (mTask.isLaunchTarget) { - Rect taskRect = ctx.currentTaskRect; - int duration = mConfig.taskViewEnterFromHomeDuration * 10; - int windowInsetTop = mConfig.systemInsets.top; // XXX: Should be for the window - float taskScale = ((float) taskRect.width() / getMeasuredWidth()) * transform.scale; - float scaledYOffset = ((1f - taskScale) * getMeasuredHeight()) / 2; - float scaledWindowInsetTop = (int) (taskScale * windowInsetTop); - float scaledTranslationY = taskRect.top + transform.translationY - - (scaledWindowInsetTop + scaledYOffset); - startDelay = mConfig.taskViewEnterFromHomeStaggerDelay; - - // Animate the top clip - mViewBounds.animateClipTop(windowInsetTop, duration, - new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - int y = (Integer) animation.getAnimatedValue(); - mHeaderView.setTranslationY(y); - } - }); - // Animate the bottom or right clip - int size = Math.round((taskRect.width() / taskScale)); - if (mConfig.hasHorizontalLayout()) { - mViewBounds.animateClipRight(getMeasuredWidth() - size, duration); - } else { - mViewBounds.animateClipBottom(getMeasuredHeight() - (windowInsetTop + size), duration); - } - // Animate the task bar of the first task view - animate() - .scaleX(taskScale) - .scaleY(taskScale) - .translationY(scaledTranslationY) - .setDuration(duration) - .withEndAction(new Runnable() { - @Override - public void run() { - setIsFullScreen(false); - requestLayout(); - - // Reset the clip - mViewBounds.setClipTop(0); - mViewBounds.setClipBottom(0); - mViewBounds.setClipRight(0); - // Reset the bar translation - mHeaderView.setTranslationY(0); - // Animate the footer into view (if it is the front most task) - animateFooterVisibility(true, mConfig.taskBarEnterAnimDuration); - - // Unbind the thumbnail from the screenshot - RecentsTaskLoader.getInstance().loadTaskData(mTask); - // Recycle the full screen screenshot - AlternateRecentsComponent.consumeLastScreenshot(); - - mCb.onTaskViewFullScreenTransitionCompleted(); - - // Decrement the post animation trigger - ctx.postAnimationTrigger.decrement(); - } - }) - .start(); - } else { - // Animate the footer into view - animateFooterVisibility(true, 0); - } - ctx.postAnimationTrigger.increment(); - - } else if (mConfig.launchedFromAppWithThumbnail) { + if (mConfig.launchedFromAppWithThumbnail) { if (mTask.isLaunchTarget) { // Animate the dim/overlay if (Constants.DebugFlags.App.EnableThumbnailAlphaOnFrontmost) { @@ -381,16 +270,8 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, } ctx.postAnimationTrigger.increment(); - // Animate the footer into view - animateFooterVisibility(true, mConfig.taskBarEnterAnimDuration); - // Animate the action button in - mActionButtonView.animate().alpha(1f) - .setStartDelay(mConfig.taskBarEnterAnimDelay) - .setDuration(mConfig.taskBarEnterAnimDuration) - .setInterpolator(mConfig.fastOutLinearInInterpolator) - .withLayer() - .start(); + fadeInActionButton(true); } else { // Animate the task up if it was occluding the launch target if (ctx.currentTaskOccludesLaunchTarget) { @@ -442,14 +323,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, }) .start(); ctx.postAnimationTrigger.increment(); - - // Animate the footer into view - animateFooterVisibility(true, mConfig.taskViewEnterFromHomeDuration); startDelay = delay; - - } else { - // Animate the footer into view - animateFooterVisibility(true, 0); } // Enable the focus animations from this point onwards so that they aren't affected by the @@ -462,6 +336,21 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, }, (startDelay / 2)); } + public void fadeInActionButton(boolean withDelay) { + // Hide the action button + mActionButtonView.setAlpha(0f); + + // Animate the action button in + ViewPropertyAnimator animator = mActionButtonView.animate().alpha(1f) + .setDuration(mConfig.taskBarEnterAnimDuration) + .setInterpolator(PhoneStatusBar.ALPHA_IN) + .withLayer(); + if (withDelay) { + animator.setStartDelay(mConfig.taskBarEnterAnimDelay); + } + animator.start(); + } + /** Animates this task view as it leaves recents by pressing home. */ void startExitToHomeAnimation(ViewAnimation.TaskViewExitContext ctx) { animate() @@ -483,7 +372,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, mThumbnailView.startLaunchTaskAnimation(postAnimRunnable); // Animate the dim - if (mDim > 0) { + if (mDimAlpha > 0) { ObjectAnimator anim = ObjectAnimator.ofInt(this, "dim", 0); anim.setDuration(mConfig.taskBarExitAnimDuration); anim.setInterpolator(mConfig.fastOutLinearInInterpolator); @@ -569,23 +458,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, mCb.onTaskViewDismissed(tv); } }); - // Hide the footer - animateFooterVisibility(false, mConfig.taskViewRemoveAnimDuration); - } - - /** Sets whether this task view is full screen or not. */ - void setIsFullScreen(boolean isFullscreen) { - mIsFullScreenView = isFullscreen; - mHeaderView.setIsFullscreen(isFullscreen); - if (isFullscreen) { - // If we are full screen, then disable the bottom outline clip for the footer - mViewBounds.setOutlineClipBottom(0); - } - } - - /** Returns whether this task view should currently be drawn as a full screen view. */ - boolean isFullScreenView() { - return mIsFullScreenView; } /** @@ -593,7 +465,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, * view. */ boolean shouldClipViewInStack() { - return mClipViewInStack && !mIsFullScreenView && (getVisibility() == View.VISIBLE); + return mClipViewInStack && (getVisibility() == View.VISIBLE); } /** Sets whether this view should be clipped, or clipped against. */ @@ -604,27 +476,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, } } - /** Gets the max footer height. */ - public int getMaxFooterHeight() { - if (mFooterView != null) { - return mFooterView.mMaxFooterHeight; - } else { - return 0; - } - } - - /** Animates the footer into and out of view. */ - void animateFooterVisibility(boolean visible, int duration) { - // Hide the footer if we are a full screen view - if (mIsFullScreenView) return; - // Hide the footer if the current task can not be locked to - if (!mTask.lockToTaskEnabled || !mTask.lockToThisTask) return; - // Otherwise, animate the visibility - if (mFooterView != null) { - mFooterView.animateFooterVisibility(visible, duration); - } - } - /** Sets the current task progress. */ public void setTaskProgress(float p) { mTaskProgress = p; @@ -639,26 +490,16 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, /** Returns the current dim. */ public void setDim(int dim) { - mDim = dim; - if (mDimAnimator != null) { - mDimAnimator.removeAllListeners(); - mDimAnimator.cancel(); - } + mDimAlpha = dim; if (mConfig.useHardwareLayers) { // Defer setting hardware layers if we have not yet measured, or there is no dim to draw if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0) { - if (mDimAnimator != null) { - mDimAnimator.removeAllListeners(); - mDimAnimator.cancel(); - } - - int inverse = 255 - mDim; - mDimColorFilter.setColor(Color.argb(0xFF, inverse, inverse, inverse)); - mLayerPaint.setColorFilter(mDimColorFilter); - mContent.setLayerType(LAYER_TYPE_HARDWARE, mLayerPaint); + mDimColorFilter.setColor(Color.argb(mDimAlpha, 0, 0, 0)); + mDimLayerPaint.setColorFilter(mDimColorFilter); + mContent.setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint); } } else { - float dimAlpha = mDim / 255.0f; + float dimAlpha = mDimAlpha / 255.0f; if (mThumbnailView != null) { mThumbnailView.setDimAlpha(dimAlpha); } @@ -670,7 +511,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, /** Returns the current dim. */ public int getDim() { - return mDim; + return mDimAlpha; } /** Animates the dim to the task progress. */ @@ -706,11 +547,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, * if the view is not currently visible, or we are in touch state (where we still want to keep * track of focus). */ - public void setFocusedTask() { + public void setFocusedTask(boolean animateFocusedState) { mIsFocused = true; if (mFocusAnimationsEnabled) { // Focus the header bar - mHeaderView.onTaskViewFocusChanged(true); + mHeaderView.onTaskViewFocusChanged(true, animateFocusedState); } // Update the thumbnail alpha with the focus mThumbnailView.onFocusChanged(true); @@ -732,7 +573,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, mIsFocused = false; if (mFocusAnimationsEnabled) { // Un-focus the header bar - mHeaderView.onTaskViewFocusChanged(false); + mHeaderView.onTaskViewFocusChanged(false, true); } // Update the thumbnail alpha with the focus @@ -766,7 +607,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, mFocusAnimationsEnabled = true; if (mIsFocused && !wasFocusAnimationsEnabled) { // Re-notify the header if we were focused and animations were not previously enabled - mHeaderView.onTaskViewFocusChanged(true); + mHeaderView.onTaskViewFocusChanged(true, true); } } @@ -776,15 +617,12 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, public void onTaskBound(Task t) { mTask = t; mTask.setCallbacks(this); - if (getMeasuredWidth() == 0) { - // If we haven't yet measured, we should just set the footer height with any animation - animateFooterVisibility(t.lockToThisTask, 0); - } else { - animateFooterVisibility(t.lockToThisTask, mConfig.taskViewLockToAppLongAnimDuration); - } - // Hide the action button if lock to app is disabled - if (!t.lockToTaskEnabled && mActionButtonView.getVisibility() != View.GONE) { - mActionButtonView.setVisibility(View.GONE); + + // Hide the action button if lock to app is disabled for this view + int lockButtonVisibility = (!t.lockToTaskEnabled || !t.lockToThisTask) ? GONE : VISIBLE; + if (mActionButtonView.getVisibility() != lockButtonVisibility) { + mActionButtonView.setVisibility(lockButtonVisibility); + requestLayout(); } } @@ -792,18 +630,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, public void onTaskDataLoaded() { if (mThumbnailView != null && mHeaderView != null) { // Bind each of the views to the new task data - if (mIsFullScreenView) { - mThumbnailView.bindToScreenshot(AlternateRecentsComponent.getLastScreenshot()); - } else { - mThumbnailView.rebindToTask(mTask); - } + mThumbnailView.rebindToTask(mTask); mHeaderView.rebindToTask(mTask); // Rebind any listeners mHeaderView.mApplicationIcon.setOnClickListener(this); mHeaderView.mDismissButton.setOnClickListener(this); - if (mFooterView != null) { - mFooterView.setOnClickListener(this); - } mActionButtonView.setOnClickListener(this); if (Constants.DebugFlags.App.EnableDevAppInfoOnLongPress) { if (mConfig.developerOptionsEnabled) { @@ -824,9 +655,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, // Unbind any listeners mHeaderView.mApplicationIcon.setOnClickListener(null); mHeaderView.mDismissButton.setOnClickListener(null); - if (mFooterView != null) { - mFooterView.setOnClickListener(null); - } mActionButtonView.setOnClickListener(null); if (Constants.DebugFlags.App.EnableDevAppInfoOnLongPress) { mHeaderView.mApplicationIcon.setOnLongClickListener(null); @@ -840,19 +668,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, setOnClickListener(enabled ? this : null); } - /**** TaskViewFooter.TaskFooterViewCallbacks ****/ - - @Override - public void onTaskFooterHeightChanged(int height, int maxHeight) { - if (mIsFullScreenView) { - // Disable the bottom outline clip when fullscreen - mViewBounds.setOutlineClipBottom(0); - } else { - // Update the bottom clip in our outline provider - mViewBounds.setOutlineClipBottom(maxHeight - height); - } - } - /**** View.OnClickListener Implementation ****/ @Override @@ -876,8 +691,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, // Reset the translation of the action button before we animate it out mActionButtonView.setTranslationZ(0f); } - mCb.onTaskViewClicked(tv, tv.getTask(), - (v == mFooterView || v == mActionButtonView)); + mCb.onTaskViewClicked(tv, tv.getTask(), (v == mActionButtonView)); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewFooter.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewFooter.java deleted file mode 100644 index 324169ed4b9e..000000000000 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewFooter.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2014 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.recents.views; - -import android.animation.ObjectAnimator; -import android.content.Context; -import android.util.AttributeSet; -import android.widget.FrameLayout; -import com.android.systemui.recents.RecentsConfiguration; - - -/** The task footer view */ -public class TaskViewFooter extends FrameLayout { - - interface TaskFooterViewCallbacks { - public void onTaskFooterHeightChanged(int height, int maxHeight); - } - - RecentsConfiguration mConfig; - - TaskFooterViewCallbacks mCb; - int mFooterHeight; - int mMaxFooterHeight; - ObjectAnimator mFooterAnimator; - - public TaskViewFooter(Context context) { - this(context, null); - } - - public TaskViewFooter(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public TaskViewFooter(Context context, AttributeSet attrs, int defStyleAttr) { - this(context, attrs, defStyleAttr, 0); - } - - public TaskViewFooter(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - mConfig = RecentsConfiguration.getInstance(); - mMaxFooterHeight = mConfig.taskViewLockToAppButtonHeight; - setFooterHeight(getFooterHeight()); - } - - /** Sets the callbacks for when the footer height changes. */ - void setCallbacks(TaskFooterViewCallbacks cb) { - mCb = cb; - mCb.onTaskFooterHeightChanged(mFooterHeight, mMaxFooterHeight); - } - - /** Sets the footer height. */ - public void setFooterHeight(int footerHeight) { - if (footerHeight != mFooterHeight) { - mFooterHeight = footerHeight; - mCb.onTaskFooterHeightChanged(footerHeight, mMaxFooterHeight); - } - } - - /** Gets the footer height. */ - public int getFooterHeight() { - return mFooterHeight; - } - - /** Animates the footer into and out of view. */ - void animateFooterVisibility(final boolean visible, int duration) { - // Return early if there is no footer - if (mMaxFooterHeight <= 0) return; - - // Cancel the previous animation - if (mFooterAnimator != null) { - mFooterAnimator.removeAllListeners(); - mFooterAnimator.cancel(); - } - int finalHeight = visible ? mMaxFooterHeight : 0; - if (duration > 0) { - mFooterAnimator = ObjectAnimator.ofInt(this, "footerHeight", finalHeight); - mFooterAnimator.setDuration(duration); - mFooterAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator); - mFooterAnimator.start(); - } else { - setFooterHeight(finalHeight); - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java index 396d4419edd0..ba868f5bc90d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java @@ -36,7 +36,6 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.RippleDrawable; -import android.graphics.drawable.ShapeDrawable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; @@ -56,25 +55,27 @@ public class TaskViewHeader extends FrameLayout { RecentsConfiguration mConfig; + // Header views ImageView mDismissButton; ImageView mApplicationIcon; TextView mActivityDescription; - RippleDrawable mBackground; - GradientDrawable mBackgroundColorDrawable; + // Header drawables + boolean mCurrentPrimaryColorIsDark; + int mCurrentPrimaryColor; int mBackgroundColor; Drawable mLightDismissDrawable; Drawable mDarkDismissDrawable; + RippleDrawable mBackground; + GradientDrawable mBackgroundColorDrawable; AnimatorSet mFocusAnimator; - ValueAnimator backgroundColorAnimator; - PorterDuffColorFilter mDimFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP); - - boolean mIsFullscreen; - boolean mCurrentPrimaryColorIsDark; - int mCurrentPrimaryColor; + // Static highlight that we draw at the top of each view static Paint sHighlightPaint; - private Paint mDimPaint = new Paint(); + + // Header dim, which is only used when task view hardware layers are not used + Paint mDimLayerPaint = new Paint(); + PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP); public TaskViewHeader(Context context) { this(context, null); @@ -159,21 +160,14 @@ public class TaskViewHeader extends FrameLayout { @Override protected void onDraw(Canvas canvas) { - if (!mIsFullscreen) { - // Draw the highlight at the top edge (but put the bottom edge just out of view) - float offset = (float) Math.ceil(mConfig.taskViewHighlightPx / 2f); - float radius = mConfig.taskViewRoundedCornerRadiusPx; - int count = canvas.save(Canvas.CLIP_SAVE_FLAG); - canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight()); - canvas.drawRoundRect(-offset, 0f, (float) getMeasuredWidth() + offset, - getMeasuredHeight() + radius, radius, radius, sHighlightPaint); - canvas.restoreToCount(count); - } - } - - /** Sets whether the current task is full screen or not. */ - void setIsFullscreen(boolean isFullscreen) { - mIsFullscreen = isFullscreen; + // Draw the highlight at the top edge (but put the bottom edge just out of view) + float offset = (float) Math.ceil(mConfig.taskViewHighlightPx / 2f); + float radius = mConfig.taskViewRoundedCornerRadiusPx; + int count = canvas.save(Canvas.CLIP_SAVE_FLAG); + canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight()); + canvas.drawRoundRect(-offset, 0f, (float) getMeasuredWidth() + offset, + getMeasuredHeight() + radius, radius, radius, sHighlightPaint); + canvas.restoreToCount(count); } @Override @@ -181,6 +175,16 @@ public class TaskViewHeader extends FrameLayout { return false; } + /** + * Sets the dim alpha, only used when we are not using hardware layers. + * (see RecentsConfiguration.useHardwareLayers) + */ + void setDimAlpha(int alpha) { + mDimColorFilter.setColor(Color.argb(alpha, 0, 0, 0)); + mDimLayerPaint.setColorFilter(mDimColorFilter); + setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint); + } + /** Returns the secondary color for a primary color. */ int getSecondaryColor(int primaryColor, boolean useLightOverlayColor) { int overlayColor = useLightOverlayColor ? Color.WHITE : Color.BLACK; @@ -268,13 +272,16 @@ public class TaskViewHeader extends FrameLayout { } /** Notifies the associated TaskView has been focused. */ - void onTaskViewFocusChanged(boolean focused) { + void onTaskViewFocusChanged(boolean focused, boolean animateFocusedState) { + // If we are not animating the visible state, just return + if (!animateFocusedState) return; + boolean isRunning = false; if (mFocusAnimator != null) { isRunning = mFocusAnimator.isRunning(); - mFocusAnimator.removeAllListeners(); - mFocusAnimator.cancel(); + Utilities.cancelAnimationWithoutCallbacks(mFocusAnimator); } + if (focused) { int secondaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark); int[][] states = new int[][] { @@ -349,11 +356,4 @@ public class TaskViewHeader extends FrameLayout { } } } - - public void setDimAlpha(int alpha) { - int color = Color.argb(alpha, 0, 0, 0); - mDimFilter.setColor(color); - mDimPaint.setColorFilter(mDimFilter); - setLayerType(LAYER_TYPE_HARDWARE, mDimPaint); - } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java index a946a849310b..c83248ef37d9 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java @@ -33,37 +33,48 @@ import android.graphics.Shader; import android.util.AttributeSet; import android.view.View; import com.android.systemui.recents.RecentsConfiguration; +import com.android.systemui.recents.misc.Utilities; import com.android.systemui.recents.model.Task; -/** The task thumbnail view */ +/** + * The task thumbnail view. It implements an image view that allows for animating the dim and + * alpha of the thumbnail image. + */ public class TaskViewThumbnail extends View { - private final int mCornerRadius; - private final Matrix mScaleMatrix = new Matrix(); RecentsConfiguration mConfig; - // Task bar clipping - Rect mClipRect = new Rect(); + // Drawing + float mDimAlpha; + Matrix mScaleMatrix = new Matrix(); Paint mDrawPaint = new Paint(); + RectF mBitmapRect = new RectF(); + RectF mLayoutRect = new RectF(); + BitmapShader mBitmapShader; LightingColorFilter mLightingColorFilter = new LightingColorFilter(0xffffffff, 0); - private final RectF mBitmapRect = new RectF(); - private final RectF mLayoutRect = new RectF(); - private BitmapShader mBitmapShader; - private float mBitmapAlpha; - private float mDimAlpha; - private View mTaskBar; - private boolean mInvisible; - private ValueAnimator mAlphaAnimator; - private ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener + + // Thumbnail alpha + float mThumbnailAlpha; + ValueAnimator mThumbnailAlphaAnimator; + ValueAnimator.AnimatorUpdateListener mThumbnailAlphaUpdateListener = new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { - mBitmapAlpha = (float) animation.getAnimatedValue(); - updateFilter(); + mThumbnailAlpha = (float) animation.getAnimatedValue(); + updateThumbnailPaintFilter(); } }; + // Task bar clipping, the top of this thumbnail can be clipped against the opaque header + // bar that overlaps this thumbnail + View mTaskBar; + Rect mClipRect = new Rect(); + + // Visibility optimization, if the thumbnail height is less than the height of the header + // bar for the task view, then just mark this thumbnail view as invisible + boolean mInvisible; + public TaskViewThumbnail(Context context) { this(context, null); } @@ -79,53 +90,82 @@ public class TaskViewThumbnail extends View { public TaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); mConfig = RecentsConfiguration.getInstance(); - mCornerRadius = mConfig.taskViewRoundedCornerRadiusPx; mDrawPaint.setColorFilter(mLightingColorFilter); mDrawPaint.setFilterBitmap(true); mDrawPaint.setAntiAlias(true); } @Override + protected void onFinishInflate() { + mThumbnailAlpha = mConfig.taskViewThumbnailAlpha; + updateThumbnailPaintFilter(); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + if (changed) { + mLayoutRect.set(0, 0, getWidth(), getHeight()); + updateThumbnailScale(); + } + } + + @Override protected void onDraw(Canvas canvas) { if (mInvisible) { return; } - canvas.drawRoundRect(0, - 0, - getWidth(), - getHeight(), - mCornerRadius, - mCornerRadius, - mDrawPaint); + // Draw the thumbnail with the rounded corners + canvas.drawRoundRect(0, 0, getWidth(), getHeight(), + mConfig.taskViewRoundedCornerRadiusPx, + mConfig.taskViewRoundedCornerRadiusPx, mDrawPaint); } - @Override - protected void onFinishInflate() { - mBitmapAlpha = 0.9f; - updateFilter(); + /** Sets the thumbnail to a given bitmap. */ + void setThumbnail(Bitmap bm) { + if (bm != null) { + mBitmapShader = new BitmapShader(bm, Shader.TileMode.CLAMP, + Shader.TileMode.CLAMP); + mDrawPaint.setShader(mBitmapShader); + mBitmapRect.set(0, 0, bm.getWidth(), bm.getHeight()); + updateThumbnailScale(); + } else { + mBitmapShader = null; + mDrawPaint.setShader(null); + } + updateThumbnailPaintFilter(); } - private void updateFilter() { + /** Updates the paint to draw the thumbnail. */ + void updateThumbnailPaintFilter() { if (mInvisible) { return; } - int mul = (int) ((1.0f - mDimAlpha) * mBitmapAlpha * 255); - int add = (int) ((1.0f - mDimAlpha) * (1 - mBitmapAlpha) * 255); + int mul = (int) ((1.0f - mDimAlpha) * mThumbnailAlpha * 255); + int add = (int) ((1.0f - mDimAlpha) * (1 - mThumbnailAlpha) * 255); if (mBitmapShader != null) { mLightingColorFilter.setColorMultiply(Color.argb(255, mul, mul, mul)); mLightingColorFilter.setColorAdd(Color.argb(0, add, add, add)); mDrawPaint.setColorFilter(mLightingColorFilter); mDrawPaint.setColor(0xffffffff); } else { - mDrawPaint.setColorFilter(null); int grey = mul + add; + mDrawPaint.setColorFilter(null); mDrawPaint.setColor(Color.argb(255, grey, grey, grey)); } invalidate(); } + /** Updates the thumbnail shader's scale transform. */ + void updateThumbnailScale() { + if (mBitmapShader != null) { + mScaleMatrix.setRectToRect(mBitmapRect, mLayoutRect, Matrix.ScaleToFit.FILL); + mBitmapShader.setLocalMatrix(mScaleMatrix); + } + } + /** Updates the clip rect based on the given task bar. */ - void enableTaskBarClip(View taskBar) { + void updateClipToTaskBar(View taskBar) { mTaskBar = taskBar; int top = (int) Math.max(0, taskBar.getTranslationY() + taskBar.getMeasuredHeight() - 1); @@ -133,75 +173,39 @@ public class TaskViewThumbnail extends View { setClipBounds(mClipRect); } - void updateVisibility(int clipBottom) { - boolean invisible = mTaskBar != null && getHeight() - clipBottom < mTaskBar.getHeight(); + /** Updates the visibility of the the thumbnail. */ + void updateThumbnailVisibility(int clipBottom) { + boolean invisible = mTaskBar != null && (getHeight() - clipBottom) <= mTaskBar.getHeight(); if (invisible != mInvisible) { mInvisible = invisible; if (!mInvisible) { - updateFilter(); + updateThumbnailPaintFilter(); } invalidate(); } } - /** Binds the thumbnail view to the screenshot. */ - boolean bindToScreenshot(Bitmap ss) { - setImageBitmap(ss); - return ss != null; - } - - /** Unbinds the thumbnail view from the screenshot. */ - void unbindFromScreenshot() { - setImageBitmap(null); + /** + * Sets the dim alpha, only used when we are not using hardware layers. + * (see RecentsConfiguration.useHardwareLayers) + */ + public void setDimAlpha(float dimAlpha) { + mDimAlpha = dimAlpha; + updateThumbnailPaintFilter(); } /** Binds the thumbnail view to the task */ void rebindToTask(Task t) { if (t.thumbnail != null) { - setImageBitmap(t.thumbnail); + setThumbnail(t.thumbnail); } else { - setImageBitmap(null); + setThumbnail(null); } } - public void setImageBitmap(Bitmap bm) { - if (bm != null) { - mBitmapShader = new BitmapShader(bm, Shader.TileMode.CLAMP, - Shader.TileMode.CLAMP); - mDrawPaint.setShader(mBitmapShader); - mBitmapRect.set(0, 0, bm.getWidth(), bm.getHeight()); - updateBitmapScale(); - } else { - mBitmapShader = null; - mDrawPaint.setShader(null); - } - updateFilter(); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - if (changed) { - mLayoutRect.set(0, 0, getWidth(), getHeight()); - updateBitmapScale(); - } - } - - private void updateBitmapScale() { - if (mBitmapShader != null) { - mScaleMatrix.setRectToRect(mBitmapRect, mLayoutRect, Matrix.ScaleToFit.FILL); - mBitmapShader.setLocalMatrix(mScaleMatrix); - } - } - - public void setDimAlpha(float dimAlpha) { - mDimAlpha = dimAlpha; - updateFilter(); - } - /** Unbinds the thumbnail view from the task */ void unbindFromTask() { - setImageBitmap(null); + setThumbnail(null); } /** Handles focus changes. */ @@ -217,54 +221,46 @@ public class TaskViewThumbnail extends View { } } - /** Prepares for the enter recents animation. */ + /** + * Prepares for the enter recents animation, this gets called before the the view + * is first visible and will be followed by a startEnterRecentsAnimation() call. + */ void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask) { if (isTaskViewLaunchTargetTask) { - mBitmapAlpha = 1f; + mThumbnailAlpha = 1f; } else { - mBitmapAlpha = mConfig.taskViewThumbnailAlpha; + mThumbnailAlpha = mConfig.taskViewThumbnailAlpha; } - updateFilter(); + updateThumbnailPaintFilter(); } - /** Animates this task thumbnail as it enters recents */ + /** Animates this task thumbnail as it enters Recents. */ void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) { startFadeAnimation(mConfig.taskViewThumbnailAlpha, delay, mConfig.taskBarEnterAnimDuration, postAnimRunnable); } - /** Animates this task thumbnail as it exits recents */ + /** Animates this task thumbnail as it exits Recents. */ void startLaunchTaskAnimation(Runnable postAnimRunnable) { startFadeAnimation(1f, 0, mConfig.taskBarExitAnimDuration, postAnimRunnable); } - /** Animates the thumbnail alpha. */ + /** Starts a new thumbnail alpha animation. */ void startFadeAnimation(float finalAlpha, int delay, int duration, final Runnable postAnimRunnable) { - if (mAlphaAnimator != null) { - mAlphaAnimator.cancel(); - } - mAlphaAnimator = ValueAnimator.ofFloat(mBitmapAlpha, finalAlpha); - mAlphaAnimator.addUpdateListener(mAlphaUpdateListener); - mAlphaAnimator.setStartDelay(delay); - mAlphaAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator); - mAlphaAnimator.setDuration(duration); - mAlphaAnimator.start(); + Utilities.cancelAnimationWithoutCallbacks(mThumbnailAlphaAnimator); + mThumbnailAlphaAnimator = ValueAnimator.ofFloat(mThumbnailAlpha, finalAlpha); + mThumbnailAlphaAnimator.setStartDelay(delay); + mThumbnailAlphaAnimator.setDuration(duration); + mThumbnailAlphaAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator); + mThumbnailAlphaAnimator.addUpdateListener(mThumbnailAlphaUpdateListener); if (postAnimRunnable != null) { - mAlphaAnimator.addListener(new AnimatorListenerAdapter() { - public boolean mCancelled; - - @Override - public void onAnimationCancel(Animator animation) { - mCancelled = true; - } - + mThumbnailAlphaAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - if (!mCancelled) { - postAnimRunnable.run(); - } + postAnimRunnable.run(); } }); } + mThumbnailAlphaAnimator.start(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java index e4faa6a3f85b..02b93780667a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java @@ -508,7 +508,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView if (mAppearAnimator != null) { mAppearAnimator.cancel(); } - mAnimationTranslationY = translationDirection * mActualHeight; + mAnimationTranslationY = translationDirection * getActualHeight(); if (mAppearAnimationFraction == -1.0f) { // not initialized yet, we start anew if (isAppearing) { @@ -601,14 +601,15 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView float top; float bottom; + final int actualHeight = getActualHeight(); if (mAnimationTranslationY > 0.0f) { - bottom = mActualHeight - heightFraction * mAnimationTranslationY * 0.1f + bottom = actualHeight - heightFraction * mAnimationTranslationY * 0.1f - translateYTotalAmount; top = bottom * heightFraction; } else { - top = heightFraction * (mActualHeight + mAnimationTranslationY) * 0.1f - + top = heightFraction * (actualHeight + mAnimationTranslationY) * 0.1f - translateYTotalAmount; - bottom = mActualHeight * (1 - heightFraction) + top * heightFraction; + bottom = actualHeight * (1 - heightFraction) + top * heightFraction; } mAppearAnimationRect.set(left, top, right, bottom); setOutlineRect(left, top + mAppearAnimationTranslation, right, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index f5e5517b731c..09d0b5d46e70 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -59,6 +59,7 @@ import android.service.notification.NotificationListenerService.RankingMap; import android.service.notification.StatusBarNotification; import android.text.TextUtils; import android.util.Log; +import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; import android.view.Display; @@ -69,6 +70,7 @@ import android.view.View; import android.view.ViewAnimationUtils; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; +import android.view.ViewParent; import android.view.ViewStub; import android.view.WindowManager; import android.view.WindowManagerGlobal; @@ -112,6 +114,9 @@ public abstract class BaseStatusBar extends SystemUI implements public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); public static final boolean MULTIUSER_DEBUG = false; + // STOPSHIP disable once we resolve b/18102199 + private static final boolean NOTIFICATION_CLICK_DEBUG = true; + protected static final int MSG_SHOW_RECENT_APPS = 1019; protected static final int MSG_HIDE_RECENT_APPS = 1020; protected static final int MSG_TOGGLE_RECENTS_APPS = 1021; @@ -266,6 +271,7 @@ public abstract class BaseStatusBar extends SystemUI implements if (DEBUG) { Log.v(TAG, "Notification click handler invoked for intent: " + pendingIntent); } + logActionClick(view); // The intent we are sending is for the application, which // won't have permission to immediately start an activity after // the user switches to home. We know it is safe to do at this @@ -295,7 +301,8 @@ public abstract class BaseStatusBar extends SystemUI implements // close the shade if it was open if (handled) { - animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */); + animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, + true /* force */); visibilityChanged(false); } // Wait for activity start. @@ -308,6 +315,40 @@ public abstract class BaseStatusBar extends SystemUI implements } } + private void logActionClick(View view) { + ViewParent parent = view.getParent(); + String key = getNotificationKeyForParent(parent); + if (key == null) { + Log.w(TAG, "Couldn't determine notification for click."); + return; + } + int index = -1; + // If this is a default template, determine the index of the button. + if (view.getId() == com.android.internal.R.id.action0 && + parent != null && parent instanceof ViewGroup) { + ViewGroup actionGroup = (ViewGroup) parent; + index = actionGroup.indexOfChild(view); + } + if (NOTIFICATION_CLICK_DEBUG) { + Log.d(TAG, "Clicked on button " + index + " for " + key); + } + try { + mBarService.onNotificationActionClick(key, index); + } catch (RemoteException e) { + // Ignore + } + } + + private String getNotificationKeyForParent(ViewParent parent) { + while (parent != null) { + if (parent instanceof ExpandableNotificationRow) { + return ((ExpandableNotificationRow) parent).getStatusBarNotification().getKey(); + } + parent = parent.getParent(); + } + return null; + } + private boolean superOnClickHandler(View view, PendingIntent pendingIntent, Intent fillInIntent) { return super.onClickHandler(view, pendingIntent, fillInIntent); @@ -341,7 +382,8 @@ public abstract class BaseStatusBar extends SystemUI implements Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0); if (BANNER_ACTION_SETUP.equals(action)) { - animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */); + animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, + true /* force */); mContext.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_REDACTION) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) @@ -766,7 +808,7 @@ public abstract class BaseStatusBar extends SystemUI implements } } }); - animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */); + animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */); return true; } }, false /* afterKeyguardGone */); @@ -1480,6 +1522,9 @@ public abstract class BaseStatusBar extends SystemUI implements } public void onClick(final View v) { + if (NOTIFICATION_CLICK_DEBUG) { + Log.d(TAG, "Clicked on content of " + mNotificationKey); + } final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing(); final boolean afterKeyguardGone = mIntent.isActivity() && PreviewInflater.wouldLaunchResolverActivity(mContext, mIntent.getIntent(), @@ -1531,7 +1576,8 @@ public abstract class BaseStatusBar extends SystemUI implements }.start(); // close the shade if it was open - animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */); + animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, + true /* force */); visibilityChanged(false); return mIntent != null && mIntent.isActivity(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java b/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java index 897dbf224176..479c2fb8e2aa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java @@ -36,4 +36,11 @@ public class DismissView extends StackScrollerDecorView { public void setOnButtonClickListener(OnClickListener listener) { mContent.setOnClickListener(listener); } + + public boolean isOnEmptySpace(float touchX, float touchY) { + return touchX < mContent.getX() + || touchX > mContent.getX() + mContent.getWidth() + || touchY < mContent.getY() + || touchY > mContent.getY() + mContent.getHeight(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index 9196dc89c6c3..a4e5e7443c06 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -23,10 +23,8 @@ import android.graphics.drawable.Drawable; import android.service.notification.StatusBarNotification; import android.util.AttributeSet; import android.view.View; -import android.view.ViewGroup; import android.view.ViewStub; import android.view.accessibility.AccessibilityEvent; - import android.widget.ImageView; import com.android.systemui.R; @@ -156,6 +154,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { } public void resetHeight() { + super.resetHeight(); mMaxExpandHeight = 0; mWasReset = true; onHeightReset(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java index f85d32b3770c..a18fff247397 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java @@ -41,7 +41,7 @@ public abstract class ExpandableOutlineView extends ExpandableView { outline.setRect(0, mClipTopAmount, getWidth(), - Math.max(mActualHeight, mClipTopAmount)); + Math.max(getActualHeight(), mClipTopAmount)); } else { outline.setRect(mOutlineRect); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java index c8f756e906c0..edfbe868c481 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java @@ -36,7 +36,7 @@ public abstract class ExpandableView extends FrameLayout { private final int mMaxNotificationHeight; private OnHeightChangedListener mOnHeightChangedListener; - protected int mActualHeight; + private int mActualHeight; protected int mClipTopAmount; private boolean mActualHeightInitialized; private ArrayList<View> mMatchParentViews = new ArrayList<View>(); @@ -103,6 +103,11 @@ public abstract class ExpandableView extends FrameLayout { } } + protected void resetHeight() { + mActualHeight = 0; + mActualHeightInitialized = false; + } + protected int getInitialHeight() { return getHeight(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java index 5db680a1b379..0fc46e9c701b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java @@ -23,9 +23,7 @@ import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.graphics.drawable.RippleDrawable; import android.util.AttributeSet; -import android.view.MotionEvent; import android.view.View; -import com.android.systemui.R; /** * A view that can be used for both the dimmed and normal background of an notification. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java index 502490f82aea..9b11f9bcd5d9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java @@ -27,11 +27,11 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.View; +import android.view.ViewTreeObserver; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import android.widget.FrameLayout; import android.widget.ImageView; - import com.android.systemui.R; /** @@ -60,6 +60,16 @@ public class NotificationContentView extends FrameLayout { private boolean mDark; private final Paint mFadePaint = new Paint(); + private boolean mAnimate; + private ViewTreeObserver.OnPreDrawListener mEnableAnimationPredrawListener + = new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + mAnimate = true; + getViewTreeObserver().removeOnPreDrawListener(this); + return true; + } + }; public NotificationContentView(Context context, AttributeSet attrs) { super(context, attrs); @@ -73,6 +83,12 @@ public class NotificationContentView extends FrameLayout { updateClipping(); } + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + updateVisibility(); + } + public void reset() { if (mContractedChild != null) { mContractedChild.animate().cancel(); @@ -117,9 +133,31 @@ public class NotificationContentView extends FrameLayout { selectLayout(false /* animate */, true /* force */); } + @Override + protected void onVisibilityChanged(View changedView, int visibility) { + super.onVisibilityChanged(changedView, visibility); + updateVisibility(); + } + + private void updateVisibility() { + setVisible(isShown()); + } + + private void setVisible(final boolean isVisible) { + if (isVisible) { + + // We only animate if we are drawn at least once, otherwise the view might animate when + // it's shown the first time + getViewTreeObserver().addOnPreDrawListener(mEnableAnimationPredrawListener); + } else { + getViewTreeObserver().removeOnPreDrawListener(mEnableAnimationPredrawListener); + mAnimate = false; + } + } + public void setActualHeight(int actualHeight) { mActualHeight = actualHeight; - selectLayout(true /* animate */, false /* force */); + selectLayout(mAnimate /* animate */, false /* force */); updateClipping(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java index b71c9bfc8f60..9154a487e8ac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java @@ -49,7 +49,6 @@ public class SignalClusterView private boolean mIsAirplaneMode = false; private int mAirplaneIconId = 0; private String mWifiDescription, mMobileDescription, mMobileTypeDescription; - private boolean mRoaming; private boolean mIsMobileTypeIconWide; ViewGroup mWifiGroup, mMobileGroup; @@ -58,6 +57,8 @@ public class SignalClusterView View mWifiSignalSpacer; private int mWideTypeIconStartPadding; + private int mEndPadding; + private int mEndPaddingNothingVisible; public SignalClusterView(Context context) { this(context, null); @@ -88,6 +89,10 @@ public class SignalClusterView super.onFinishInflate(); mWideTypeIconStartPadding = getContext().getResources().getDimensionPixelSize( R.dimen.wide_type_icon_start_padding); + mEndPadding = getContext().getResources().getDimensionPixelSize( + R.dimen.signal_cluster_battery_padding); + mEndPaddingNothingVisible = getContext().getResources().getDimensionPixelSize( + R.dimen.no_signal_cluster_battery_padding); } @Override @@ -143,14 +148,12 @@ public class SignalClusterView @Override public void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon, - String contentDescription, String typeContentDescription, boolean roaming, - boolean isTypeIconWide) { + String contentDescription, String typeContentDescription, boolean isTypeIconWide) { mMobileVisible = visible; mMobileStrengthId = strengthIcon; mMobileTypeId = typeIcon; mMobileDescription = contentDescription; mMobileTypeDescription = typeContentDescription; - mRoaming = roaming; mIsMobileTypeIconWide = isTypeIconWide; apply(); @@ -244,7 +247,7 @@ public class SignalClusterView mWifiAirplaneSpacer.setVisibility(View.GONE); } - if (mRoaming && mMobileVisible && mWifiVisible) { + if (mMobileVisible && mMobileTypeId != 0 && mWifiVisible) { mWifiSignalSpacer.setVisibility(View.VISIBLE); } else { mWifiSignalSpacer.setVisibility(View.GONE); @@ -257,7 +260,10 @@ public class SignalClusterView (mMobileVisible ? "VISIBLE" : "GONE"), mMobileStrengthId, mMobileTypeId)); - mMobileType.setVisibility((mRoaming || mMobileTypeId != 0) ? View.VISIBLE : View.GONE); + mMobileType.setVisibility(mMobileTypeId != 0 ? View.VISIBLE : View.GONE); + + boolean anythingVisible = mWifiVisible || mIsAirplaneMode || mMobileVisible || mVpnVisible; + setPaddingRelative(0, 0, anythingVisible ? mEndPadding : mEndPaddingNothingVisible, 0); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java index c5d06b94a115..6cb5bccf39fd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java @@ -122,9 +122,14 @@ public class DemoStatusIcons extends LinearLayout implements DemoMode { } String cast = args.getString("cast"); if (cast != null) { - int iconId = cast.equals("cast") ? R.drawable.stat_sys_cast : 0; + int iconId = cast.equals("show") ? R.drawable.stat_sys_cast : 0; updateSlot("cast", null, iconId); } + String hotspot = args.getString("hotspot"); + if (hotspot != null) { + int iconId = hotspot.equals("show") ? R.drawable.stat_sys_hotspot : 0; + updateSlot("hotspot", null, iconId); + } } } @@ -154,7 +159,7 @@ public class DemoStatusIcons extends LinearLayout implements DemoMode { } } StatusBarIcon icon = new StatusBarIcon(iconPkg, UserHandle.CURRENT, iconId, 0, 0, "Demo"); - StatusBarIconView v = new StatusBarIconView(getContext(), null); + StatusBarIconView v = new StatusBarIconView(getContext(), null, null); v.setTag(slot); v.set(icon); addView(v, 0, new LinearLayout.LayoutParams(mIconSize, mIconSize)); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java index b566bbc7096e..6fd67580226f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java @@ -48,6 +48,7 @@ public class DozeParameters { pw.print(" getDisplayStateSupported(): "); pw.println(getDisplayStateSupported()); pw.print(" getPulseDuration(): "); pw.println(getPulseDuration()); pw.print(" getPulseInDuration(): "); pw.println(getPulseInDuration()); + pw.print(" getPulseInDelay(): "); pw.println(getPulseInDelay()); pw.print(" getPulseInVisibleDuration(): "); pw.println(getPulseVisibleDuration()); pw.print(" getPulseOutDuration(): "); pw.println(getPulseOutDuration()); pw.print(" getPulseOnSigMotion(): "); pw.println(getPulseOnSigMotion()); @@ -72,6 +73,10 @@ public class DozeParameters { return getInt("doze.pulse.duration.in", R.integer.doze_pulse_duration_in); } + public int getPulseInDelay() { + return getInt("doze.pulse.delay.in", R.integer.doze_pulse_delay_in); + } + public int getPulseVisibleDuration() { return getInt("doze.pulse.duration.visible", R.integer.doze_pulse_duration_visible); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index dd5df123c4bb..fddbee2ee400 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -39,6 +39,8 @@ import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityNodeInfo; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; import android.widget.FrameLayout; import android.widget.TextView; @@ -72,6 +74,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private static final Intent INSECURE_CAMERA_INTENT = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL); + private static final int DOZE_ANIMATION_STAGGER_DELAY = 48; + private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250; private KeyguardAffordanceView mCameraImageView; private KeyguardAffordanceView mPhoneImageView; @@ -92,7 +96,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private PhoneStatusBar mPhoneStatusBar; private final TrustDrawable mTrustDrawable; - + private final Interpolator mLinearOutSlowInInterpolator; private int mLastUnlockIconRes = 0; public KeyguardBottomAreaView(Context context) { @@ -111,6 +115,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); mTrustDrawable = new TrustDrawable(mContext); + mLinearOutSlowInInterpolator = + AnimationUtils.loadInterpolator(context, android.R.interpolator.linear_out_slow_in); } private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() { @@ -133,7 +139,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL if (action == ACTION_CLICK) { if (host == mLockIcon) { mPhoneStatusBar.animateCollapsePanels( - CommandQueue.FLAG_EXCLUDE_NONE, true /* force */); + CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */); return true; } else if (host == mCameraImageView) { launchCamera(); @@ -450,6 +456,35 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } } + public void startFinishDozeAnimation() { + long delay = 0; + if (mPhoneImageView.getVisibility() == View.VISIBLE) { + startFinishDozeAnimationElement(mPhoneImageView, delay); + delay += DOZE_ANIMATION_STAGGER_DELAY; + } + startFinishDozeAnimationElement(mLockIcon, delay); + delay += DOZE_ANIMATION_STAGGER_DELAY; + if (mCameraImageView.getVisibility() == View.VISIBLE) { + startFinishDozeAnimationElement(mCameraImageView, delay); + } + mIndicationText.setAlpha(0f); + mIndicationText.animate() + .alpha(1f) + .setInterpolator(mLinearOutSlowInInterpolator) + .setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION); + } + + private void startFinishDozeAnimationElement(View element, long delay) { + element.setAlpha(0f); + element.setTranslationY(element.getHeight() / 2); + element.animate() + .alpha(1f) + .translationY(0f) + .setInterpolator(mLinearOutSlowInInterpolator) + .setStartDelay(delay) + .setDuration(DOZE_ANIMATION_ELEMENT_DURATION); + } + private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { post(new Runnable() { @@ -477,6 +512,11 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL public void onScreenTurnedOff(int why) { updateLockIcon(); } + + @Override + public void onKeyguardVisibilityChanged(boolean showing) { + updateLockIcon(); + } }; public void setKeyguardIndicationController( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java index 650a14fc33a0..40c913440472 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java @@ -36,6 +36,8 @@ import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.KeyguardUserSwitcher; import com.android.systemui.statusbar.policy.UserInfoController; +import java.text.NumberFormat; + /** * The header group on Keyguard. */ @@ -150,7 +152,8 @@ public class KeyguardStatusBarView extends RelativeLayout @Override public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { - mBatteryLevel.setText(getResources().getString(R.string.battery_level_template, level)); + String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0); + mBatteryLevel.setText(percentage); boolean changed = mBatteryCharging != charging; mBatteryCharging = charging; if (changed) { 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 88e71e2cee74..9bb52e71ddd7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -33,12 +33,14 @@ import android.os.Message; import android.util.AttributeSet; import android.util.Log; import android.view.Display; +import android.view.Gravity; import android.view.MotionEvent; import android.view.Surface; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; +import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import com.android.systemui.R; @@ -503,15 +505,31 @@ public class NavigationBarView extends LinearLayout { // We swap all children of the 90 and 270 degree layouts, since they are vertical View rotation90 = mRotatedViews[Surface.ROTATION_90]; swapChildrenOrderIfVertical(rotation90.findViewById(R.id.nav_buttons)); + adjustExtraKeyGravity(rotation90, isLayoutRtl); View rotation270 = mRotatedViews[Surface.ROTATION_270]; if (rotation90 != rotation270) { swapChildrenOrderIfVertical(rotation270.findViewById(R.id.nav_buttons)); + adjustExtraKeyGravity(rotation270, isLayoutRtl); } mIsLayoutRtl = isLayoutRtl; } } + private void adjustExtraKeyGravity(View navBar, boolean isLayoutRtl) { + View menu = navBar.findViewById(R.id.menu); + View imeSwitcher = navBar.findViewById(R.id.ime_switcher); + if (menu != null) { + FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) menu.getLayoutParams(); + lp.gravity = isLayoutRtl ? Gravity.BOTTOM : Gravity.TOP; + menu.setLayoutParams(lp); + } + if (imeSwitcher != null) { + FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) imeSwitcher.getLayoutParams(); + lp.gravity = isLayoutRtl ? Gravity.BOTTOM : Gravity.TOP; + imeSwitcher.setLayoutParams(lp); + } + } /** * Swaps the children order of a LinearLayout if it's orientation is Vertical diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index a6fccb624ab2..d9e44c30c7a6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -52,7 +52,7 @@ import com.android.systemui.statusbar.stack.StackStateAnimator; public class NotificationPanelView extends PanelView implements ExpandableView.OnHeightChangedListener, ObservableScrollView.Listener, View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener, - KeyguardAffordanceHelper.Callback { + KeyguardAffordanceHelper.Callback, NotificationStackScrollLayout.OnEmptySpaceClickListener { // Cap and total height of Roboto font. Needs to be adjusted when font for the big clock is // changed. @@ -64,7 +64,7 @@ public class NotificationPanelView extends PanelView implements private static final int DOZE_BACKGROUND_COLOR = 0xff000000; private static final int TAG_KEY_ANIM = R.id.scrim; - private static final long DOZE_BACKGROUND_ANIM_DURATION = ScrimController.ANIMATION_DURATION; + public static final long DOZE_ANIMATION_DURATION = 700; private KeyguardAffordanceHelper mAfforanceHelper; private StatusBarHeaderView mHeader; @@ -132,6 +132,7 @@ public class NotificationPanelView extends PanelView implements private Interpolator mFastOutSlowInInterpolator; private Interpolator mFastOutLinearInterpolator; + private Interpolator mDozeAnimationInterpolator; private ObjectAnimator mClockAnimator; private int mClockAnimationTarget = -1; private int mTopPaddingAdjustment; @@ -167,6 +168,8 @@ public class NotificationPanelView extends PanelView implements private boolean mQsTouchAboveFalsingThreshold; private int mQsFalsingThreshold; + private float mKeyguardStatusBarAnimateAlpha = 1f; + public NotificationPanelView(Context context, AttributeSet attrs) { super(context, attrs); } @@ -194,11 +197,14 @@ public class NotificationPanelView extends PanelView implements findViewById(R.id.notification_stack_scroller); mNotificationStackScroller.setOnHeightChangedListener(this); mNotificationStackScroller.setOverscrollTopChangedListener(this); + mNotificationStackScroller.setOnEmptySpaceClickListener(this); mNotificationStackScroller.setScrollView(mScrollView); mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(), android.R.interpolator.fast_out_slow_in); mFastOutLinearInterpolator = AnimationUtils.loadInterpolator(getContext(), android.R.interpolator.fast_out_linear_in); + mDozeAnimationInterpolator = AnimationUtils.loadInterpolator(getContext(), + android.R.interpolator.linear_out_slow_in); mKeyguardBottomArea = (KeyguardBottomAreaView) findViewById(R.id.keyguard_bottom_area); mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim); mAfforanceHelper = new KeyguardAffordanceHelper(this, getContext()); @@ -521,13 +527,15 @@ public class NotificationPanelView extends PanelView implements mIntercepting = false; break; } + return super.onInterceptTouchEvent(event); + } - // Allow closing the whole panel when in SHADE state. - if (mStatusBarState == StatusBarState.SHADE) { - return super.onInterceptTouchEvent(event); - } else { - return !mQsExpanded && super.onInterceptTouchEvent(event); - } + @Override + protected boolean isInContentBounds(float x, float y) { + float yTransformed = y - mNotificationStackScroller.getY(); + float stackScrollerX = mNotificationStackScroller.getX(); + return mNotificationStackScroller.isInContentBounds(yTransformed) && stackScrollerX < x + && x < stackScrollerX + mNotificationStackScroller.getWidth(); } private void resetDownStates(MotionEvent event) { @@ -631,10 +639,9 @@ public class NotificationPanelView extends PanelView implements } private boolean isInQsArea(float x, float y) { - return mStatusBarState != StatusBarState.SHADE || - (x >= mScrollView.getLeft() && x <= mScrollView.getRight()) && - (y <= mNotificationStackScroller.getBottomMostNotificationBottom() - || y <= mQsContainer.getY() + mQsContainer.getHeight()); + return (x >= mScrollView.getLeft() && x <= mScrollView.getRight()) && + (y <= mNotificationStackScroller.getBottomMostNotificationBottom() + || y <= mQsContainer.getY() + mQsContainer.getHeight()); } private void handleQsDown(MotionEvent event) { @@ -802,6 +809,7 @@ public class NotificationPanelView extends PanelView implements requestPanelHeightUpdate(); mNotificationStackScroller.setInterceptDelegateEnabled(expanded); mStatusBar.setQsExpanded(expanded); + mQsPanel.setExpanded(expanded); } } @@ -908,6 +916,8 @@ public class NotificationPanelView extends PanelView implements @Override public void run() { mKeyguardStatusBar.setVisibility(View.INVISIBLE); + mKeyguardStatusBar.setAlpha(1f); + mKeyguardStatusBarAnimateAlpha = 1f; } }; @@ -917,10 +927,31 @@ public class NotificationPanelView extends PanelView implements .setStartDelay(mStatusBar.getKeyguardFadingAwayDelay()) .setDuration(mStatusBar.getKeyguardFadingAwayDuration()/2) .setInterpolator(PhoneStatusBar.ALPHA_OUT) + .setUpdateListener(mStatusBarAnimateAlphaListener) .withEndAction(mAnimateKeyguardStatusBarInvisibleEndRunnable) .start(); } + private final ValueAnimator.AnimatorUpdateListener mStatusBarAnimateAlphaListener = + new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mKeyguardStatusBarAnimateAlpha = mKeyguardStatusBar.getAlpha(); + } + }; + + private void animateKeyguardStatusBarIn() { + mKeyguardStatusBar.setVisibility(View.VISIBLE); + mKeyguardStatusBar.setAlpha(0f); + mKeyguardStatusBar.animate() + .alpha(1f) + .setStartDelay(0) + .setDuration(DOZE_ANIMATION_DURATION) + .setInterpolator(mDozeAnimationInterpolator) + .setUpdateListener(mStatusBarAnimateAlphaListener) + .start(); + } + private final Runnable mAnimateKeyguardBottomAreaInvisibleEndRunnable = new Runnable() { @Override public void run() { @@ -1011,7 +1042,7 @@ public class NotificationPanelView extends PanelView implements ? View.VISIBLE : View.INVISIBLE); if (mKeyguardUserSwitcher != null && mQsExpanded && !mStackScrollerOverscrolling) { - mKeyguardUserSwitcher.hide(true /* animate */); + mKeyguardUserSwitcher.hideIfNotSimple(true /* animate */); } } @@ -1081,9 +1112,26 @@ public class NotificationPanelView extends PanelView implements } private float calculateQsTopPadding() { - // We can only do the smoother transition on Keyguard when we also are not collapsing from a - // scrolled quick settings. - if (mKeyguardShowing && mScrollYOverride == -1) { + if (mKeyguardShowing + && (mTwoFingerQsExpand || mIsExpanding && mQsExpandedWhenExpandingStarted)) { + + // Either QS pushes the notifications down when fully expanded, or QS is fully above the + // notifications (mostly on tablets). maxNotifications denotes the normal top padding + // on Keyguard, maxQs denotes the top padding from the quick settings panel. We need to + // take the maximum and linearly interpolate with the panel expansion for a nice motion. + int maxNotifications = mClockPositionResult.stackScrollerPadding + - mClockPositionResult.stackScrollerPaddingAdjustment + - mNotificationTopPadding; + int maxQs = getTempQsMaxExpansion(); + int max = mStatusBarState == StatusBarState.KEYGUARD + ? Math.max(maxNotifications, maxQs) + : maxQs; + return (int) interpolate(getExpandedFraction(), + mQsMinExpansionHeight, max); + } else if (mKeyguardShowing && mScrollYOverride == -1) { + + // We can only do the smoother transition on Keyguard when we also are not collapsing + // from a scrolled quick settings. return interpolate(getQsExpansionFraction(), mNotificationStackScroller.getIntrinsicPadding() - mNotificationTopPadding, mQsMaxExpansionHeight); @@ -1095,7 +1143,9 @@ public class NotificationPanelView extends PanelView implements private void requestScrollerTopPaddingUpdate(boolean animate) { mNotificationStackScroller.updateTopPadding(calculateQsTopPadding(), mScrollView.getScrollY(), - mAnimateNextTopPaddingChange || animate); + mAnimateNextTopPaddingChange || animate, + mKeyguardShowing + && (mTwoFingerQsExpand || mIsExpanding && mQsExpandedWhenExpandingStarted)); mAnimateNextTopPaddingChange = false; } @@ -1225,18 +1275,27 @@ public class NotificationPanelView extends PanelView implements @Override protected void onHeightUpdated(float expandedHeight) { - if (!mQsExpanded) { + if (!mQsExpanded || mTwoFingerQsExpand || mIsExpanding && mQsExpandedWhenExpandingStarted) { positionClockAndNotifications(); } if (mTwoFingerQsExpand || mQsExpanded && !mQsTracking && mQsExpansionAnimator == null && !mQsExpansionFromOverscroll) { - float panelHeightQsCollapsed = mNotificationStackScroller.getIntrinsicPadding() - + mNotificationStackScroller.getMinStackHeight() - + mNotificationStackScroller.getNotificationTopPadding(); - float panelHeightQsExpanded = calculatePanelHeightQsExpanded(); - float t = (expandedHeight - panelHeightQsCollapsed) - / (panelHeightQsExpanded - panelHeightQsCollapsed); + float t; + if (mKeyguardShowing) { + // On Keyguard, interpolate the QS expansion linearly to the panel expansion + t = expandedHeight / getMaxPanelHeight(); + } else { + + // In Shade, interpolate linearly such that QS is closed whenever panel height is + // minimum QS expansion + minStackHeight + float panelHeightQsCollapsed = mNotificationStackScroller.getIntrinsicPadding() + + mNotificationStackScroller.getMinStackHeight() + + mNotificationStackScroller.getNotificationTopPadding(); + float panelHeightQsExpanded = calculatePanelHeightQsExpanded(); + t = (expandedHeight - panelHeightQsCollapsed) + / (panelHeightQsExpanded - panelHeightQsCollapsed); + } setQsExpansion(mQsMinExpansionHeight + t * (getTempQsMaxExpansion() - mQsMinExpansionHeight)); } @@ -1270,8 +1329,10 @@ public class NotificationPanelView extends PanelView implements float notificationHeight = mNotificationStackScroller.getHeight() - mNotificationStackScroller.getEmptyBottomMargin() - mNotificationStackScroller.getTopPadding(); - float totalHeight = mQsMaxExpansionHeight + notificationHeight - + mNotificationStackScroller.getNotificationTopPadding(); + float totalHeight = Math.max( + mQsMaxExpansionHeight + mNotificationStackScroller.getNotificationTopPadding(), + mClockPositionResult.stackScrollerPadding - mTopPaddingAdjustment) + + notificationHeight; if (totalHeight > mNotificationStackScroller.getHeight()) { float fullyCollapsedHeight = mQsMaxExpansionHeight + mNotificationStackScroller.getMinStackHeight() @@ -1386,7 +1447,8 @@ public class NotificationPanelView extends PanelView implements alphaNotifications = MathUtils.constrain(alphaNotifications, 0, 1); alphaNotifications = (float) Math.pow(alphaNotifications, 0.75); float alphaQsExpansion = 1 - Math.min(1, getQsExpansionFraction() * 2); - mKeyguardStatusBar.setAlpha(Math.min(alphaNotifications, alphaQsExpansion)); + mKeyguardStatusBar.setAlpha(Math.min(alphaNotifications, alphaQsExpansion) + * mKeyguardStatusBarAnimateAlpha); mKeyguardBottomArea.setAlpha(Math.min(1 - getQsExpansionFraction(), alphaNotifications)); setQsTranslation(mQsExpansionHeight); } @@ -1403,7 +1465,7 @@ public class NotificationPanelView extends PanelView implements super.onExpandingStarted(); mNotificationStackScroller.onExpansionStarted(); mIsExpanding = true; - mQsExpandedWhenExpandingStarted = mQsExpanded; + mQsExpandedWhenExpandingStarted = mQsFullyExpanded; if (mQsExpanded) { onQsExpansionStarted(); } @@ -1457,11 +1519,12 @@ public class NotificationPanelView extends PanelView implements @Override protected void onTrackingStarted() { super.onTrackingStarted(); + if (mQsFullyExpanded) { + mTwoFingerQsExpand = true; + } if (mStatusBar.getBarState() == StatusBarState.KEYGUARD || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED) { mAfforanceHelper.animateHideLeftRightIcon(); - } else if (mQsExpanded) { - mTwoFingerQsExpand = true; } } @@ -1735,19 +1798,22 @@ public class NotificationPanelView extends PanelView implements return (1 - t) * start + t * end; } - private void updateKeyguardStatusBarVisibility() { - mKeyguardStatusBar.setVisibility(mKeyguardShowing && !mDozing ? VISIBLE : INVISIBLE); - } - - public void setDozing(boolean dozing) { + public void setDozing(boolean dozing, boolean animate) { if (dozing == mDozing) return; mDozing = dozing; if (mDozing) { - setBackgroundColorAlpha(this, DOZE_BACKGROUND_COLOR, 0xff, false /*animate*/); + setBackgroundColorAlpha(DOZE_BACKGROUND_COLOR, 0xff, false /*animate*/); + mKeyguardStatusBar.setVisibility(View.INVISIBLE); + mKeyguardBottomArea.setVisibility(View.INVISIBLE); } else { - setBackgroundColorAlpha(this, DOZE_BACKGROUND_COLOR, 0, true /*animate*/); + setBackgroundColorAlpha(DOZE_BACKGROUND_COLOR, 0, animate); + mKeyguardBottomArea.setVisibility(View.VISIBLE); + mKeyguardStatusBar.setVisibility(View.VISIBLE); + if (animate) { + animateKeyguardStatusBarIn(); + mKeyguardBottomArea.startFinishDozeAnimation(); + } } - updateKeyguardStatusBarVisibility(); } @Override @@ -1755,21 +1821,21 @@ public class NotificationPanelView extends PanelView implements return mDozing; } - private static void setBackgroundColorAlpha(final View target, int rgb, int targetAlpha, + private void setBackgroundColorAlpha(int rgb, int targetAlpha, boolean animate) { - int currentAlpha = getBackgroundAlpha(target); + int currentAlpha = getBackgroundAlpha(this); if (currentAlpha == targetAlpha) { return; } final int r = Color.red(rgb); final int g = Color.green(rgb); final int b = Color.blue(rgb); - Object runningAnim = target.getTag(TAG_KEY_ANIM); + Object runningAnim = getTag(TAG_KEY_ANIM); if (runningAnim instanceof ValueAnimator) { ((ValueAnimator) runningAnim).cancel(); } if (!animate) { - target.setBackgroundColor(Color.argb(targetAlpha, r, g, b)); + setBackgroundColor(Color.argb(targetAlpha, r, g, b)); return; } ValueAnimator anim = ValueAnimator.ofInt(currentAlpha, targetAlpha); @@ -1777,18 +1843,19 @@ public class NotificationPanelView extends PanelView implements @Override public void onAnimationUpdate(ValueAnimator animation) { int value = (int) animation.getAnimatedValue(); - target.setBackgroundColor(Color.argb(value, r, g, b)); + setBackgroundColor(Color.argb(value, r, g, b)); } }); - anim.setDuration(DOZE_BACKGROUND_ANIM_DURATION); + anim.setInterpolator(mDozeAnimationInterpolator); + anim.setDuration(DOZE_ANIMATION_DURATION); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - target.setTag(TAG_KEY_ANIM, null); + setTag(TAG_KEY_ANIM, null); } }); anim.start(); - target.setTag(TAG_KEY_ANIM, anim); + setTag(TAG_KEY_ANIM, anim); } private static int getBackgroundAlpha(View view) { @@ -1833,4 +1900,9 @@ public class NotificationPanelView extends PanelView implements public void onScreenTurnedOn() { mKeyguardStatusView.refreshTime(); } + + @Override + public void onEmptySpaceClicked(float x, float y) { + onEmptySpaceClick(x); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java index f74d2f4baf70..3efaaff21a4d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java @@ -236,4 +236,8 @@ public class PanelBar extends FrameLayout { public void onExpandingFinished() { } + + public void onClosingFinished() { + + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index a7ff0bde678b..c706ef095cfa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -68,9 +68,9 @@ public abstract class PanelView extends FrameLayout { protected int mTouchSlop; protected boolean mHintAnimationRunning; private boolean mOverExpandedBeforeFling; - private float mOriginalIndicationY; private boolean mTouchAboveFalsingThreshold; private int mUnlockFalsingThreshold; + private boolean mTouchStartedInEmptyArea; private ValueAnimator mHeightAnimator; private ObjectAnimator mPeekAnimator; @@ -107,7 +107,7 @@ public abstract class PanelView extends FrameLayout { }; protected void onExpandingFinished() { - mClosing = false; + endClosing(); mBar.onExpandingFinished(); } @@ -250,9 +250,7 @@ public abstract class PanelView extends FrameLayout { trackMovement(event); if (!waitForTouchSlop || (mHeightAnimator != null && !mHintAnimationRunning) || mPeekPending || mPeekAnimator != null) { - if (mHeightAnimator != null) { - mHeightAnimator.cancel(); // end any outstanding animations - } + cancelHeightAnimator(); cancelPeek(); mTouchSlopExceeded = (mHeightAnimator != null && !mHintAnimationRunning) || mPeekPending || mPeekAnimator != null; @@ -287,15 +285,13 @@ public abstract class PanelView extends FrameLayout { || mInitialOffsetOnTouch == 0f)) { mTouchSlopExceeded = true; if (waitForTouchSlop && !mTracking) { - if (!mJustPeeked) { + if (!mJustPeeked && mInitialOffsetOnTouch != 0f) { mInitialOffsetOnTouch = mExpandedHeight; mInitialTouchX = x; mInitialTouchY = y; h = 0; } - if (mHeightAnimator != null) { - mHeightAnimator.cancel(); // end any outstanding animations - } + cancelHeightAnimator(); removeCallbacks(mPeekRunnable); mPeekPending = false; onTrackingStarted(); @@ -372,7 +368,7 @@ public abstract class PanelView extends FrameLayout { } protected void onTrackingStarted() { - mClosing = false; + endClosing(); mTracking = true; mCollapseAfterPeek = false; mBar.onTrackingStarted(PanelView.this); @@ -407,15 +403,14 @@ public abstract class PanelView extends FrameLayout { mStatusBar.userActivity(); if (mHeightAnimator != null && !mHintAnimationRunning || mPeekPending || mPeekAnimator != null) { - if (mHeightAnimator != null) { - mHeightAnimator.cancel(); // end any outstanding animations - } + cancelHeightAnimator(); cancelPeek(); mTouchSlopExceeded = true; return true; } mInitialTouchY = y; mInitialTouchX = x; + mTouchStartedInEmptyArea = !isInContentBounds(x, y); mTouchSlopExceeded = false; mJustPeeked = false; mPanelClosedOnDown = mExpandedHeight == 0.0f; @@ -439,11 +434,9 @@ public abstract class PanelView extends FrameLayout { case MotionEvent.ACTION_MOVE: final float h = y - mInitialTouchY; trackMovement(event); - if (scrolledToBottom) { + if (scrolledToBottom || mTouchStartedInEmptyArea) { if (h < -mTouchSlop && h < -Math.abs(x - mInitialTouchX)) { - if (mHeightAnimator != null) { - mHeightAnimator.cancel(); - } + cancelHeightAnimator(); mInitialOffsetOnTouch = mExpandedHeight; mInitialTouchY = y; mInitialTouchX = x; @@ -461,6 +454,25 @@ public abstract class PanelView extends FrameLayout { return false; } + /** + * @return Whether a pair of coordinates are inside the visible view content bounds. + */ + protected abstract boolean isInContentBounds(float x, float y); + + private void cancelHeightAnimator() { + if (mHeightAnimator != null) { + mHeightAnimator.cancel(); + } + endClosing(); + } + + private void endClosing() { + if (mClosing) { + mClosing = false; + onClosingFinished(); + } + } + private void initVelocityTracker() { if (mVelocityTracker != null) { mVelocityTracker.recycle(); @@ -627,10 +639,10 @@ public abstract class PanelView extends FrameLayout { } mExpandedHeight = Math.max(0, mExpandedHeight); - onHeightUpdated(mExpandedHeight); mExpandedFraction = Math.min(1f, fhWithoutOverExpansion == 0 ? 0 : mExpandedHeight / fhWithoutOverExpansion); + onHeightUpdated(mExpandedHeight); notifyBarPanelExpansionChanged(); } @@ -700,9 +712,7 @@ public abstract class PanelView extends FrameLayout { mPeekRunnable.run(); } } else if (!isFullyCollapsed() && !mTracking && !mClosing) { - if (mHeightAnimator != null) { - mHeightAnimator.cancel(); - } + cancelHeightAnimator(); mClosing = true; notifyExpandingStarted(); if (delayed) { @@ -785,13 +795,16 @@ public abstract class PanelView extends FrameLayout { private void abortAnimations() { cancelPeek(); - if (mHeightAnimator != null) { - mHeightAnimator.cancel(); - } + cancelHeightAnimator(); removeCallbacks(mPostCollapseRunnable); removeCallbacks(mFlingCollapseRunnable); } + protected void onClosingFinished() { + mBar.onClosingFinished(); + } + + protected void startUnlockHintAnimation() { // We don't need to hint the user if an animation is already running or the user is changing @@ -841,16 +854,15 @@ public abstract class PanelView extends FrameLayout { }); animator.start(); mHeightAnimator = animator; - mOriginalIndicationY = mKeyguardBottomArea.getIndicationView().getY(); mKeyguardBottomArea.getIndicationView().animate() - .y(mOriginalIndicationY - mHintDistance) + .translationY(-mHintDistance) .setDuration(250) .setInterpolator(mFastOutSlowInInterpolator) .withEndAction(new Runnable() { @Override public void run() { mKeyguardBottomArea.getIndicationView().animate() - .y(mOriginalIndicationY) + .translationY(0) .setDuration(450) .setInterpolator(mBounceInterpolator) .start(); @@ -898,7 +910,7 @@ public abstract class PanelView extends FrameLayout { * * @return whether the panel will be expanded after the action performed by this method */ - private boolean onEmptySpaceClick(float x) { + protected boolean onEmptySpaceClick(float x) { if (mHintAnimationRunning) { return true; } 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 9e3f0f67f532..eb487547f967 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -40,6 +40,7 @@ import android.app.Notification; import android.app.PendingIntent; import android.app.StatusBarManager; import android.content.BroadcastReceiver; +import android.content.ComponentCallbacks2; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -95,6 +96,7 @@ import android.view.ViewPropertyAnimator; import android.view.ViewStub; import android.view.ViewTreeObserver; import android.view.WindowManager; +import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.animation.AccelerateDecelerateInterpolator; @@ -173,6 +175,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; public class PhoneStatusBar extends BaseStatusBar implements DemoMode, DragDownHelper.DragDownCallback, ActivityStarter { @@ -581,7 +584,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, addNavigationBar(); // Lastly, call to the icon policy to install/update all the icons. - mIconPolicy = new PhoneStatusBarPolicy(mContext, mCastController); + mIconPolicy = new PhoneStatusBarPolicy(mContext, mCastController, mHotspotController); mSettingsObserver.onChange(false); // set up mHeadsUpObserver.onChange(true); // set up @@ -798,7 +801,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } mUserInfoController = new UserInfoController(mContext); mVolumeComponent = getComponent(VolumeComponent.class); - mZenModeController = mVolumeComponent.getZenController(); + if (mVolumeComponent != null) { + mZenModeController = mVolumeComponent.getZenController(); + } mCastController = new CastControllerImpl(mContext); final SignalClusterView signalCluster = (SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster); @@ -2413,6 +2418,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false); showBouncer(); disable(mDisabledUnmodified, true /* animate */); + + // Trimming will happen later if Keyguard is showing - doing it here might cause a jank in + // the bouncer appear animation. + if (!mStatusBarKeyguardViewManager.isShowing()) { + WindowManagerGlobal.getInstance().trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); + } } public boolean interceptTouchEvent(MotionEvent event) { @@ -2955,6 +2966,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mSecurityController != null) { mSecurityController.dump(fd, pw, args); } + pw.println("SharedPreferences:"); + for (Map.Entry<String, ?> entry : mContext.getSharedPreferences(mContext.getPackageName(), + Context.MODE_PRIVATE).getAll().entrySet()) { + pw.print(" "); pw.print(entry.getKey()); pw.print("="); pw.println(entry.getValue()); + } } private String hunStateToString(Entry entry) { @@ -3036,7 +3052,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } }); if (dismissShade) { - animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */); + animateCollapsePanels( + CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */); } return true; } @@ -3664,15 +3681,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mState != StatusBarState.KEYGUARD && !mNotificationPanel.isDozing()) { return; } - mNotificationPanel.setDozing(mDozing); + mNotificationPanel.setDozing(mDozing, mScrimController.isPulsing() /*animate*/); if (mDozing) { - mKeyguardBottomArea.setVisibility(View.INVISIBLE); mStackScroller.setDark(true, false /*animate*/); } else { - mKeyguardBottomArea.setVisibility(View.VISIBLE); mStackScroller.setDark(false, false /*animate*/); } - mScrimController.setDozing(mDozing); + mScrimController.setDozing(mDozing, mScrimController.isPulsing() /*animate*/); } public void updateStackScrollerState(boolean goingToFullShade) { @@ -3725,7 +3740,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, public boolean onSpacePressed() { if (mScreenOn != null && mScreenOn && (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)) { - animateCollapsePanels(0 /* flags */, true /* force */); + animateCollapsePanels( + CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */); return true; } return false; @@ -3779,6 +3795,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, runPostCollapseRunnables(); } + public void onClosingFinished() { + runPostCollapseRunnables(); + } + public void onUnlockHintStarted() { mKeyguardIndicationController.showTransientIndication(R.string.keyguard_unlock); } 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 47e1ab5193cd..60d23cebe970 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -35,6 +35,7 @@ import com.android.internal.telephony.TelephonyIntents; import com.android.systemui.R; import com.android.systemui.statusbar.policy.CastController; import com.android.systemui.statusbar.policy.CastController.CastDevice; +import com.android.systemui.statusbar.policy.HotspotController; /** * This class contains all of the policy about which icons are installed in the status @@ -49,6 +50,7 @@ public class PhoneStatusBarPolicy { private static final String SLOT_SYNC_ACTIVE = "sync_active"; private static final String SLOT_CAST = "cast"; + private static final String SLOT_HOTSPOT = "hotspot"; private static final String SLOT_BLUETOOTH = "bluetooth"; private static final String SLOT_TTY = "tty"; private static final String SLOT_ZEN = "zen"; @@ -60,6 +62,7 @@ public class PhoneStatusBarPolicy { private final StatusBarManager mService; private final Handler mHandler = new Handler(); private final CastController mCast; + private final HotspotController mHotspot; // Assume it's all good unless we hear otherwise. We don't always seem // to get broadcasts that it *is* there. @@ -102,9 +105,10 @@ public class PhoneStatusBarPolicy { } }; - public PhoneStatusBarPolicy(Context context, CastController cast) { + public PhoneStatusBarPolicy(Context context, CastController cast, HotspotController hotspot) { mContext = context; mCast = cast; + mHotspot = hotspot; mService = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE); // listen for broadcasts @@ -152,6 +156,11 @@ public class PhoneStatusBarPolicy { mService.setIcon(SLOT_CAST, R.drawable.stat_sys_cast, 0, null); mService.setIconVisibility(SLOT_CAST, false); mCast.addCallback(mCastCallback); + + // hotspot + mService.setIcon(SLOT_HOTSPOT, R.drawable.stat_sys_hotspot, 0, null); + mService.setIconVisibility(SLOT_HOTSPOT, mHotspot.isHotspotEnabled()); + mHotspot.addCallback(mHotspotCallback); } public void setZenMode(int zen) { @@ -300,6 +309,13 @@ public class PhoneStatusBarPolicy { mService.setIconVisibility(SLOT_CAST, isCasting); } + private final HotspotController.Callback mHotspotCallback = new HotspotController.Callback() { + @Override + public void onHotspotChanged(boolean enabled) { + mService.setIconVisibility(SLOT_HOTSPOT, enabled); + } + }; + private final CastController.Callback mCastCallback = new CastController.Callback() { @Override public void onCastDevicesChanged() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index 6411fb84ccd2..e4eae38fcdcd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -20,7 +20,6 @@ import android.content.Context; import android.content.res.Resources; import android.util.AttributeSet; import android.util.EventLog; -import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.accessibility.AccessibilityEvent; @@ -152,6 +151,12 @@ public class PhoneStatusBarView extends PanelBar { } @Override + public void onClosingFinished() { + super.onClosingFinished(); + mBar.onClosingFinished(); + } + + @Override public void onTrackingStopped(PanelView panel, boolean expand) { super.onTrackingStopped(panel, expand); mBar.onTrackingStopped(expand); 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 2dc08d48efbc..a4db46a0b567 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java @@ -120,6 +120,7 @@ public class QSTileHost implements QSTile.Host { tile.userSwitch(newUserId); } mSecurity.onUserSwitched(newUserId); + mNetwork.onUserSwitched(newUserId); mObserver.register(); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 54adbf482589..10d65943b9f4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -28,6 +28,7 @@ import android.view.ViewTreeObserver; import android.view.animation.AnimationUtils; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; +import android.view.animation.PathInterpolator; import com.android.systemui.R; import com.android.systemui.doze.DozeHost; @@ -70,9 +71,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { private Runnable mOnAnimationFinished; private boolean mAnimationStarted; private boolean mDozing; + private boolean mPulsingOut; private DozeHost.PulseCallback mPulseCallback; private final Interpolator mInterpolator = new DecelerateInterpolator(); private final Interpolator mLinearOutSlowInInterpolator; + private final Interpolator mPulseInInterpolator = PhoneStatusBar.ALPHA_OUT; + private final Interpolator mPulseOutInterpolator = PhoneStatusBar.ALPHA_IN; private BackDropView mBackDropView; private boolean mScrimSrcEnabled; @@ -130,14 +134,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { scheduleUpdate(); } - public void setDozing(boolean dozing) { + public void setDozing(boolean dozing, boolean animate) { if (mDozing == dozing) return; mDozing = dozing; if (!mDozing) { cancelPulsing(); - mAnimateChange = true; - } else { - mAnimateChange = false; + mAnimateChange = animate; } scheduleUpdate(); } @@ -181,6 +183,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { } private void pulseFinished() { + mPulsingOut = false; if (mPulseCallback != null) { mPulseCallback.onPulseFinished(); mPulseCallback = null; @@ -220,8 +223,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { } else if (mBouncerShowing) { setScrimInFrontColor(SCRIM_IN_FRONT_ALPHA); setScrimBehindColor(0f); + } else if (mDozing && isPulsing() && !mPulsingOut) { + setScrimInFrontColor(0); + setScrimBehindColor(SCRIM_BEHIND_ALPHA_KEYGUARD); } else if (mDozing) { setScrimInFrontColor(1); + setScrimBehindColor(SCRIM_BEHIND_ALPHA_KEYGUARD); } else { float fraction = Math.max(0, Math.min(mFraction, 1)); setScrimInFrontColor(0f); @@ -276,7 +283,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { private void startScrimAnimation(final ScrimView scrim, int targetColor) { int current = Color.alpha(scrim.getScrimColor()); int target = Color.alpha(targetColor); - if (current == targetColor) { + if (current == target) { return; } ValueAnimator anim = ValueAnimator.ofInt(current, target); @@ -287,9 +294,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { scrim.setScrimColor(Color.argb(value, 0, 0, 0)); } }); - anim.setInterpolator(mAnimateKeyguardFadingOut - ? mLinearOutSlowInInterpolator - : mInterpolator); + anim.setInterpolator(getInterpolator()); anim.setStartDelay(mAnimationDelay); anim.setDuration(mDurationOverride != -1 ? mDurationOverride : ANIMATION_DURATION); anim.addListener(new AnimatorListenerAdapter() { @@ -307,6 +312,18 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { mAnimationStarted = true; } + private Interpolator getInterpolator() { + if (mAnimateKeyguardFadingOut) { + return mLinearOutSlowInInterpolator; + } else if (isPulsing() && !mPulsingOut) { + return mPulseInInterpolator; + } else if (isPulsing()) { + return mPulseOutInterpolator; + } else { + return mInterpolator; + } + } + @Override public boolean onPreDraw() { mScrimBehind.getViewTreeObserver().removeOnPreDrawListener(this); @@ -332,10 +349,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { if (!mDozing) return; DozeLog.tracePulseStart(); mDurationOverride = mDozeParameters.getPulseInDuration(); - mAnimationDelay = 0; + mAnimationDelay = mDozeParameters.getPulseInDelay(); mAnimateChange = true; mOnAnimationFinished = mPulseInFinished; - setScrimColor(mScrimInFront, 0); + scheduleUpdate(); // Signal that the pulse is ready to turn the screen on and draw. pulseStarted(); @@ -357,10 +374,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { if (DEBUG) Log.d(TAG, "Pulse out, mDozing=" + mDozing); if (!mDozing) return; mDurationOverride = mDozeParameters.getPulseOutDuration(); - mAnimationDelay = 0; mAnimateChange = true; mOnAnimationFinished = mPulseOutFinished; - setScrimColor(mScrimInFront, 1); + mPulsingOut = true; + scheduleUpdate(); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java index b0f3ea1ec48d..247252cfcc48 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java @@ -48,6 +48,8 @@ import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.UserInfoController; +import java.text.NumberFormat; + /** * The view to manage the header area in the expanded status bar. */ @@ -300,9 +302,6 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL updateSystemIconsLayoutParams(); updateClickTargets(); updateMultiUserSwitch(); - if (mQSPanel != null) { - mQSPanel.setExpanded(mExpanded); - } updateClockScale(); updateAvatarScale(); updateClockLp(); @@ -395,7 +394,8 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL @Override public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { - mBatteryLevel.setText(getResources().getString(R.string.battery_level_template, level)); + String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0); + mBatteryLevel.setText(percentage); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 55c861a66ace..65d231e89437 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.phone; +import android.content.ComponentCallbacks2; import android.content.Context; import android.os.Bundle; import android.os.RemoteException; @@ -24,6 +25,7 @@ import android.util.Slog; import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; +import android.view.WindowManagerGlobal; import com.android.internal.policy.IKeyguardShowCallback; import com.android.internal.widget.LockPatternUtils; @@ -268,6 +270,8 @@ public class StatusBarKeyguardViewManager { public void run() { mStatusBarWindowManager.setKeyguardFadingAway(false); mPhoneStatusBar.finishKeyguardFadingAway(); + WindowManagerGlobal.getInstance().trimMemory( + ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); } }); } else { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrustDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrustDrawable.java index dcda2c717deb..b89aa8fa936b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrustDrawable.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrustDrawable.java @@ -133,6 +133,7 @@ public class TrustDrawable extends Drawable { if (!mAnimating) { mAnimating = true; updateState(true); + invalidateSelf(); } } @@ -146,18 +147,21 @@ public class TrustDrawable extends Drawable { mState = STATE_UNSET; mCurAlpha = 0; mCurInnerRadius = mInnerRadiusEnter; + invalidateSelf(); } } public void setTrustManaged(boolean trustManaged) { if (trustManaged == mTrustManaged && mState != STATE_UNSET) return; mTrustManaged = trustManaged; - if (mAnimating) { - updateState(true); - } + updateState(true); } - private void updateState(boolean animate) { + private void updateState(boolean allowTransientState) { + if (!mAnimating) { + return; + } + int nextState = mState; if (mState == STATE_UNSET) { nextState = mTrustManaged ? STATE_ENTERING : STATE_GONE; @@ -170,7 +174,7 @@ public class TrustDrawable extends Drawable { } else if (mState == STATE_EXITING) { if (mTrustManaged) nextState = STATE_ENTERING; } - if (!animate) { + if (!allowTransientState) { if (nextState == STATE_ENTERING) nextState = STATE_VISIBLE; if (nextState == STATE_EXITING) nextState = STATE_GONE; } @@ -200,9 +204,8 @@ public class TrustDrawable extends Drawable { mState = nextState; if (mCurAnimator != null) { mCurAnimator.start(); - } else { - invalidateSelf(); } + invalidateSelf(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiAccessPointController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointController.java index b800fbfb804f..0a385d72666b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiAccessPointController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointController.java @@ -16,15 +16,20 @@ 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.wifi.ScanResult; import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiConfiguration.KeyMgmt; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.wifi.WifiManager.ActionListener; +import android.os.UserHandle; +import android.os.UserManager; +import android.provider.Settings; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -39,9 +44,13 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; -public class WifiAccessPointController { - private static final String TAG = "WifiAccessPointController"; - private static final boolean DEBUG = false; +public class AccessPointController { + private static final String TAG = "AccessPointController"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + // This string extra specifies a network to open the connect dialog on, so the user can enter + // network credentials. This is used by quick settings for secured networks. + private static final String EXTRA_START_CONNECT_SSID = "wifi_start_connect_ssid"; private static final int[] ICONS = { R.drawable.ic_qs_wifi_0, @@ -54,13 +63,26 @@ public class WifiAccessPointController { private final Context mContext; private final ArrayList<AccessPointCallback> mCallbacks = new ArrayList<AccessPointCallback>(); private final WifiManager mWifiManager; + private final UserManager mUserManager; private final Receiver mReceiver = new Receiver(); private boolean mScanning; + private int mCurrentUser; - public WifiAccessPointController(Context context) { + public AccessPointController(Context context) { mContext = context; mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); + mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + mCurrentUser = ActivityManager.getCurrentUser(); + } + + public boolean canConfigWifi() { + return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, + new UserHandle(mCurrentUser)); + } + + void onUserSwitched(int newUserId) { + mCurrentUser = newUserId; } public void addCallback(AccessPointCallback callback) { @@ -81,22 +103,31 @@ public class WifiAccessPointController { if (mScanning) return; if (DEBUG) Log.d(TAG, "scan!"); mScanning = mWifiManager.startScan(); + // Grab current networks immediately while we wait for scan. + updateAccessPoints(); } - public void connect(AccessPoint ap) { - if (ap == null || ap.networkId < 0) return; + public boolean connect(AccessPoint ap) { + if (ap == null) return false; if (DEBUG) Log.d(TAG, "connect networkId=" + ap.networkId); - mWifiManager.connect(ap.networkId, new ActionListener() { - @Override - public void onSuccess() { - if (DEBUG) Log.d(TAG, "connect success"); - } - - @Override - public void onFailure(int reason) { - if (DEBUG) Log.d(TAG, "connect failure reason=" + reason); + if (ap.networkId < 0) { + // Unknown network, need to add it. + if (ap.hasSecurity) { + Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS); + intent.putExtra(EXTRA_START_CONNECT_SSID, ap.ssid); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + return true; + } else { + WifiConfiguration config = new WifiConfiguration(); + config.SSID = "\"" + ap.ssid + "\""; + config.allowedKeyManagement.set(KeyMgmt.NONE); + mWifiManager.connect(config, mConnectListener); } - }); + } else { + mWifiManager.connect(ap.networkId, mConnectListener); + } + return false; } private void fireCallback(AccessPoint[] aps) { @@ -139,23 +170,40 @@ public class WifiAccessPointController { } final String ssid = scanResult.SSID; if (TextUtils.isEmpty(ssid) || ssids.contains(ssid)) continue; - if (!configured.containsKey(ssid)) continue; ssids.add(ssid); final WifiConfiguration config = configured.get(ssid); final int level = WifiManager.calculateSignalLevel(scanResult.level, ICONS.length); final AccessPoint ap = new AccessPoint(); + ap.isConfigured = config != null; ap.networkId = config != null ? config.networkId : AccessPoint.NO_NETWORK; ap.ssid = ssid; ap.iconId = ICONS[level]; ap.isConnected = ap.networkId != AccessPoint.NO_NETWORK && ap.networkId == connectedNetworkId; ap.level = level; + // Based on Settings AccessPoint#getSecurity, keep up to date + // with better methods of determining no security or not. + ap.hasSecurity = scanResult.capabilities.contains("WEP") + || scanResult.capabilities.contains("PSK") + || scanResult.capabilities.contains("EAP"); aps.add(ap); } Collections.sort(aps, mByStrength); fireCallback(aps.toArray(new AccessPoint[aps.size()])); } + private final ActionListener mConnectListener = new ActionListener() { + @Override + public void onSuccess() { + if (DEBUG) Log.d(TAG, "connect success"); + } + + @Override + public void onFailure(int reason) { + if (DEBUG) Log.d(TAG, "connect failure reason=" + reason); + } + }; + private final Comparator<AccessPoint> mByStrength = new Comparator<AccessPoint> () { @Override public int compare(AccessPoint lhs, AccessPoint rhs) { @@ -163,7 +211,7 @@ public class WifiAccessPointController { } private int score(AccessPoint ap) { - return ap.level + (ap.isConnected ? 10 : 0); + return ap.level + (ap.isConnected ? 20 : 0) + (ap.isConfigured ? 10 : 0); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java index 6f021aca15f1..33f7affe892f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java @@ -308,7 +308,11 @@ public class FlashlightController { new CameraCaptureSession.StateListener() { @Override public void onConfigured(CameraCaptureSession session) { - mSession = session; + if (session.getDevice() == mCameraDevice) { + mSession = session; + } else { + session.close(); + } postUpdateFlashlight(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java index a3765aa9a8fe..6998791c72ad 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java @@ -102,7 +102,6 @@ public class KeyButtonRipple extends Drawable { } } - @Override public void draw(Canvas canvas) { mSupportHardware = canvas.isHardwareAccelerated(); @@ -176,6 +175,11 @@ public class KeyButtonRipple extends Drawable { } @Override + public void jumpToCurrentState() { + cancelAnimations(); + } + + @Override public boolean isStateful() { return true; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java index 7cc75da1db53..b9cc0f94ee9e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java @@ -17,38 +17,27 @@ package com.android.systemui.statusbar.policy; import android.animation.Animator; -import android.animation.AnimatorSet; import android.animation.ObjectAnimator; -import android.animation.TimeInterpolator; import android.app.ActivityManager; import android.content.Context; import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.CanvasProperty; -import android.graphics.Paint; -import android.graphics.RectF; import android.hardware.input.InputManager; import android.media.AudioManager; import android.os.Bundle; import android.os.SystemClock; import android.util.AttributeSet; import android.util.Log; -import android.util.MathUtils; import android.view.HapticFeedbackConstants; -import android.view.HardwareCanvas; import android.view.InputDevice; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.MotionEvent; -import android.view.RenderNodeAnimator; import android.view.SoundEffectConstants; import android.view.View; import android.view.ViewConfiguration; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.ImageView; -import java.lang.Math; -import java.util.ArrayList; import com.android.systemui.R; @@ -124,6 +113,14 @@ public class KeyButtonView extends ImageView { } @Override + protected void onWindowVisibilityChanged(int visibility) { + super.onWindowVisibilityChanged(visibility); + if (visibility != View.VISIBLE) { + jumpDrawablesToCurrentState(); + } + } + + @Override public boolean performAccessibilityAction(int action, Bundle arguments) { if (action == ACTION_CLICK && mCode != 0) { sendEvent(KeyEvent.ACTION_DOWN, 0, SystemClock.uptimeMillis()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java index 8f0000fd4d88..297ff7095850 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java @@ -19,15 +19,16 @@ package com.android.systemui.statusbar.policy; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; -import android.animation.ValueAnimator; import android.content.Context; import android.database.DataSetObserver; +import android.util.AttributeSet; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewStub; import android.view.animation.AnimationUtils; -import android.widget.TextView; +import android.widget.FrameLayout; import com.android.keyguard.AppearAnimationUtils; import com.android.systemui.R; @@ -35,8 +36,6 @@ import com.android.systemui.qs.tiles.UserDetailItemView; import com.android.systemui.statusbar.phone.KeyguardStatusBarView; import com.android.systemui.statusbar.phone.NotificationPanelView; import com.android.systemui.statusbar.phone.PhoneStatusBar; -import com.android.systemui.statusbar.phone.StatusBarHeaderView; -import com.android.systemui.statusbar.phone.UserAvatarView; /** * Manages the user switcher on the Keyguard. @@ -46,6 +45,7 @@ public class KeyguardUserSwitcher { private static final String TAG = "KeyguardUserSwitcher"; private static final boolean ALWAYS_ON = false; + private final Container mUserSwitcherContainer; private final ViewGroup mUserSwitcher; private final KeyguardStatusBarView mStatusBarView; private final Adapter mAdapter; @@ -53,24 +53,29 @@ public class KeyguardUserSwitcher { private final KeyguardUserSwitcherScrim mBackground; private ObjectAnimator mBgAnimator; private UserSwitcherController mUserSwitcherController; + private boolean mAnimating; public KeyguardUserSwitcher(Context context, ViewStub userSwitcher, KeyguardStatusBarView statusBarView, NotificationPanelView panelView, UserSwitcherController userSwitcherController) { if (context.getResources().getBoolean(R.bool.config_keyguardUserSwitcher) || ALWAYS_ON) { - mUserSwitcher = (ViewGroup) userSwitcher.inflate(); + mUserSwitcherContainer = (Container) userSwitcher.inflate(); + mUserSwitcher = (ViewGroup) + mUserSwitcherContainer.findViewById(R.id.keyguard_user_switcher_inner); mBackground = new KeyguardUserSwitcherScrim(mUserSwitcher); mUserSwitcher.setBackground(mBackground); mStatusBarView = statusBarView; mStatusBarView.setKeyguardUserSwitcher(this); panelView.setKeyguardUserSwitcher(this); - mAdapter = new Adapter(context, userSwitcherController); + mAdapter = new Adapter(context, userSwitcherController, this); mAdapter.registerDataSetObserver(mDataSetObserver); mUserSwitcherController = userSwitcherController; mAppearAnimationUtils = new AppearAnimationUtils(context, 400, -0.5f, 0.5f, AnimationUtils.loadInterpolator( context, android.R.interpolator.fast_out_slow_in)); + mUserSwitcherContainer.setKeyguardUserSwitcher(this); } else { + mUserSwitcherContainer = null; mUserSwitcher = null; mStatusBarView = null; mAdapter = null; @@ -98,9 +103,9 @@ public class KeyguardUserSwitcher { } public void show(boolean animate) { - if (mUserSwitcher != null && mUserSwitcher.getVisibility() != View.VISIBLE) { + if (mUserSwitcher != null && mUserSwitcherContainer.getVisibility() != View.VISIBLE) { cancelAnimations(); - mUserSwitcher.setVisibility(View.VISIBLE); + mUserSwitcherContainer.setVisibility(View.VISIBLE); mStatusBarView.setKeyguardUserSwitcherShowing(true, animate); if (animate) { startAppearAnimation(); @@ -108,13 +113,13 @@ public class KeyguardUserSwitcher { } } - public void hide(boolean animate) { - if (mUserSwitcher != null && mUserSwitcher.getVisibility() == View.VISIBLE) { + private void hide(boolean animate) { + if (mUserSwitcher != null && mUserSwitcherContainer.getVisibility() == View.VISIBLE) { cancelAnimations(); if (animate) { startDisappearAnimation(); } else { - mUserSwitcher.setVisibility(View.GONE); + mUserSwitcherContainer.setVisibility(View.GONE); } mStatusBarView.setKeyguardUserSwitcherShowing(false, animate); } @@ -129,6 +134,7 @@ public class KeyguardUserSwitcher { mBgAnimator.cancel(); } mUserSwitcher.animate().cancel(); + mAnimating = false; } private void startAppearAnimation() { @@ -146,6 +152,7 @@ public class KeyguardUserSwitcher { mUserSwitcher.setClipToPadding(true); } }); + mAnimating = true; mBgAnimator = ObjectAnimator.ofInt(mBackground, "alpha", 0, 255); mBgAnimator.setDuration(400); mBgAnimator.setInterpolator(PhoneStatusBar.ALPHA_IN); @@ -153,12 +160,14 @@ public class KeyguardUserSwitcher { @Override public void onAnimationEnd(Animator animation) { mBgAnimator = null; + mAnimating = false; } }); mBgAnimator.start(); } private void startDisappearAnimation() { + mAnimating = true; mUserSwitcher.animate() .alpha(0f) .setDuration(300) @@ -166,8 +175,9 @@ public class KeyguardUserSwitcher { .withEndAction(new Runnable() { @Override public void run() { - mUserSwitcher.setVisibility(View.GONE); + mUserSwitcherContainer.setVisibility(View.GONE); mUserSwitcher.setAlpha(1f); + mAnimating = false; } }); } @@ -198,6 +208,16 @@ public class KeyguardUserSwitcher { } } + public void hideIfNotSimple(boolean animate) { + if (mUserSwitcherContainer != null && !mUserSwitcherController.isSimpleUserSwitcher()) { + hide(animate); + } + } + + boolean isAnimating() { + return mAnimating; + } + public final DataSetObserver mDataSetObserver = new DataSetObserver() { @Override public void onChanged() { @@ -209,10 +229,13 @@ public class KeyguardUserSwitcher { View.OnClickListener { private Context mContext; + private KeyguardUserSwitcher mKeyguardUserSwitcher; - public Adapter(Context context, UserSwitcherController controller) { + public Adapter(Context context, UserSwitcherController controller, + KeyguardUserSwitcher kgu) { super(controller); mContext = context; + mKeyguardUserSwitcher = kgu; } @Override @@ -240,7 +263,37 @@ public class KeyguardUserSwitcher { @Override public void onClick(View v) { - switchTo(((UserSwitcherController.UserRecord)v.getTag())); + UserSwitcherController.UserRecord user = (UserSwitcherController.UserRecord) v.getTag(); + if (user.isCurrent && !user.isGuest) { + // Close the switcher if tapping the current user. Guest is excluded because + // tapping the guest user while it's current clears the session. + mKeyguardUserSwitcher.hideIfNotSimple(true /* animate */); + } else { + switchTo(user); + } + } + } + + public static class Container extends FrameLayout { + + private KeyguardUserSwitcher mKeyguardUserSwitcher; + + public Container(Context context, AttributeSet attrs) { + super(context, attrs); + setClipChildren(false); + } + + public void setKeyguardUserSwitcher(KeyguardUserSwitcher keyguardUserSwitcher) { + mKeyguardUserSwitcher = keyguardUserSwitcher; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + // Hide switcher if it didn't handle the touch event (and let the event go through). + if (mKeyguardUserSwitcher != null && !mKeyguardUserSwitcher.isAnimating()) { + mKeyguardUserSwitcher.hideIfNotSimple(true /* animate */); + } + return false; } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java index 43630375633f..a5fc2fe8ce31 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java @@ -42,7 +42,7 @@ public class KeyguardUserSwitcherScrim extends Drawable private int mDarkColor; private int mTop; - private int mAlpha; + private int mAlpha = 255; private Paint mRadialGradientPaint = new Paint(); private int mLayoutWidth; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index 2ed9366ff0e1..bb29d01e2557 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -39,11 +39,13 @@ public interface NetworkController { void addAccessPointCallback(AccessPointCallback callback); void removeAccessPointCallback(AccessPointCallback callback); void scanForAccessPoints(); - void connect(AccessPoint ap); + boolean connect(AccessPoint ap); boolean isMobileDataSupported(); boolean isMobileDataEnabled(); void setMobileDataEnabled(boolean enabled); DataUsageInfo getDataUsageInfo(); + boolean canConfigWifi(); + void onUserSwitched(int newUserId); public interface AccessPointCallback { void onAccessPointsChanged(AccessPoint[] accessPoints); @@ -56,6 +58,8 @@ public interface NetworkController { public int iconId; public String ssid; public boolean isConnected; + public boolean isConfigured; + public boolean hasSecurity; public int level; // 0 - 5 } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index 36259979b13e..6c0b425ab361 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -164,12 +164,11 @@ public class NetworkControllerImpl extends BroadcastReceiver public interface SignalCluster { void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription); void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon, - String contentDescription, String typeContentDescription, boolean roaming, - boolean isTypeIconWide); + String contentDescription, String typeContentDescription, boolean isTypeIconWide); void setIsAirplaneMode(boolean is, int airplaneIcon); } - private final WifiAccessPointController mAccessPoints; + private final AccessPointController mAccessPoints; private final MobileDataController mMobileDataController; /** @@ -240,7 +239,7 @@ public class NetworkControllerImpl extends BroadcastReceiver updateAirplaneMode(); mLastLocale = mContext.getResources().getConfiguration().locale; - mAccessPoints = new WifiAccessPointController(mContext); + mAccessPoints = new AccessPointController(mContext); mMobileDataController = new MobileDataController(mContext); mMobileDataController.setCallback(new MobileDataController.Callback() { @Override @@ -250,6 +249,16 @@ public class NetworkControllerImpl extends BroadcastReceiver }); } + @Override + public boolean canConfigWifi() { + return mAccessPoints.canConfigWifi(); + } + + @Override + public void onUserSwitched(int newUserId) { + mAccessPoints.onUserSwitched(newUserId); + } + private void notifyMobileDataEnabled(boolean enabled) { for (NetworkSignalChangedCallback cb : mSignalsChangedCallbacks) { cb.onMobileDataEnabled(enabled); @@ -314,8 +323,8 @@ public class NetworkControllerImpl extends BroadcastReceiver } @Override - public void connect(AccessPoint ap) { - mAccessPoints.connect(ap); + public boolean connect(AccessPoint ap) { + return mAccessPoints.connect(ap); } @Override @@ -386,7 +395,6 @@ public class NetworkControllerImpl extends BroadcastReceiver mDataTypeIconId, mContentDescriptionWimax, mContentDescriptionDataType, - mDataTypeIconId == TelephonyIcons.ROAMING_ICON, false /* isTypeIconWide */ ); } else { // normal mobile data @@ -396,7 +404,6 @@ public class NetworkControllerImpl extends BroadcastReceiver mDataTypeIconId, mContentDescriptionPhoneSignal, mContentDescriptionDataType, - mDataTypeIconId == TelephonyIcons.ROAMING_ICON, isTypeIconWide(mDataTypeIconId)); } cluster.setIsAirplaneMode(mAirplaneMode, mAirplaneIconId); @@ -1606,7 +1613,6 @@ public class NetworkControllerImpl extends BroadcastReceiver mDemoDataTypeIconId, "Demo", "Demo", - mDemoDataTypeIconId == TelephonyIcons.ROAMING_ICON, isTypeIconWide(mDemoDataTypeIconId)); } refreshViews(); 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 4a204061144f..87ce565d5da0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -40,6 +40,7 @@ import com.android.systemui.statusbar.EmptyShadeView; import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.ExpandableView; import com.android.systemui.statusbar.SpeedBumpView; +import com.android.systemui.statusbar.StackScrollerDecorView; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.PhoneStatusBar; import com.android.systemui.statusbar.policy.ScrollAdapter; @@ -70,6 +71,12 @@ public class NotificationStackScrollLayout extends ViewGroup private SwipeHelper mSwipeHelper; private boolean mSwipingInProgress; private int mCurrentStackHeight = Integer.MAX_VALUE; + + /** + * mCurrentStackHeight is the actual stack height, mLastSetStackHeight is the stack height set + * externally from {@link #setStackHeight} + */ + private float mLastSetStackHeight; private int mOwnScrollY; private int mMaxLayoutHeight; @@ -84,6 +91,9 @@ public class NotificationStackScrollLayout extends ViewGroup private int mLastMotionY; private int mDownX; private int mActivePointerId; + private boolean mTouchIsClick; + private float mInitialTouchX; + private float mInitialTouchY; private int mSidePaddings; private Paint mDebugPaint; @@ -133,6 +143,7 @@ public class NotificationStackScrollLayout extends ViewGroup private OnChildLocationsChangedListener mListener; private OnOverscrollTopChangedListener mOverscrollTopChangedListener; private ExpandableView.OnHeightChangedListener mOnHeightChangedListener; + private OnEmptySpaceClickListener mOnEmptySpaceClickListener; private boolean mNeedsAnimation; private boolean mTopPaddingNeedsAnimation; private boolean mDimmedNeedsAnimation; @@ -367,6 +378,9 @@ public class NotificationStackScrollLayout extends ViewGroup if (childViewState == null) { return ViewState.LOCATION_UNKNOWN; } + if (childViewState.gone) { + return ViewState.LOCATION_GONE; + } return childViewState.location; } @@ -445,6 +459,7 @@ public class NotificationStackScrollLayout extends ViewGroup * @param height the new height of the stack */ public void setStackHeight(float height) { + mLastSetStackHeight = height; setIsExpanded(height > 0.0f); int newStackHeight = (int) height; int minStackHeight = getMinStackHeight(); @@ -581,7 +596,9 @@ public class NotificationStackScrollLayout extends ViewGroup final int count = getChildCount(); for (int childIdx = 0; childIdx < count; childIdx++) { ExpandableView slidingChild = (ExpandableView) getChildAt(childIdx); - if (slidingChild.getVisibility() == GONE) { + if (slidingChild.getVisibility() == GONE + || slidingChild instanceof StackScrollerDecorView + || slidingChild == mSpeedBumpView) { continue; } float childTop = slidingChild.getTranslationY(); @@ -687,6 +704,7 @@ public class NotificationStackScrollLayout extends ViewGroup transformTouchEvent(ev, this, mScrollView); return mScrollView.onTouchEvent(ev); } + handleEmptySpaceClick(ev); boolean expandWantsIt = false; if (!mSwipingInProgress && !mOnlyScrollingInThisMotion && isScrollingEnabled()) { if (isCancelOrUp) { @@ -1338,7 +1356,19 @@ public class NotificationStackScrollLayout extends ViewGroup && initialVelocity > 0; } - public void updateTopPadding(float qsHeight, int scrollY, boolean animate) { + /** + * Updates the top padding of the notifications, taking {@link #getIntrinsicPadding()} into + * account. + * + * @param qsHeight the top padding imposed by the quick settings panel + * @param scrollY how much the notifications are scrolled inside the QS/notifications scroll + * container + * @param animate whether to animate the change + * @param ignoreIntrinsicPadding if true, {@link #getIntrinsicPadding()} is ignored and + * {@code qsHeight} is the final top padding + */ + public void updateTopPadding(float qsHeight, int scrollY, boolean animate, + boolean ignoreIntrinsicPadding) { float start = qsHeight - scrollY + mNotificationTopPadding; float stackHeight = getHeight() - start; int minStackHeight = getMinStackHeight(); @@ -1346,13 +1376,13 @@ public class NotificationStackScrollLayout extends ViewGroup float overflow = minStackHeight - stackHeight; stackHeight = minStackHeight; start = getHeight() - stackHeight; - setTranslationY(overflow); mTopPaddingOverflow = overflow; } else { - setTranslationY(0); mTopPaddingOverflow = 0; } - setTopPadding(clampPadding((int) start), animate); + setTopPadding(ignoreIntrinsicPadding ? (int) start : clampPadding((int) start), + animate); + setStackHeight(mLastSetStackHeight); } public int getNotificationTopPadding() { @@ -1430,6 +1460,7 @@ public class NotificationStackScrollLayout extends ViewGroup transformTouchEvent(ev, mScrollView, this); } initDownStates(ev); + handleEmptySpaceClick(ev); boolean expandWantsIt = false; if (!mSwipingInProgress && !mOnlyScrollingInThisMotion && isScrollingEnabled()) { expandWantsIt = mExpandHelper.onInterceptTouchEvent(ev); @@ -1448,11 +1479,31 @@ public class NotificationStackScrollLayout extends ViewGroup return swipeWantsIt || scrollWantsIt || expandWantsIt || super.onInterceptTouchEvent(ev); } + private void handleEmptySpaceClick(MotionEvent ev) { + switch (ev.getActionMasked()) { + case MotionEvent.ACTION_MOVE: + if (mTouchIsClick && (Math.abs(ev.getY() - mInitialTouchY) > mTouchSlop + || Math.abs(ev.getX() - mInitialTouchX) > mTouchSlop )) { + mTouchIsClick = false; + } + break; + case MotionEvent.ACTION_UP: + if (mPhoneStatusBar.getBarState() != StatusBarState.KEYGUARD && mTouchIsClick && + isBelowLastNotification(mInitialTouchX, mInitialTouchY)) { + mOnEmptySpaceClickListener.onEmptySpaceClicked(mInitialTouchX, mInitialTouchY); + } + break; + } + } + private void initDownStates(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { mExpandedInThisMotion = false; mOnlyScrollingInThisMotion = !mScroller.isFinished(); mDisallowScrollingInThisMotion = false; + mTouchIsClick = true; + mInitialTouchX = ev.getX(); + mInitialTouchY = ev.getY(); } } @@ -1886,7 +1937,14 @@ public class NotificationStackScrollLayout extends ViewGroup * @return Whether the specified motion event is actually happening over the content. */ private boolean isInContentBounds(MotionEvent event) { - return event.getY() < getHeight() - getEmptyBottomMargin(); + return isInContentBounds(event.getY()); + } + + /** + * @return Whether a y coordinate is inside the content. + */ + public boolean isInContentBounds(float y) { + return y < getHeight() - getEmptyBottomMargin(); } private void setIsBeingDragged(boolean isDragged) { @@ -1995,6 +2053,10 @@ public class NotificationStackScrollLayout extends ViewGroup this.mOnHeightChangedListener = mOnHeightChangedListener; } + public void setOnEmptySpaceClickListener(OnEmptySpaceClickListener listener) { + mOnEmptySpaceClickListener = listener; + } + public void onChildAnimationFinished() { requestChildrenUpdate(); } @@ -2245,6 +2307,24 @@ public class NotificationStackScrollLayout extends ViewGroup } } + private boolean isBelowLastNotification(float touchX, float touchY) { + ExpandableView lastChildNotGone = (ExpandableView) getLastChildNotGone(); + if (lastChildNotGone == null) { + return touchY > mIntrinsicPadding; + } + if (lastChildNotGone != mDismissView && lastChildNotGone != mEmptyShadeView) { + return touchY > lastChildNotGone.getY() + lastChildNotGone.getActualHeight(); + } else if (lastChildNotGone == mEmptyShadeView) { + return touchY > mEmptyShadeView.getY(); + } else { + float dismissY = mDismissView.getY(); + boolean belowDismissView = touchY > dismissY + mDismissView.getActualHeight(); + return belowDismissView || (touchY > dismissY + && mDismissView.isOnEmptySpace(touchX - mDismissView.getX(), + touchY - dismissY)); + } + } + /** * A listener that is notified when some child locations might have changed. */ @@ -2253,6 +2333,13 @@ public class NotificationStackScrollLayout extends ViewGroup } /** + * A listener that is notified when the empty space below the notifications is clicked on + */ + public interface OnEmptySpaceClickListener { + public void onEmptySpaceClicked(float x, float y); + } + + /** * A listener that gets notified when the overscroll at the top has changed. */ public interface OnOverscrollTopChangedListener { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java index 853628eaf6b7..ddc425102b2c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java @@ -200,15 +200,25 @@ public class StackScrollAlgorithm { // apply clipping and shadow float newNotificationEnd = newYTranslation + newHeight; - // In the unlocked shade we have to clip a little bit higher because of the rounded - // corners of the notifications. - float clippingCorrection = state.dimmed ? 0 : mRoundedRectCornerRadius * state.scale; - - // When the previous notification is swiped, we don't clip the content to the - // bottom of it. - float clipHeight = previousNotificationIsSwiped - ? newHeight - : newNotificationEnd - (previousNotificationEnd - clippingCorrection); + float clipHeight; + if (previousNotificationIsSwiped) { + // When the previous notification is swiped, we don't clip the content to the + // bottom of it. + clipHeight = newHeight; + } else { + clipHeight = newNotificationEnd - previousNotificationEnd; + clipHeight = Math.max(0.0f, clipHeight); + if (clipHeight != 0.0f) { + + // In the unlocked shade we have to clip a little bit higher because of the rounded + // corners of the notifications, but only if we are not fully overlapped by + // the top card. + float clippingCorrection = state.dimmed + ? 0 + : mRoundedRectCornerRadius * state.scale; + clipHeight += clippingCorrection; + } + } updateChildClippingAndBackground(state, newHeight, clipHeight, newHeight - (previousNotificationStart - newYTranslation)); @@ -669,7 +679,11 @@ public class StackScrollAlgorithm { StackScrollState.ViewState childViewState = resultState.getViewStateForView(child); if (i < algorithmState.itemsInTopStack) { float stackIndex = algorithmState.itemsInTopStack - i; - stackIndex = Math.min(stackIndex, MAX_ITEMS_IN_TOP_STACK + 2); + + // Ensure that the topmost item is a little bit higher than the rest when fully + // scrolled, to avoid drawing errors when swiping it out + float max = MAX_ITEMS_IN_TOP_STACK + (i == 0 ? 2.5f : 2); + stackIndex = Math.min(stackIndex, max); if (i == 0 && algorithmState.itemsInTopStack < 2.0f) { // We only have the top item and an additional item in the top stack, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java index 0967ecd06a52..461137001b11 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java @@ -119,9 +119,7 @@ public class StackScrollState { } // apply alpha - if (!becomesInvisible) { - child.setAlpha(newAlpha); - } + child.setAlpha(newAlpha); } // apply visibility @@ -236,6 +234,8 @@ public class StackScrollState { public static final int LOCATION_MAIN_AREA = 0x08; public static final int LOCATION_BOTTOM_STACK_PEEKING = 0x10; public static final int LOCATION_BOTTOM_STACK_HIDDEN = 0x20; + /** The view isn't layouted at all. */ + public static final int LOCATION_GONE = 0x40; float alpha; float yTranslation; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java index 433357ecb934..674642b3c437 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java @@ -477,6 +477,7 @@ public class StackStateAnimator { if (newEndValue == 0 && !mWasCancelled) { child.setVisibility(View.INVISIBLE); } + // remove the tag when the animation is finished child.setTag(TAG_ANIMATOR_ALPHA, null); child.setTag(TAG_START_ALPHA, null); child.setTag(TAG_END_ALPHA, null); @@ -498,13 +499,7 @@ public class StackStateAnimator { animator.setStartDelay(delay); } animator.addListener(getGlobalAnimationFinishedListener()); - // remove the tag when the animation is finished - animator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - } - }); startAnimator(animator); child.setTag(TAG_ANIMATOR_ALPHA, animator); child.setTag(TAG_START_ALPHA, child.getAlpha()); diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java index 0586a83d12ab..0fe6d892a0f3 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java @@ -1,7 +1,6 @@ package com.android.systemui.volume; import android.content.Context; -import android.content.Intent; import android.content.res.Configuration; import android.database.ContentObserver; import android.media.AudioManager; @@ -11,13 +10,10 @@ import android.media.session.ISessionController; import android.media.session.MediaController; import android.media.session.MediaSessionManager; import android.net.Uri; -import android.os.AsyncTask; import android.os.Handler; import android.os.RemoteException; -import android.os.UserHandle; import android.provider.Settings; import android.util.Log; -import android.view.WindowManagerGlobal; import com.android.systemui.R; import com.android.systemui.SystemUI; @@ -53,6 +49,7 @@ public class VolumeUI extends SystemUI { private final Handler mHandler = new Handler(); + private boolean mEnabled; private AudioManager mAudioManager; private MediaSessionManager mMediaSessionManager; private VolumeController mVolumeController; @@ -63,6 +60,8 @@ public class VolumeUI extends SystemUI { @Override public void start() { + mEnabled = mContext.getResources().getBoolean(R.bool.enable_volume_ui); + if (!mEnabled) return; mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); mMediaSessionManager = (MediaSessionManager) mContext .getSystemService(Context.MEDIA_SESSION_SERVICE); @@ -84,6 +83,7 @@ public class VolumeUI extends SystemUI { @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.print("mEnabled="); pw.println(mEnabled); if (mPanel != null) { mPanel.dump(fd, pw, args); } diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java index ea431aeb2678..c840f171791d 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java +++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java @@ -31,6 +31,7 @@ import android.provider.Settings; import android.provider.Settings.Global; import android.service.notification.Condition; import android.service.notification.ZenModeConfig; +import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.util.MathUtils; @@ -220,7 +221,8 @@ public class ZenModePanel extends LinearLayout { mBucketIndex = -1; } else { mBucketIndex = DEFAULT_BUCKET_INDEX; - mTimeCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[mBucketIndex]); + mTimeCondition = ZenModeConfig.toTimeCondition(mContext, + MINUTE_BUCKETS[mBucketIndex]); } if (DEBUG) Log.d(mTag, "Initial bucket index: " + mBucketIndex); mConditions = null; // reset conditions @@ -339,9 +341,11 @@ public class ZenModePanel extends LinearLayout { if (condition == null) return null; final long time = ZenModeConfig.tryParseCountdownConditionId(condition.id); if (time == 0) return null; - final long span = time - System.currentTimeMillis(); + final long now = System.currentTimeMillis(); + final long span = time - now; if (span <= 0 || span > MAX_BUCKET_MINUTES * MINUTES_MS) return null; - return ZenModeConfig.toTimeCondition(time, Math.round(span / (float) MINUTES_MS)); + return ZenModeConfig.toTimeCondition(mContext, + time, Math.round(span / (float) MINUTES_MS), now); } private void handleUpdateConditions(Condition[] conditions) { @@ -395,7 +399,7 @@ public class ZenModePanel extends LinearLayout { if (favoriteIndex == -1) { getConditionTagAt(FOREVER_CONDITION_INDEX).rb.setChecked(true); } else { - mTimeCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[favoriteIndex]); + mTimeCondition = ZenModeConfig.toTimeCondition(mContext, MINUTE_BUCKETS[favoriteIndex]); mBucketIndex = favoriteIndex; bind(mTimeCondition, mZenConditions.getChildAt(TIME_CONDITION_INDEX)); getConditionTagAt(TIME_CONDITION_INDEX).rb.setChecked(true); @@ -430,7 +434,8 @@ public class ZenModePanel extends LinearLayout { } tag.condition = condition; tag.rb.setEnabled(enabled); - if (sameConditionId(mSessionExitCondition, tag.condition)) { + if (mSessionExitCondition != null + && sameConditionId(mSessionExitCondition, tag.condition)) { tag.rb.setChecked(true); } tag.rb.setOnCheckedChangeListener(new OnCheckedChangeListener() { @@ -450,16 +455,32 @@ public class ZenModePanel extends LinearLayout { } }); - if (tag.title == null) { - tag.title = (TextView) row.findViewById(android.R.id.title); + if (tag.lines == null) { + tag.lines = row.findViewById(android.R.id.content); } + if (tag.line1 == null) { + tag.line1 = (TextView) row.findViewById(android.R.id.text1); + } + if (tag.line2 == null) { + tag.line2 = (TextView) row.findViewById(android.R.id.text2); + } + final String line1, line2; if (condition == null) { - tag.title.setText(mContext.getString(com.android.internal.R.string.zen_mode_forever)); + line1 = mContext.getString(com.android.internal.R.string.zen_mode_forever); + line2 = null; + } else { + line1 = !TextUtils.isEmpty(condition.line1) ? condition.line1 : condition.summary; + line2 = condition.line2; + } + tag.line1.setText(line1); + if (TextUtils.isEmpty(line2)) { + tag.line2.setVisibility(GONE); } else { - tag.title.setText(condition.summary); + tag.line2.setVisibility(VISIBLE); + tag.line2.setText(line2); } - tag.title.setEnabled(enabled); - tag.title.setAlpha(enabled ? 1 : .4f); + tag.lines.setEnabled(enabled); + tag.lines.setAlpha(enabled ? 1 : .4f); final ImageView button1 = (ImageView) row.findViewById(android.R.id.button1); button1.setOnClickListener(new OnClickListener() { @@ -476,7 +497,7 @@ public class ZenModePanel extends LinearLayout { onClickTimeButton(row, tag, true /*up*/); } }); - tag.title.setOnClickListener(new OnClickListener() { + tag.lines.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { tag.rb.setChecked(true); @@ -491,7 +512,8 @@ public class ZenModePanel extends LinearLayout { } else { final long span = time - System.currentTimeMillis(); button1.setEnabled(span > MIN_BUCKET_MINUTES * MINUTES_MS); - final Condition maxCondition = ZenModeConfig.toTimeCondition(MAX_BUCKET_MINUTES); + final Condition maxCondition = ZenModeConfig.toTimeCondition(mContext, + MAX_BUCKET_MINUTES); button2.setEnabled(!Objects.equals(condition.summary, maxCondition.summary)); } @@ -504,7 +526,7 @@ public class ZenModePanel extends LinearLayout { // wire up interaction callbacks for newly-added condition rows if (convertView == null) { Interaction.register(tag.rb, mInteractionCallback); - Interaction.register(tag.title, mInteractionCallback); + Interaction.register(tag.lines, mInteractionCallback); Interaction.register(button1, mInteractionCallback); Interaction.register(button2, mInteractionCallback); } @@ -524,7 +546,7 @@ public class ZenModePanel extends LinearLayout { return; } announceForAccessibility(mContext.getString(R.string.zen_mode_and_condition, modeText, - tag.title.getText())); + tag.line1.getText())); } private void onClickTimeButton(View row, ConditionTag tag, boolean up) { @@ -541,18 +563,21 @@ public class ZenModePanel extends LinearLayout { final long bucketTime = now + bucketMinutes * MINUTES_MS; if (up && bucketTime > time || !up && bucketTime < time) { mBucketIndex = j; - newCondition = ZenModeConfig.toTimeCondition(bucketTime, bucketMinutes); + newCondition = ZenModeConfig.toTimeCondition(mContext, + bucketTime, bucketMinutes, now); break; } } if (newCondition == null) { mBucketIndex = DEFAULT_BUCKET_INDEX; - newCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[mBucketIndex]); + newCondition = ZenModeConfig.toTimeCondition(mContext, + MINUTE_BUCKETS[mBucketIndex]); } } else { // on a known index, simply increment or decrement mBucketIndex = Math.max(0, Math.min(N - 1, mBucketIndex + (up ? 1 : -1))); - newCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[mBucketIndex]); + newCondition = ZenModeConfig.toTimeCondition(mContext, + MINUTE_BUCKETS[mBucketIndex]); } mTimeCondition = newCondition; bind(mTimeCondition, row); @@ -639,7 +664,9 @@ public class ZenModePanel extends LinearLayout { // used as the view tag on condition rows private static class ConditionTag { RadioButton rb; - TextView title; + View lines; + TextView line1; + TextView line2; Condition condition; } @@ -690,7 +717,7 @@ public class ZenModePanel extends LinearLayout { } private SharedPreferences prefs() { - return mContext.getSharedPreferences(ZenModePanel.class.getSimpleName(), 0); + return mContext.getSharedPreferences(mContext.getPackageName(), 0); } private void updateMinuteIndex() { diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index 9c81f0a94856..4714826dee62 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -1332,6 +1332,22 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } @Override + public final void setElevation(float elevation) { + mElevation = elevation; + if (mDecor != null) { + mDecor.setElevation(elevation); + } + } + + @Override + public final void setClipToOutline(boolean clipToOutline) { + mClipToOutline = clipToOutline; + if (mDecor != null) { + mDecor.setClipToOutline(clipToOutline); + } + } + + @Override public final void setBackgroundDrawable(Drawable drawable) { if (drawable != mBackgroundDrawable || mBackgroundResource != 0) { mBackgroundResource = 0; @@ -3342,9 +3358,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { final boolean noActionBar = !hasFeature(FEATURE_ACTION_BAR) || hasFeature(FEATURE_NO_TITLE); if (targetPreHoneycomb || (targetPreIcs && targetHcNeedsOptions && noActionBar)) { - addFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY); + setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE); } else { - clearFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY); + setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_FALSE); } // Non-floating windows on high end devices must put up decor beneath the system bars and diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 1882d5613e3e..d418ffb60145 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -136,8 +136,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final String TAG = "WindowManager"; static final boolean DEBUG = false; static final boolean localLOGV = false; - static final boolean DEBUG_LAYOUT = false; static final boolean DEBUG_INPUT = false; + static final boolean DEBUG_KEYGUARD = false; + static final boolean DEBUG_LAYOUT = false; static final boolean DEBUG_STARTING_WINDOW = false; static final boolean DEBUG_WAKEUP = false; static final boolean SHOW_STARTING_ANIMATIONS = true; @@ -1431,6 +1432,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { case TYPE_WALLPAPER: case TYPE_PRIVATE_PRESENTATION: case TYPE_VOICE_INTERACTION: + case TYPE_ACCESSIBILITY_OVERLAY: // The window manager will check these. break; case TYPE_PHONE: @@ -1484,7 +1486,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { case TYPE_PHONE: case TYPE_POINTER: case TYPE_PRIORITY_PHONE: - case TYPE_RECENTS_OVERLAY: case TYPE_SEARCH_BAR: case TYPE_STATUS_BAR: case TYPE_STATUS_BAR_PANEL: @@ -1603,7 +1604,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { case TYPE_VOICE_INTERACTION: // voice interaction layer is almost immediately above apps. return 5; - case TYPE_RECENTS_OVERLAY: case TYPE_SYSTEM_DIALOG: return 6; case TYPE_TOAST: @@ -1662,15 +1662,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { // the drag layer: input for drag-and-drop is associated with this window, // which sits above all other focusable windows return 25; - case TYPE_SECURE_SYSTEM_OVERLAY: + case TYPE_ACCESSIBILITY_OVERLAY: + // overlay put by accessibility services to intercept user interaction return 26; - case TYPE_BOOT_PROGRESS: + case TYPE_SECURE_SYSTEM_OVERLAY: return 27; + case TYPE_BOOT_PROGRESS: + return 28; case TYPE_POINTER: // the (mouse) pointer layer - return 28; - case TYPE_HIDDEN_NAV_CONSUMER: return 29; + case TYPE_HIDDEN_NAV_CONSUMER: + return 30; } Log.e(TAG, "Unknown window type: " + type); return 2; @@ -1974,7 +1977,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } mKeyguardScrim = win; break; - } return WindowManagerGlobal.ADD_OKAY; } @@ -2231,15 +2233,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { return -1; } - // If an incoming call is ringing, HOME is totally disabled. - // (The user is already on the InCallUI at this point, - // and his ONLY options are to answer or reject the call.) - TelecomManager telecomManager = getTelecommService(); - if (telecomManager != null && telecomManager.isRinging()) { - Log.i(TAG, "Ignoring HOME; there's a ringing incoming call."); - return -1; - } - // Delay handling home if a double-tap is possible. if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) { mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case @@ -3215,10 +3208,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { // whether it is taking care of insetting its content. If not, // we need to use the parent's content frame so that the entire // window is positioned within that content. Otherwise we can use - // the display frame and let the attached window take care of + // the overscan frame and let the attached window take care of // positioning its content appropriately. if (adjust != SOFT_INPUT_ADJUST_RESIZE) { - cf.set(attached.getOverscanFrameLw()); + // Set the content frame of the attached window to the parent's decor frame + // (same as content frame when IME isn't present) if specifically requested by + // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag. + // Otherwise, use the overscan frame. + cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0 + ? attached.getContentFrameLw() : attached.getOverscanFrameLw()); } else { // If the window is resizing, then we want to base the content // frame on our attached content frame to resize... however, @@ -4984,6 +4982,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public void dismissKeyguardLw() { if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) { + if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw"); mHandler.post(new Runnable() { @Override public void run() { @@ -5015,6 +5014,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) { if (mKeyguardDelegate != null) { + if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation"); mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration); } } @@ -5355,7 +5355,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { return true; } }; - mBootMsgDialog.setTitle(R.string.android_upgrading_title); + if (mContext.getPackageManager().isUpgrade()) { + mBootMsgDialog.setTitle(R.string.android_upgrading_title); + } else { + mBootMsgDialog.setTitle(R.string.android_start_title); + } mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); mBootMsgDialog.setIndeterminate(true); mBootMsgDialog.getWindow().setType( diff --git a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java deleted file mode 100644 index bc55ed138b13..000000000000 --- a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright (C) 2008 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.policy.impl; - -import android.app.ActivityManager; -import android.app.Dialog; -import android.app.StatusBarManager; -import android.content.ActivityNotFoundException; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.os.Handler; -import android.util.Log; -import android.view.KeyEvent; -import android.view.SoundEffectConstants; -import android.view.View; -import android.view.Window; -import android.view.WindowManager; -import android.view.View.OnClickListener; -import android.widget.TextView; - -import java.util.List; - -public class RecentApplicationsDialog extends Dialog implements OnClickListener { - // Elements for debugging support -// private static final String LOG_TAG = "RecentApplicationsDialog"; - private static final boolean DBG_FORCE_EMPTY_LIST = false; - - static private StatusBarManager sStatusBar; - - private static final int NUM_BUTTONS = 8; - private static final int MAX_RECENT_TASKS = NUM_BUTTONS * 2; // allow for some discards - - final TextView[] mIcons = new TextView[NUM_BUTTONS]; - View mNoAppsText; - IntentFilter mBroadcastIntentFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); - - class RecentTag { - ActivityManager.RecentTaskInfo info; - Intent intent; - } - - Handler mHandler = new Handler(); - Runnable mCleanup = new Runnable() { - public void run() { - // dump extra memory we're hanging on to - for (TextView icon: mIcons) { - icon.setCompoundDrawables(null, null, null, null); - icon.setTag(null); - } - } - }; - - public RecentApplicationsDialog(Context context) { - super(context, com.android.internal.R.style.Theme_Dialog_RecentApplications); - - } - - /** - * We create the recent applications dialog just once, and it stays around (hidden) - * until activated by the user. - * - * @see PhoneWindowManager#showRecentAppsDialog - */ - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - Context context = getContext(); - - if (sStatusBar == null) { - sStatusBar = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE); - } - - Window window = getWindow(); - window.requestFeature(Window.FEATURE_NO_TITLE); - window.setType(WindowManager.LayoutParams.TYPE_RECENTS_OVERLAY); - window.setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, - WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); - window.setTitle("Recents"); - - setContentView(com.android.internal.R.layout.recent_apps_dialog); - - final WindowManager.LayoutParams params = window.getAttributes(); - params.width = WindowManager.LayoutParams.MATCH_PARENT; - params.height = WindowManager.LayoutParams.MATCH_PARENT; - window.setAttributes(params); - window.setFlags(0, WindowManager.LayoutParams.FLAG_DIM_BEHIND); - - mIcons[0] = (TextView)findViewById(com.android.internal.R.id.button0); - mIcons[1] = (TextView)findViewById(com.android.internal.R.id.button1); - mIcons[2] = (TextView)findViewById(com.android.internal.R.id.button2); - mIcons[3] = (TextView)findViewById(com.android.internal.R.id.button3); - mIcons[4] = (TextView)findViewById(com.android.internal.R.id.button4); - mIcons[5] = (TextView)findViewById(com.android.internal.R.id.button5); - mIcons[6] = (TextView)findViewById(com.android.internal.R.id.button6); - mIcons[7] = (TextView)findViewById(com.android.internal.R.id.button7); - mNoAppsText = findViewById(com.android.internal.R.id.no_applications_message); - - for (TextView b: mIcons) { - b.setOnClickListener(this); - } - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_TAB) { - // Ignore all meta keys other than SHIFT. The app switch key could be a - // fallback action chorded with ALT, META or even CTRL depending on the key map. - // DPad navigation is handled by the ViewRoot elsewhere. - final boolean backward = event.isShiftPressed(); - final int numIcons = mIcons.length; - int numButtons = 0; - while (numButtons < numIcons && mIcons[numButtons].getVisibility() == View.VISIBLE) { - numButtons += 1; - } - if (numButtons != 0) { - int nextFocus = backward ? numButtons - 1 : 0; - for (int i = 0; i < numButtons; i++) { - if (mIcons[i].hasFocus()) { - if (backward) { - nextFocus = (i + numButtons - 1) % numButtons; - } else { - nextFocus = (i + 1) % numButtons; - } - break; - } - } - final int direction = backward ? View.FOCUS_BACKWARD : View.FOCUS_FORWARD; - if (mIcons[nextFocus].requestFocus(direction)) { - mIcons[nextFocus].playSoundEffect( - SoundEffectConstants.getContantForFocusDirection(direction)); - } - } - - // The dialog always handles the key to prevent the ViewRoot from - // performing the default navigation itself. - return true; - } - - return super.onKeyDown(keyCode, event); - } - - /** - * Dismiss the dialog and switch to the selected application. - */ - public void dismissAndSwitch() { - final int numIcons = mIcons.length; - RecentTag tag = null; - for (int i = 0; i < numIcons; i++) { - if (mIcons[i].getVisibility() != View.VISIBLE) { - break; - } - if (i == 0 || mIcons[i].hasFocus()) { - tag = (RecentTag) mIcons[i].getTag(); - if (mIcons[i].hasFocus()) { - break; - } - } - } - if (tag != null) { - switchTo(tag); - } - dismiss(); - } - - /** - * Handler for user clicks. If a button was clicked, launch the corresponding activity. - */ - public void onClick(View v) { - for (TextView b: mIcons) { - if (b == v) { - RecentTag tag = (RecentTag)b.getTag(); - switchTo(tag); - break; - } - } - dismiss(); - } - - private void switchTo(RecentTag tag) { - if (tag.info.id >= 0) { - // This is an active task; it should just go to the foreground. - final ActivityManager am = (ActivityManager) - getContext().getSystemService(Context.ACTIVITY_SERVICE); - am.moveTaskToFront(tag.info.id, ActivityManager.MOVE_TASK_WITH_HOME); - } else if (tag.intent != null) { - tag.intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY - | Intent.FLAG_ACTIVITY_TASK_ON_HOME); - try { - getContext().startActivity(tag.intent); - } catch (ActivityNotFoundException e) { - Log.w("Recent", "Unable to launch recent task", e); - } - } - } - - /** - * Set up and show the recent activities dialog. - */ - @Override - public void onStart() { - super.onStart(); - reloadButtons(); - if (sStatusBar != null) { - sStatusBar.disable(StatusBarManager.DISABLE_EXPAND); - } - - // receive broadcasts - getContext().registerReceiver(mBroadcastReceiver, mBroadcastIntentFilter); - - mHandler.removeCallbacks(mCleanup); - } - - /** - * Dismiss the recent activities dialog. - */ - @Override - public void onStop() { - super.onStop(); - - if (sStatusBar != null) { - sStatusBar.disable(StatusBarManager.DISABLE_NONE); - } - - // stop receiving broadcasts - getContext().unregisterReceiver(mBroadcastReceiver); - - mHandler.postDelayed(mCleanup, 100); - } - - /** - * Reload the 6 buttons with recent activities - */ - private void reloadButtons() { - - final Context context = getContext(); - final PackageManager pm = context.getPackageManager(); - final ActivityManager am = (ActivityManager) - context.getSystemService(Context.ACTIVITY_SERVICE); - final List<ActivityManager.RecentTaskInfo> recentTasks = - am.getRecentTasks(MAX_RECENT_TASKS, ActivityManager.RECENT_IGNORE_UNAVAILABLE); - - ActivityInfo homeInfo = - new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME) - .resolveActivityInfo(pm, 0); - - IconUtilities iconUtilities = new IconUtilities(getContext()); - - // Performance note: Our android performance guide says to prefer Iterator when - // using a List class, but because we know that getRecentTasks() always returns - // an ArrayList<>, we'll use a simple index instead. - int index = 0; - int numTasks = recentTasks.size(); - for (int i = 0; i < numTasks && (index < NUM_BUTTONS); ++i) { - final ActivityManager.RecentTaskInfo info = recentTasks.get(i); - - // for debug purposes only, disallow first result to create empty lists - if (DBG_FORCE_EMPTY_LIST && (i == 0)) continue; - - Intent intent = new Intent(info.baseIntent); - if (info.origActivity != null) { - intent.setComponent(info.origActivity); - } - - // Skip the current home activity. - if (homeInfo != null) { - if (homeInfo.packageName.equals( - intent.getComponent().getPackageName()) - && homeInfo.name.equals( - intent.getComponent().getClassName())) { - continue; - } - } - - intent.setFlags((intent.getFlags()&~Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) - | Intent.FLAG_ACTIVITY_NEW_TASK); - final ResolveInfo resolveInfo = pm.resolveActivity(intent, 0); - if (resolveInfo != null) { - final ActivityInfo activityInfo = resolveInfo.activityInfo; - final String title = activityInfo.loadLabel(pm).toString(); - Drawable icon = activityInfo.loadIcon(pm); - - if (title != null && title.length() > 0 && icon != null) { - final TextView tv = mIcons[index]; - tv.setText(title); - icon = iconUtilities.createIconDrawable(icon); - tv.setCompoundDrawables(null, icon, null, null); - RecentTag tag = new RecentTag(); - tag.info = info; - tag.intent = intent; - tv.setTag(tag); - tv.setVisibility(View.VISIBLE); - tv.setPressed(false); - tv.clearFocus(); - ++index; - } - } - } - - // handle the case of "no icons to show" - mNoAppsText.setVisibility((index == 0) ? View.VISIBLE : View.GONE); - - // hide the rest - for (; index < NUM_BUTTONS; ++index) { - mIcons[index].setVisibility(View.GONE); - } - } - - /** - * This is the listener for the ACTION_CLOSE_SYSTEM_DIALOGS intent. It's an indication that - * we should close ourselves immediately, in order to allow a higher-priority UI to take over - * (e.g. phone call received). - */ - private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) { - String reason = intent.getStringExtra(PhoneWindowManager.SYSTEM_DIALOG_REASON_KEY); - if (! PhoneWindowManager.SYSTEM_DIALOG_REASON_RECENT_APPS.equals(reason)) { - dismiss(); - } - } - } - }; -} diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index bfbf0ac7cf37..278189008362 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -1040,7 +1040,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private void addServiceLocked(Service service, UserState userState) { try { - service.linkToOwnDeathLocked(); + service.onAdded(); userState.mBoundServices.add(service); userState.mComponentNameToServiceMap.put(service.mComponentName, service); } catch (RemoteException re) { @@ -1056,7 +1056,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private void removeServiceLocked(Service service, UserState userState) { userState.mBoundServices.remove(service); userState.mComponentNameToServiceMap.remove(service.mComponentName); - service.unlinkToOwnDeathLocked(); + service.onRemoved(); } /** @@ -1931,6 +1931,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { final ResolveInfo mResolveInfo; + final IBinder mOverlayWindowToken = new Binder(); + // the events pending events to be dispatched to this service final SparseArray<AccessibilityEvent> mPendingEvents = new SparseArray<>(); @@ -2112,7 +2114,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { userState.mBindingServices.remove(mComponentName); mWasConnectedAndDied = false; try { - mServiceInterface.setConnection(this, mId); + mServiceInterface.init(this, mId, mOverlayWindowToken); onUserStateChangedLocked(userState); } catch (RemoteException re) { Slog.w(LOG_TAG, "Error while setting connection for service: " @@ -2602,6 +2604,27 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { /* do nothing - #binderDied takes care */ } + public void onAdded() throws RemoteException { + linkToOwnDeathLocked(); + final long identity = Binder.clearCallingIdentity(); + try { + mWindowManagerService.addWindowToken(mOverlayWindowToken, + WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + public void onRemoved() { + final long identity = Binder.clearCallingIdentity(); + try { + mWindowManagerService.removeWindowToken(mOverlayWindowToken, true); + } finally { + Binder.restoreCallingIdentity(identity); + } + unlinkToOwnDeathLocked(); + } + public void linkToOwnDeathLocked() throws RemoteException { mService.linkToDeath(this, 0); } @@ -2614,7 +2637,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { try { // Clear the proxy in the other process so this // IAccessibilityServiceConnection can be garbage collected. - mServiceInterface.setConnection(null, mId); + mServiceInterface.init(null, mId, null); } catch (RemoteException re) { /* ignore */ } @@ -3156,7 +3179,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { case WindowManager.LayoutParams.TYPE_STATUS_BAR: case WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL: case WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL: - case WindowManager.LayoutParams.TYPE_RECENTS_OVERLAY: case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY: case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT: case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG: @@ -3165,6 +3187,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return AccessibilityWindowInfo.TYPE_SYSTEM; } + case WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY: { + return AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY; + } + default: { return -1; } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 6a6dcaf39d3b..bf674611876f 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -238,8 +238,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { private boolean mLockdownEnabled; private LockdownVpnTracker mLockdownTracker; - private Nat464Xlat mClat; - /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */ private Object mRulesLock = new Object(); /** Currently active network rules by UID. */ @@ -715,12 +713,10 @@ public class ConnectivityService extends IConnectivityManager.Stub { intentFilter.addAction(Intent.ACTION_USER_STOPPING); mContext.registerReceiverAsUser( mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null); - mClat = new Nat464Xlat(mContext, mNetd, this, mTrackerHandler); try { mNetd.registerObserver(mTethering); mNetd.registerObserver(mDataActivityObserver); - mNetd.registerObserver(mClat); } catch (RemoteException e) { loge("Error registering observer :" + e); } @@ -3549,7 +3545,9 @@ public class ConnectivityService extends IConnectivityManager.Stub { // The NetworkAgentInfo does not know whether clatd is running on its network or not. Before // we do anything else, make sure its LinkProperties are accurate. - mClat.fixupLinkProperties(networkAgent, oldLp); + if (networkAgent.clatd != null) { + networkAgent.clatd.fixupLinkProperties(oldLp); + } updateInterfaces(newLp, oldLp, netId); updateMtu(newLp, oldLp); @@ -3568,15 +3566,15 @@ public class ConnectivityService extends IConnectivityManager.Stub { } } - private void updateClat(LinkProperties newLp, LinkProperties oldLp, NetworkAgentInfo na) { - final boolean wasRunningClat = mClat.isRunningClat(na); - final boolean shouldRunClat = Nat464Xlat.requiresClat(na); + private void updateClat(LinkProperties newLp, LinkProperties oldLp, NetworkAgentInfo nai) { + final boolean wasRunningClat = nai.clatd != null && nai.clatd.isStarted(); + final boolean shouldRunClat = Nat464Xlat.requiresClat(nai); if (!wasRunningClat && shouldRunClat) { - // Start clatd. If it's already been started but is not running yet, this is a no-op. - mClat.startClat(na); + nai.clatd = new Nat464Xlat(mContext, mNetd, mTrackerHandler, nai); + nai.clatd.start(); } else if (wasRunningClat && !shouldRunClat) { - mClat.stopClat(); + nai.clatd.stop(); } } diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags index 64d8f6fd09f5..8417cccdb649 100644 --- a/services/core/java/com/android/server/EventLogTags.logtags +++ b/services/core/java/com/android/server/EventLogTags.logtags @@ -52,7 +52,7 @@ option java_package com.android.server # NotificationManagerService.java # --------------------------- # when a NotificationManager.notify is called -2750 notification_enqueue (uid|1|5),(pid|1|5),(pkg|3),(id|1|5),(tag|3),(userid|1|5),(notification|3) +2750 notification_enqueue (uid|1|5),(pid|1|5),(pkg|3),(id|1|5),(tag|3),(userid|1|5),(notification|3),(update|1) # when someone tries to cancel a notification, the notification manager sometimes # calls this with flags too 2751 notification_cancel (uid|1|5),(pid|1|5),(pkg|3),(id|1|5),(tag|3),(userid|1|5),(required_flags|1),(forbidden_flags|1),(reason|1|5),(listener|3) @@ -69,6 +69,10 @@ option java_package com.android.server 27511 notification_expansion (key|3),(user_action|1),(expanded|1) # when a notification has been clicked 27520 notification_clicked (key|3) +# when a notification action button has been clicked +27521 notification_action_clicked (key|3),(action_index|1) +# when a notification has been canceled +27530 notification_canceled (key|3),(reason|1) # --------------------------- # Watchdog.java diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 1623eac6ac9e..edea274c155f 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -774,7 +774,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (defIm == null && mMethodList.size() > 0) { defIm = InputMethodUtils.getMostApplicableDefaultIME( mSettings.getEnabledInputMethodListLocked()); - Slog.i(TAG, "No default found, using " + defIm.getId()); + if (defIm != null) { + Slog.i(TAG, "Default found, using " + defIm.getId()); + } else { + Slog.i(TAG, "No default found"); + } } if (defIm != null) { setSelectedInputMethodAndSubtypeLocked(defIm, NOT_A_SUBTYPE_ID, false); diff --git a/services/core/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java index 07cc8647b62b..387eabc85d6b 100644 --- a/services/core/java/com/android/server/IntentResolver.java +++ b/services/core/java/com/android/server/IntentResolver.java @@ -21,7 +21,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -30,6 +29,7 @@ import java.util.Set; import android.net.Uri; import android.util.FastImmutableArraySet; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.Log; import android.util.PrintWriterPrinter; import android.util.Slog; @@ -736,7 +736,7 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { /** * All filters that have been registered. */ - private final HashSet<F> mFilters = new HashSet<F>(); + private final ArraySet<F> mFilters = new ArraySet<F>(); /** * All of the MIME types that have been registered, such as "image/jpeg", diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 28a6917cb0c7..d9c96e4a2537 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -1796,9 +1796,6 @@ public class LocationManagerService extends ILocationManager.Stub { @Override public boolean addGpsStatusListener(IGpsStatusListener listener, String packageName) { - if (mGpsStatusProvider == null) { - return false; - } int allowedResolutionLevel = getCallerAllowedResolutionLevel(); checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, LocationManager.GPS_PROVIDER); @@ -1813,6 +1810,10 @@ public class LocationManagerService extends ILocationManager.Stub { Binder.restoreCallingIdentity(ident); } + if (mGpsStatusProvider == null) { + return false; + } + try { mGpsStatusProvider.addGpsStatusListener(listener); } catch (RemoteException e) { diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java index 926235f9f2de..9596b57a5e15 100644 --- a/services/core/java/com/android/server/MmsServiceBroker.java +++ b/services/core/java/com/android/server/MmsServiceBroker.java @@ -219,7 +219,7 @@ public class MmsServiceBroker extends SystemService { // Service API calls implementation, proxied to the real MmsService in "com.android.mms.service" private final class BinderService extends IMms.Stub { @Override - public void sendMessage(long subId, String callingPkg, Uri contentUri, + public void sendMessage(int subId, String callingPkg, Uri contentUri, String locationUrl, Bundle configOverrides, PendingIntent sentIntent) throws RemoteException { mContext.enforceCallingPermission(Manifest.permission.SEND_SMS, "Send MMS message"); @@ -232,7 +232,7 @@ public class MmsServiceBroker extends SystemService { } @Override - public void downloadMessage(long subId, String callingPkg, String locationUrl, + public void downloadMessage(int subId, String callingPkg, String locationUrl, Uri contentUri, Bundle configOverrides, PendingIntent downloadedIntent) throws RemoteException { mContext.enforceCallingPermission(Manifest.permission.RECEIVE_MMS, @@ -259,7 +259,7 @@ public class MmsServiceBroker extends SystemService { } @Override - public Bundle getCarrierConfigValues(long subId) throws RemoteException { + public Bundle getCarrierConfigValues(int subId) throws RemoteException { return getServiceGuarded().getCarrierConfigValues(subId); } @@ -360,7 +360,7 @@ public class MmsServiceBroker extends SystemService { } @Override - public void sendStoredMessage(long subId, String callingPkg, Uri messageUri, + public void sendStoredMessage(int subId, String callingPkg, Uri messageUri, Bundle configOverrides, PendingIntent sentIntent) throws RemoteException { mContext.enforceCallingPermission(Manifest.permission.SEND_SMS, "Send stored MMS message"); diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 020c95182d21..0f033d71bbc9 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -940,6 +940,17 @@ public class NetworkManagementService extends INetworkManagementService.Stub } @Override + public void setInterfaceIpv6NdOffload(String iface, boolean enable) { + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + try { + mConnector.execute( + "interface", "ipv6ndoffload", iface, (enable ? "enable" : "disable")); + } catch (NativeDaemonConnectorException e) { + throw e.rethrowAsParcelableException(); + } + } + + @Override public void addRoute(int netId, RouteInfo route) { modifyRoute("add", "" + netId, route); } @@ -1854,23 +1865,23 @@ public class NetworkManagementService extends INetworkManagementService.Stub } @Override - public void stopClatd() throws IllegalStateException { + public void stopClatd(String interfaceName) throws IllegalStateException { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); try { - mConnector.execute("clatd", "stop"); + mConnector.execute("clatd", "stop", interfaceName); } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); } } @Override - public boolean isClatdStarted() { + public boolean isClatdStarted(String interfaceName) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); final NativeDaemonEvent event; try { - event = mConnector.execute("clatd", "status"); + event = mConnector.execute("clatd", "status", interfaceName); } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); } diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java index cf2a49f922e2..f4fb5199e730 100644 --- a/services/core/java/com/android/server/SystemConfig.java +++ b/services/core/java/com/android/server/SystemConfig.java @@ -32,8 +32,6 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; -import java.util.HashMap; -import java.util.HashSet; import static com.android.internal.util.ArrayUtils.appendInt; @@ -50,7 +48,7 @@ public class SystemConfig { // These are the built-in uid -> permission mappings that were read from the // system configuration files. - final SparseArray<HashSet<String>> mSystemPermissions = new SparseArray<>(); + final SparseArray<ArraySet<String>> mSystemPermissions = new SparseArray<>(); // These are the built-in shared libraries that were read from the // system configuration files. Keys are the library names; strings are the @@ -59,7 +57,7 @@ public class SystemConfig { // These are the features this devices supports that were read from the // system configuration files. - final HashMap<String, FeatureInfo> mAvailableFeatures = new HashMap<>(); + final ArrayMap<String, FeatureInfo> mAvailableFeatures = new ArrayMap<>(); public static final class PermissionEntry { public final String name; @@ -94,7 +92,7 @@ public class SystemConfig { return mGlobalGids; } - public SparseArray<HashSet<String>> getSystemPermissions() { + public SparseArray<ArraySet<String>> getSystemPermissions() { return mSystemPermissions; } @@ -102,7 +100,7 @@ public class SystemConfig { return mSharedLibraries; } - public HashMap<String, FeatureInfo> getAvailableFeatures() { + public ArrayMap<String, FeatureInfo> getAvailableFeatures() { return mAvailableFeatures; } @@ -252,9 +250,9 @@ public class SystemConfig { continue; } perm = perm.intern(); - HashSet<String> perms = mSystemPermissions.get(uid); + ArraySet<String> perms = mSystemPermissions.get(uid); if (perms == null) { - perms = new HashSet<String>(); + perms = new ArraySet<String>(); mSystemPermissions.put(uid, perms); } perms.add(perm); diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index b3337bbe3579..fcc5339e4498 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -72,7 +72,7 @@ import com.android.server.am.BatteryStatsService; * and 15973975 by saving the phoneId of the registrant and then using the * phoneId when deciding to to make a callback. This is necessary because * a subId changes from to a dummy value when a SIM is removed and thus won't - * compare properly. Because SubscriptionManager.getPhoneId(long subId) handles + * compare properly. Because SubscriptionManager.getPhoneId(int subId) handles * the dummy value conversion we properly do the callbacks. * * Eventually we may want to remove the notion of dummy value but for now this @@ -95,7 +95,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { int events; - long subId; + int subId; int phoneId; @@ -154,7 +154,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private VoLteServiceState mVoLteServiceState = new VoLteServiceState(); - private long mDefaultSubId = SubscriptionManager.INVALID_SUB_ID; + private int mDefaultSubId = SubscriptionManager.INVALID_SUB_ID; private int mDefaultPhoneId = SubscriptionManager.INVALID_PHONE_ID; @@ -201,7 +201,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } case MSG_UPDATE_DEFAULT_SUB: { int newDefaultPhoneId = msg.arg1; - long newDefaultSubId = (Long)(msg.obj); + int newDefaultSubId = (Integer)(msg.obj); if (VDBG) { log("MSG_UPDATE_DEFAULT_SUB:current mDefaultSubId=" + mDefaultSubId + " current mDefaultPhoneId=" + mDefaultPhoneId + " newDefaultSubId= " @@ -212,11 +212,12 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { //defaultSubId comes before new defaultSubId update) we need to recall all //possible missed notify callback synchronized (mRecords) { - for (Record r : mRecords) { - if(r.subId == SubscriptionManager.DEFAULT_SUB_ID) { - checkPossibleMissNotify(r, newDefaultPhoneId); - } - } + for (Record r : mRecords) { + if(r.subId == SubscriptionManager.DEFAULT_SUB_ID) { + checkPossibleMissNotify(r, newDefaultPhoneId); + } + } + handleRemoveListLocked(); } mDefaultSubId = newDefaultSubId; mDefaultPhoneId = newDefaultPhoneId; @@ -235,7 +236,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { if (DBG) log("onReceive: userHandle=" + userHandle); mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHED, userHandle, 0)); } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_SUBSCRIPTION_CHANGED)) { - Long newDefaultSubIdObj = new Long(intent.getLongExtra( + Integer newDefaultSubIdObj = new Integer(intent.getIntExtra( PhoneConstants.SUBSCRIPTION_KEY, SubscriptionManager.getDefaultSubId())); int newDefaultPhoneId = intent.getIntExtra(PhoneConstants.SLOT_KEY, SubscriptionManager.getPhoneId(mDefaultSubId)); @@ -331,13 +332,13 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } @Override - public void listenForSubscriber(long subId, String pkgForDebug, IPhoneStateListener callback, + public void listenForSubscriber(int subId, String pkgForDebug, IPhoneStateListener callback, int events, boolean notifyNow) { listen(pkgForDebug, callback, events, notifyNow, subId); } private void listen(String pkgForDebug, IPhoneStateListener callback, int events, - boolean notifyNow, long subId) { + boolean notifyNow, int subId) { int callerUid = UserHandle.getCallingUserId(); int myUid = UserHandle.myUserId(); if (VDBG) { @@ -345,10 +346,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { + " notifyNow=" + notifyNow + " subId=" + subId + " myUid=" + myUid + " callerUid=" + callerUid); } - if (events != 0) { + + if (events != PhoneStateListener.LISTEN_NONE) { /* Checks permission and throws Security exception */ checkListenerPermission(events); - synchronized (mRecords) { // register Record r = null; @@ -363,26 +364,26 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } r = new Record(); r.binder = b; - r.callback = callback; - r.pkgForDebug = pkgForDebug; - r.callerUid = callerUid; - // Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID, - // force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID - if (!SubscriptionManager.isValidSubId(subId)) { - r.subId = SubscriptionManager.DEFAULT_SUB_ID; - } else {//APP specify subID - r.subId = subId; - } - r.phoneId = SubscriptionManager.getPhoneId(r.subId); - mRecords.add(r); if (DBG) log("listen: add new record"); } + r.callback = callback; + r.pkgForDebug = pkgForDebug; + r.callerUid = callerUid; + // Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID, + // force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID + if (!SubscriptionManager.isValidSubId(subId)) { + r.subId = SubscriptionManager.DEFAULT_SUB_ID; + } else {//APP specify subID + r.subId = subId; + } + r.phoneId = SubscriptionManager.getPhoneId(r.subId); + int phoneId = r.phoneId; r.events = events; if (DBG) { - log("listen: r=" + r + " r.subId=" + r.subId + " phoneId=" + phoneId); + log("listen: Register r=" + r + " r.subId=" + r.subId + " phoneId=" + phoneId); } if (VDBG) toStringLogSSC("listen"); if (notifyNow && validatePhoneId(phoneId)) { @@ -502,6 +503,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } } } else { + if(DBG) log("listen: Unregister"); remove(callback.asBinder()); } } @@ -543,7 +545,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { broadcastCallStateChanged(state, incomingNumber, SubscriptionManager.DEFAULT_SUB_ID); } - public void notifyCallStateForSubscriber(long subId, int state, String incomingNumber) { + public void notifyCallStateForSubscriber(int subId, int state, String incomingNumber) { if (!checkNotifyPermission("notifyCallState()")) { return; } @@ -573,7 +575,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { broadcastCallStateChanged(state, incomingNumber, subId); } - public void notifyServiceStateForPhoneId(int phoneId, long subId, ServiceState state) { + public void notifyServiceStateForPhoneId(int phoneId, int subId, ServiceState state) { if (!checkNotifyPermission("notifyServiceState()")){ return; } @@ -619,7 +621,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { notifySignalStrengthForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, signalStrength); } - public void notifySignalStrengthForSubscriber(long subId, SignalStrength signalStrength) { + public void notifySignalStrengthForSubscriber(int subId, SignalStrength signalStrength) { if (!checkNotifyPermission("notifySignalStrength()")) { return; } @@ -679,7 +681,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { notifyCellInfoForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, cellInfo); } - public void notifyCellInfoForSubscriber(long subId, List<CellInfo> cellInfo) { + public void notifyCellInfoForSubscriber(int subId, List<CellInfo> cellInfo) { if (!checkNotifyPermission("notifyCellInfo()")) { return; } @@ -736,7 +738,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } @Override - public void notifyMessageWaitingChangedForPhoneId(int phoneId, long subId, boolean mwi) { + public void notifyMessageWaitingChangedForPhoneId(int phoneId, int subId, boolean mwi) { if (!checkNotifyPermission("notifyMessageWaitingChanged()")) { return; } @@ -766,7 +768,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { notifyCallForwardingChangedForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, cfi); } - public void notifyCallForwardingChangedForSubscriber(long subId, boolean cfi) { + public void notifyCallForwardingChangedForSubscriber(int subId, boolean cfi) { if (!checkNotifyPermission("notifyCallForwardingChanged()")) { return; } @@ -797,7 +799,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { notifyDataActivityForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, state); } - public void notifyDataActivityForSubscriber(long subId, int state) { + public void notifyDataActivityForSubscriber(int subId, int state) { if (!checkNotifyPermission("notifyDataActivity()" )) { return; } @@ -825,7 +827,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { networkCapabilities, networkType, roaming); } - public void notifyDataConnectionForSubscriber(long subId, int state, + public void notifyDataConnectionForSubscriber(int subId, int state, boolean isDataConnectivityPossible, String reason, String apn, String apnType, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, int networkType, boolean roaming) { @@ -914,7 +916,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { reason, apnType); } - public void notifyDataConnectionFailedForSubscriber(long subId, + public void notifyDataConnectionFailedForSubscriber(int subId, String reason, String apnType) { if (!checkNotifyPermission("notifyDataConnectionFailed()")) { return; @@ -947,7 +949,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { notifyCellLocationForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, cellLocation); } - public void notifyCellLocationForSubscriber(long subId, Bundle cellLocation) { + public void notifyCellLocationForSubscriber(int subId, Bundle cellLocation) { log("notifyCellLocationForSubscriber: subId=" + subId + " cellLocation=" + cellLocation); if (!checkNotifyPermission("notifyCellLocation()")) { @@ -1094,7 +1096,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - public void notifyOemHookRawEventForSubscriber(long subId, byte[] rawData) { + public void notifyOemHookRawEventForSubscriber(int subId, byte[] rawData) { if (!checkNotifyPermission("notifyOemHookRawEventForSubscriber")) { return; } @@ -1160,7 +1162,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { // the legacy intent broadcasting // - private void broadcastServiceStateChanged(ServiceState state, long subId) { + private void broadcastServiceStateChanged(ServiceState state, int subId) { long ident = Binder.clearCallingIdentity(); try { mBatteryStats.notePhoneState(state.getState()); @@ -1179,7 +1181,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } - private void broadcastSignalStrengthChanged(SignalStrength signalStrength, long subId) { + private void broadcastSignalStrengthChanged(SignalStrength signalStrength, int subId) { long ident = Binder.clearCallingIdentity(); try { mBatteryStats.notePhoneSignalStrength(signalStrength); @@ -1198,7 +1200,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } - private void broadcastCallStateChanged(int state, String incomingNumber, long subId) { + private void broadcastCallStateChanged(int state, String incomingNumber, int subId) { long ident = Binder.clearCallingIdentity(); try { if (state == TelephonyManager.CALL_STATE_IDLE) { @@ -1226,7 +1228,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private void broadcastDataConnectionStateChanged(int state, boolean isDataConnectivityPossible, String reason, String apn, String apnType, LinkProperties linkProperties, - NetworkCapabilities networkCapabilities, boolean roaming, long subId) { + NetworkCapabilities networkCapabilities, boolean roaming, int subId) { // Note: not reporting to the battery stats service here, because the // status bar takes care of that after taking into account all of the // required info. @@ -1258,7 +1260,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } private void broadcastDataConnectionFailed(String reason, String apnType, - long subId) { + int subId) { Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED); intent.putExtra(PhoneConstants.FAILURE_REASON_KEY, reason); intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType); @@ -1374,11 +1376,11 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private static class LogSSC { private Time mTime; private String mS; - private long mSubId; + private int mSubId; private int mPhoneId; private ServiceState mState; - public void set(Time t, String s, long subId, int phoneId, ServiceState state) { + public void set(Time t, String s, int subId, int phoneId, ServiceState state) { mTime = t; mS = s; mSubId = subId; mPhoneId = phoneId; mState = state; } @@ -1391,7 +1393,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private LogSSC logSSC [] = new LogSSC[10]; private int next = 0; - private void logServiceStateChanged(String s, long subId, int phoneId, ServiceState state) { + private void logServiceStateChanged(String s, int subId, int phoneId, ServiceState state) { if (logSSC == null || logSSC.length == 0) { return; } @@ -1427,7 +1429,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - boolean subIdMatch(long rSubId, long subId) { + boolean subIdMatch(int rSubId, int subId) { if(rSubId == SubscriptionManager.DEFAULT_SUB_ID) { return (subId == mDefaultSubId); } else { @@ -1445,7 +1447,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { r.callback.onServiceStateChanged( new ServiceState(mServiceState[phoneId])); } catch (RemoteException ex) { - remove(r.binder); + mRemoveList.add(r.binder); } } @@ -1472,7 +1474,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1 : gsmSignalStrength)); } catch (RemoteException ex) { - remove(r.binder); + mRemoveList.add(r.binder); } } @@ -1484,7 +1486,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } r.callback.onCellInfoChanged(mCellInfo.get(phoneId)); } catch (RemoteException ex) { - remove(r.binder); + mRemoveList.add(r.binder); } } @@ -1497,7 +1499,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { r.callback.onMessageWaitingIndicatorChanged( mMessageWaiting[phoneId]); } catch (RemoteException ex) { - remove(r.binder); + mRemoveList.add(r.binder); } } @@ -1510,7 +1512,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { r.callback.onCallForwardingIndicatorChanged( mCallForwarding[phoneId]); } catch (RemoteException ex) { - remove(r.binder); + mRemoveList.add(r.binder); } } @@ -1535,7 +1537,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { r.callback.onDataConnectionStateChanged(mDataConnectionState[phoneId], mDataConnectionNetworkType[phoneId]); } catch (RemoteException ex) { - remove(r.binder); + mRemoveList.add(r.binder); } } } diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java index d4c436f6c8f5..5add88eaa63c 100644 --- a/services/core/java/com/android/server/TextServicesManagerService.java +++ b/services/core/java/com/android/server/TextServicesManagerService.java @@ -16,6 +16,7 @@ package com.android.server; +import com.android.internal.annotations.GuardedBy; import com.android.internal.content.PackageMonitor; import com.android.internal.textservice.ISpellCheckerService; import com.android.internal.textservice.ISpellCheckerSession; @@ -28,14 +29,18 @@ import org.xmlpull.v1.XmlPullParserException; import android.app.ActivityManagerNative; import android.app.AppGlobals; import android.app.IUserSwitchObserver; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.ServiceConnection; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.content.pm.UserInfo; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; @@ -43,6 +48,7 @@ import android.os.IRemoteCallback; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; +import android.os.UserManager; import android.provider.Settings; import android.service.textservice.SpellCheckerService; import android.text.TextUtils; @@ -84,6 +90,12 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { public TextServicesManagerService(Context context) { mSystemReady = false; mContext = context; + + final IntentFilter broadcastFilter = new IntentFilter(); + broadcastFilter.addAction(Intent.ACTION_USER_ADDED); + broadcastFilter.addAction(Intent.ACTION_USER_REMOVED); + mContext.registerReceiver(new TextServicesBroadcastReceiver(), broadcastFilter); + int userId = UserHandle.USER_OWNER; try { ActivityManagerNative.getDefault().registerUserSwitchObserver( @@ -119,6 +131,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { private void switchUserLocked(int userId) { mSettings.setCurrentUserId(userId); + updateCurrentProfileIds(); unbindServiceLocked(); buildSpellCheckerMapLocked(mContext, mSpellCheckerList, mSpellCheckerMap, mSettings); SpellCheckerInfo sci = getCurrentSpellChecker(null); @@ -133,6 +146,16 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } } + void updateCurrentProfileIds() { + List<UserInfo> profiles = + UserManager.get(mContext).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; + } + mSettings.setCurrentProfileIds(currentProfileIds); + } + private class TextServicesMonitor extends PackageMonitor { private boolean isChangingPackagesOfCurrentUser() { final int userId = getChangingUserId(); @@ -171,6 +194,19 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } } + class TextServicesBroadcastReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (Intent.ACTION_USER_ADDED.equals(action) + || Intent.ACTION_USER_REMOVED.equals(action)) { + updateCurrentProfileIds(); + return; + } + Slog.w(TAG, "Unexpected intent " + intent); + } + } + private static void buildSpellCheckerMapLocked(Context context, ArrayList<SpellCheckerInfo> list, HashMap<String, SpellCheckerInfo> map, TextServicesSettings settings) { @@ -223,7 +259,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { Slog.d(TAG, "--- calledFromForegroundUserOrSystemProcess ? " + "calling uid = " + uid + " system uid = " + Process.SYSTEM_UID + " calling userId = " + userId + ", foreground user id = " - + mSettings.getCurrentUserId()); + + mSettings.getCurrentUserId() + ", calling pid = " + Binder.getCallingPid()); try { final String[] packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid); for (int i = 0; i < packageNames.length; ++i) { @@ -237,10 +273,40 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { if (uid == Process.SYSTEM_UID || userId == mSettings.getCurrentUserId()) { return true; - } else { - Slog.w(TAG, "--- IPC called from background users. Ignore. \n" + getStackTrace()); - return false; } + + // Permits current profile to use TSFM as long as the current text service is the system's + // one. This is a tentative solution and should be replaced with fully functional multiuser + // support. + // TODO: Implement multiuser support in TSMS. + final boolean isCurrentProfile = mSettings.isCurrentProfile(userId); + if (DBG) { + Slog.d(TAG, "--- userId = "+ userId + " isCurrentProfile = " + isCurrentProfile); + } + if (mSettings.isCurrentProfile(userId)) { + final SpellCheckerInfo spellCheckerInfo = getCurrentSpellCheckerWithoutVerification(); + if (spellCheckerInfo != null) { + final ServiceInfo serviceInfo = spellCheckerInfo.getServiceInfo(); + final boolean isSystemSpellChecker = + (serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; + if (DBG) { + Slog.d(TAG, "--- current spell checker = "+ spellCheckerInfo.getPackageName() + + " isSystem = " + isSystemSpellChecker); + } + if (isSystemSpellChecker) { + return true; + } + } + } + + // Unlike InputMethodManagerService#calledFromValidUser, INTERACT_ACROSS_USERS_FULL isn't + // taken into account here. Anyway this method is supposed to be removed once multiuser + // support is implemented. + if (DBG) { + Slog.d(TAG, "--- IPC from userId:" + userId + " is being ignored. \n" + + getStackTrace()); + } + return false; } private boolean bindCurrentSpellCheckerService( @@ -292,6 +358,10 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { if (!calledFromValidUser()) { return null; } + return getCurrentSpellCheckerWithoutVerification(); + } + + private SpellCheckerInfo getCurrentSpellCheckerWithoutVerification() { synchronized (mSpellCheckerMap) { final String curSpellCheckerId = mSettings.getSelectedSpellChecker(); if (DBG) { @@ -914,6 +984,10 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { private static class TextServicesSettings { private final ContentResolver mResolver; private int mCurrentUserId; + @GuardedBy("mLock") + private int[] mCurrentProfileIds = new int[0]; + private Object mLock = new Object(); + public TextServicesSettings(ContentResolver resolver, int userId) { mResolver = resolver; mCurrentUserId = userId; @@ -928,6 +1002,22 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { mCurrentUserId = userId; } + public void setCurrentProfileIds(int[] currentProfileIds) { + synchronized (mLock) { + mCurrentProfileIds = currentProfileIds; + } + } + + public boolean isCurrentProfile(int userId) { + synchronized (mLock) { + if (userId == mCurrentUserId) return true; + for (int i = 0; i < mCurrentProfileIds.length; i++) { + if (userId == mCurrentProfileIds[i]) return true; + } + return false; + } + } + public int getCurrentUserId() { return mCurrentUserId; } diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index 89e3f49ef7ff..8e46c4dfb223 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -415,15 +415,9 @@ public class Watchdog extends Thread { dumpKernelStackTraces(); } - // Trigger the kernel to dump all blocked threads to the kernel log - try { - FileWriter sysrq_trigger = new FileWriter("/proc/sysrq-trigger"); - sysrq_trigger.write("w"); - sysrq_trigger.close(); - } catch (IOException e) { - Slog.e(TAG, "Failed to write to /proc/sysrq-trigger"); - Slog.e(TAG, e.getMessage()); - } + // Trigger the kernel to dump all blocked threads, and backtraces on all CPUs to the kernel log + doSysRq('w'); + doSysRq('l'); // Try to add the error to the dropbox, but assuming that the ActivityManager // itself may be deadlocked. (which has happened, causing this statement to @@ -488,6 +482,16 @@ public class Watchdog extends Thread { } } + private void doSysRq(char c) { + try { + FileWriter sysrq_trigger = new FileWriter("/proc/sysrq-trigger"); + sysrq_trigger.write(c); + sysrq_trigger.close(); + } catch (IOException e) { + Slog.w(TAG, "Failed to write to /proc/sysrq-trigger", e); + } + } + private File dumpKernelStackTraces() { String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null); if (tracesPath == null || tracesPath.length() == 0) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 8dfb3217c0af..9179cc494f35 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1606,192 +1606,7 @@ public final class ActivityManagerService extends ActivityManagerNative final ArrayList<ProcessMemInfo> memInfos = (ArrayList<ProcessMemInfo>)msg.obj; Thread thread = new Thread() { @Override public void run() { - final SparseArray<ProcessMemInfo> infoMap - = new SparseArray<ProcessMemInfo>(memInfos.size()); - for (int i=0, N=memInfos.size(); i<N; i++) { - ProcessMemInfo mi = memInfos.get(i); - infoMap.put(mi.pid, mi); - } - updateCpuStatsNow(); - synchronized (mProcessCpuTracker) { - final int N = mProcessCpuTracker.countStats(); - for (int i=0; i<N; i++) { - ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i); - if (st.vsize > 0) { - long pss = Debug.getPss(st.pid, null); - if (pss > 0) { - if (infoMap.indexOfKey(st.pid) < 0) { - ProcessMemInfo mi = new ProcessMemInfo(st.name, st.pid, - ProcessList.NATIVE_ADJ, -1, "native", null); - mi.pss = pss; - memInfos.add(mi); - } - } - } - } - } - - long totalPss = 0; - for (int i=0, N=memInfos.size(); i<N; i++) { - ProcessMemInfo mi = memInfos.get(i); - if (mi.pss == 0) { - mi.pss = Debug.getPss(mi.pid, null); - } - totalPss += mi.pss; - } - Collections.sort(memInfos, new Comparator<ProcessMemInfo>() { - @Override public int compare(ProcessMemInfo lhs, ProcessMemInfo rhs) { - if (lhs.oomAdj != rhs.oomAdj) { - return lhs.oomAdj < rhs.oomAdj ? -1 : 1; - } - if (lhs.pss != rhs.pss) { - return lhs.pss < rhs.pss ? 1 : -1; - } - return 0; - } - }); - - StringBuilder tag = new StringBuilder(128); - StringBuilder stack = new StringBuilder(128); - tag.append("Low on memory -- "); - appendMemBucket(tag, totalPss, "total", false); - appendMemBucket(stack, totalPss, "total", true); - - StringBuilder logBuilder = new StringBuilder(1024); - logBuilder.append("Low on memory:\n"); - - boolean firstLine = true; - int lastOomAdj = Integer.MIN_VALUE; - for (int i=0, N=memInfos.size(); i<N; i++) { - ProcessMemInfo mi = memInfos.get(i); - - if (mi.oomAdj != ProcessList.NATIVE_ADJ - && (mi.oomAdj < ProcessList.SERVICE_ADJ - || mi.oomAdj == ProcessList.HOME_APP_ADJ - || mi.oomAdj == ProcessList.PREVIOUS_APP_ADJ)) { - if (lastOomAdj != mi.oomAdj) { - lastOomAdj = mi.oomAdj; - if (mi.oomAdj <= ProcessList.FOREGROUND_APP_ADJ) { - tag.append(" / "); - } - if (mi.oomAdj >= ProcessList.FOREGROUND_APP_ADJ) { - if (firstLine) { - stack.append(":"); - firstLine = false; - } - stack.append("\n\t at "); - } else { - stack.append("$"); - } - } else { - tag.append(" "); - stack.append("$"); - } - if (mi.oomAdj <= ProcessList.FOREGROUND_APP_ADJ) { - appendMemBucket(tag, mi.pss, mi.name, false); - } - appendMemBucket(stack, mi.pss, mi.name, true); - if (mi.oomAdj >= ProcessList.FOREGROUND_APP_ADJ - && ((i+1) >= N || memInfos.get(i+1).oomAdj != lastOomAdj)) { - stack.append("("); - for (int k=0; k<DUMP_MEM_OOM_ADJ.length; k++) { - if (DUMP_MEM_OOM_ADJ[k] == mi.oomAdj) { - stack.append(DUMP_MEM_OOM_LABEL[k]); - stack.append(":"); - stack.append(DUMP_MEM_OOM_ADJ[k]); - } - } - stack.append(")"); - } - } - - logBuilder.append(" "); - logBuilder.append(ProcessList.makeOomAdjString(mi.oomAdj)); - logBuilder.append(' '); - logBuilder.append(ProcessList.makeProcStateString(mi.procState)); - logBuilder.append(' '); - ProcessList.appendRamKb(logBuilder, mi.pss); - logBuilder.append(" kB: "); - logBuilder.append(mi.name); - logBuilder.append(" ("); - logBuilder.append(mi.pid); - logBuilder.append(") "); - logBuilder.append(mi.adjType); - logBuilder.append('\n'); - if (mi.adjReason != null) { - logBuilder.append(" "); - logBuilder.append(mi.adjReason); - logBuilder.append('\n'); - } - } - - logBuilder.append(" "); - ProcessList.appendRamKb(logBuilder, totalPss); - logBuilder.append(" kB: TOTAL\n"); - - long[] infos = new long[Debug.MEMINFO_COUNT]; - Debug.getMemInfo(infos); - logBuilder.append(" MemInfo: "); - logBuilder.append(infos[Debug.MEMINFO_SLAB]).append(" kB slab, "); - logBuilder.append(infos[Debug.MEMINFO_SHMEM]).append(" kB shmem, "); - logBuilder.append(infos[Debug.MEMINFO_BUFFERS]).append(" kB buffers, "); - logBuilder.append(infos[Debug.MEMINFO_CACHED]).append(" kB cached, "); - logBuilder.append(infos[Debug.MEMINFO_FREE]).append(" kB free\n"); - if (infos[Debug.MEMINFO_ZRAM_TOTAL] != 0) { - logBuilder.append(" ZRAM: "); - logBuilder.append(infos[Debug.MEMINFO_ZRAM_TOTAL]); - logBuilder.append(" kB RAM, "); - logBuilder.append(infos[Debug.MEMINFO_SWAP_TOTAL]); - logBuilder.append(" kB swap total, "); - logBuilder.append(infos[Debug.MEMINFO_SWAP_FREE]); - logBuilder.append(" kB swap free\n"); - } - Slog.i(TAG, logBuilder.toString()); - - StringBuilder dropBuilder = new StringBuilder(1024); - /* - StringWriter oomSw = new StringWriter(); - PrintWriter oomPw = new FastPrintWriter(oomSw, false, 256); - StringWriter catSw = new StringWriter(); - PrintWriter catPw = new FastPrintWriter(catSw, false, 256); - String[] emptyArgs = new String[] { }; - dumpApplicationMemoryUsage(null, oomPw, " ", emptyArgs, true, catPw); - oomPw.flush(); - String oomString = oomSw.toString(); - */ - dropBuilder.append(stack); - dropBuilder.append('\n'); - dropBuilder.append('\n'); - dropBuilder.append(logBuilder); - dropBuilder.append('\n'); - /* - dropBuilder.append(oomString); - dropBuilder.append('\n'); - */ - StringWriter catSw = new StringWriter(); - synchronized (ActivityManagerService.this) { - PrintWriter catPw = new FastPrintWriter(catSw, false, 256); - String[] emptyArgs = new String[] { }; - catPw.println(); - dumpProcessesLocked(null, catPw, emptyArgs, 0, false, null); - catPw.println(); - mServices.dumpServicesLocked(null, catPw, emptyArgs, 0, - false, false, null); - catPw.println(); - dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false, null); - catPw.flush(); - } - dropBuilder.append(catSw.toString()); - addErrorToDropBox("lowmem", null, "system_server", null, - null, tag.toString(), dropBuilder.toString(), null, null); - //Slog.i(TAG, "Sent to dropbox:"); - //Slog.i(TAG, dropBuilder.toString()); - synchronized (ActivityManagerService.this) { - long now = SystemClock.uptimeMillis(); - if (mLastMemUsageReportTime < now) { - mLastMemUsageReportTime = now; - } - } + reportMemUsage(memInfos); } }; thread.start(); @@ -1952,9 +1767,7 @@ public final class ActivityManagerService extends ActivityManagerNative + (SystemClock.uptimeMillis()-start) + "ms"); mProcessStats.addSysMemUsageLocked(memInfo.getCachedSizeKb(), memInfo.getFreeSizeKb(), memInfo.getZramTotalSizeKb(), - memInfo.getBuffersSizeKb()+memInfo.getShmemSizeKb() - +memInfo.getSlabSizeKb(), - nativeTotalPss); + memInfo.getKernelUsedSizeKb(), nativeTotalPss); } } @@ -8849,7 +8662,8 @@ public final class ActivityManagerService extends ActivityManagerNative task = mStackSupervisor.anyTaskForIdLocked(task.taskId); if (task != null) { if (!isSystemInitiated - && ((mFocusedActivity == null) || (task != mFocusedActivity.task))) { + && ((mStackSupervisor.getFocusedStack() == null) + || (task != mStackSupervisor.getFocusedStack().topTask()))) { throw new IllegalArgumentException("Invalid task, not in foreground"); } mStackSupervisor.setLockTaskModeLocked(task, !isSystemInitiated); @@ -13923,6 +13737,35 @@ public final class ActivityManagerService extends ActivityManagerNative } } + private static final int KSM_SHARED = 0; + private static final int KSM_SHARING = 1; + private static final int KSM_UNSHARED = 2; + private static final int KSM_VOLATILE = 3; + + private final long[] getKsmInfo() { + long[] longOut = new long[4]; + final int[] SINGLE_LONG_FORMAT = new int[] { + Process.PROC_SPACE_TERM|Process.PROC_OUT_LONG + }; + long[] longTmp = new long[1]; + Process.readProcFile("/sys/kernel/mm/ksm/pages_shared", + SINGLE_LONG_FORMAT, null, longTmp, null); + longOut[KSM_SHARED] = longTmp[0] * ProcessList.PAGE_SIZE / 1024; + longTmp[0] = 0; + Process.readProcFile("/sys/kernel/mm/ksm/pages_sharing", + SINGLE_LONG_FORMAT, null, longTmp, null); + longOut[KSM_SHARING] = longTmp[0] * ProcessList.PAGE_SIZE / 1024; + longTmp[0] = 0; + Process.readProcFile("/sys/kernel/mm/ksm/pages_unshared", + SINGLE_LONG_FORMAT, null, longTmp, null); + longOut[KSM_UNSHARED] = longTmp[0] * ProcessList.PAGE_SIZE / 1024; + longTmp[0] = 0; + Process.readProcFile("/sys/kernel/mm/ksm/pages_volatile", + SINGLE_LONG_FORMAT, null, longTmp, null); + longOut[KSM_VOLATILE] = longTmp[0] * ProcessList.PAGE_SIZE / 1024; + return longOut; + } + final void dumpApplicationMemoryUsage(FileDescriptor fd, PrintWriter pw, String prefix, String[] args, boolean brief, PrintWriter categoryPw) { boolean dumpDetails = false; @@ -14240,8 +14083,7 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized (this) { mProcessStats.addSysMemUsageLocked(memInfo.getCachedSizeKb(), memInfo.getFreeSizeKb(), memInfo.getZramTotalSizeKb(), - memInfo.getBuffersSizeKb()+memInfo.getShmemSizeKb()+memInfo.getSlabSizeKb(), - nativeProcTotalPss); + memInfo.getKernelUsedSizeKb(), nativeProcTotalPss); } } if (!brief) { @@ -14269,7 +14111,7 @@ public final class ActivityManagerService extends ActivityManagerNative pw.print(" Free RAM: "); pw.print(cachedPss + memInfo.getCachedSizeKb() + memInfo.getFreeSizeKb()); pw.print(" kB ("); pw.print(cachedPss); pw.print(" cached pss + "); - pw.print(memInfo.getCachedSizeKb()); pw.print(" cached + "); + pw.print(memInfo.getCachedSizeKb()); pw.print(" cached kernel + "); pw.print(memInfo.getFreeSizeKb()); pw.println(" free)"); } else { pw.print("ram,"); pw.print(memInfo.getTotalSizeKb()); pw.print(","); @@ -14280,16 +14122,12 @@ public final class ActivityManagerService extends ActivityManagerNative } if (!isCompact) { pw.print(" Used RAM: "); pw.print(totalPss - cachedPss - + memInfo.getBuffersSizeKb() + memInfo.getShmemSizeKb() - + memInfo.getSlabSizeKb()); pw.print(" kB ("); + + memInfo.getKernelUsedSizeKb()); pw.print(" kB ("); pw.print(totalPss - cachedPss); pw.print(" used pss + "); - pw.print(memInfo.getBuffersSizeKb()); pw.print(" buffers + "); - pw.print(memInfo.getShmemSizeKb()); pw.print(" shmem + "); - pw.print(memInfo.getSlabSizeKb()); pw.println(" slab)"); + pw.print(memInfo.getKernelUsedSizeKb()); pw.print(" kernel)\n"); pw.print(" Lost RAM: "); pw.print(memInfo.getTotalSizeKb() - totalPss - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb() - - memInfo.getBuffersSizeKb() - memInfo.getShmemSizeKb() - - memInfo.getSlabSizeKb()); pw.println(" kB"); + - memInfo.getKernelUsedSizeKb()); pw.println(" kB"); } if (!brief) { if (memInfo.getZramTotalSizeKb() != 0) { @@ -14307,32 +14145,16 @@ public final class ActivityManagerService extends ActivityManagerNative pw.println(memInfo.getSwapFreeSizeKb()); } } - final int[] SINGLE_LONG_FORMAT = new int[] { - Process.PROC_SPACE_TERM|Process.PROC_OUT_LONG - }; - long[] longOut = new long[1]; - Process.readProcFile("/sys/kernel/mm/ksm/pages_shared", - SINGLE_LONG_FORMAT, null, longOut, null); - long shared = longOut[0] * ProcessList.PAGE_SIZE / 1024; - longOut[0] = 0; - Process.readProcFile("/sys/kernel/mm/ksm/pages_sharing", - SINGLE_LONG_FORMAT, null, longOut, null); - long sharing = longOut[0] * ProcessList.PAGE_SIZE / 1024; - longOut[0] = 0; - Process.readProcFile("/sys/kernel/mm/ksm/pages_unshared", - SINGLE_LONG_FORMAT, null, longOut, null); - long unshared = longOut[0] * ProcessList.PAGE_SIZE / 1024; - longOut[0] = 0; - Process.readProcFile("/sys/kernel/mm/ksm/pages_volatile", - SINGLE_LONG_FORMAT, null, longOut, null); - long voltile = longOut[0] * ProcessList.PAGE_SIZE / 1024; + final long[] ksm = getKsmInfo(); if (!isCompact) { - if (sharing != 0 || shared != 0 || unshared != 0 || voltile != 0) { - pw.print(" KSM: "); pw.print(sharing); + if (ksm[KSM_SHARING] != 0 || ksm[KSM_SHARED] != 0 || ksm[KSM_UNSHARED] != 0 + || ksm[KSM_VOLATILE] != 0) { + pw.print(" KSM: "); pw.print(ksm[KSM_SHARING]); pw.print(" kB saved from shared "); - pw.print(shared); pw.println(" kB"); - pw.print(" "); pw.print(unshared); pw.print(" kB unshared; "); - pw.print(voltile); pw.println(" kB volatile"); + pw.print(ksm[KSM_SHARED]); pw.println(" kB"); + pw.print(" "); pw.print(ksm[KSM_UNSHARED]); + pw.print(" kB unshared; "); + pw.print(ksm[KSM_VOLATILE]); pw.println(" kB volatile"); } pw.print(" Tuning: "); pw.print(ActivityManager.staticGetMemoryClass()); @@ -14352,9 +14174,9 @@ public final class ActivityManagerService extends ActivityManagerNative } pw.println(); } else { - pw.print("ksm,"); pw.print(sharing); pw.print(","); - pw.print(shared); pw.print(","); pw.print(unshared); pw.print(","); - pw.println(voltile); + pw.print("ksm,"); pw.print(ksm[KSM_SHARING]); pw.print(","); + pw.print(ksm[KSM_SHARED]); pw.print(","); pw.print(ksm[KSM_UNSHARED]); + pw.print(","); pw.println(ksm[KSM_VOLATILE]); pw.print("tuning,"); pw.print(ActivityManager.staticGetMemoryClass()); pw.print(','); @@ -14373,6 +14195,265 @@ public final class ActivityManagerService extends ActivityManagerNative } } + private void appendBasicMemEntry(StringBuilder sb, int oomAdj, int procState, long pss, + String name) { + sb.append(" "); + sb.append(ProcessList.makeOomAdjString(oomAdj)); + sb.append(' '); + sb.append(ProcessList.makeProcStateString(procState)); + sb.append(' '); + ProcessList.appendRamKb(sb, pss); + sb.append(" kB: "); + sb.append(name); + } + + private void appendMemInfo(StringBuilder sb, ProcessMemInfo mi) { + appendBasicMemEntry(sb, mi.oomAdj, mi.procState, mi.pss, mi.name); + sb.append(" ("); + sb.append(mi.pid); + sb.append(") "); + sb.append(mi.adjType); + sb.append('\n'); + if (mi.adjReason != null) { + sb.append(" "); + sb.append(mi.adjReason); + sb.append('\n'); + } + } + + void reportMemUsage(ArrayList<ProcessMemInfo> memInfos) { + final SparseArray<ProcessMemInfo> infoMap = new SparseArray<>(memInfos.size()); + for (int i=0, N=memInfos.size(); i<N; i++) { + ProcessMemInfo mi = memInfos.get(i); + infoMap.put(mi.pid, mi); + } + updateCpuStatsNow(); + synchronized (mProcessCpuTracker) { + final int N = mProcessCpuTracker.countStats(); + for (int i=0; i<N; i++) { + ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i); + if (st.vsize > 0) { + long pss = Debug.getPss(st.pid, null); + if (pss > 0) { + if (infoMap.indexOfKey(st.pid) < 0) { + ProcessMemInfo mi = new ProcessMemInfo(st.name, st.pid, + ProcessList.NATIVE_ADJ, -1, "native", null); + mi.pss = pss; + memInfos.add(mi); + } + } + } + } + } + + long totalPss = 0; + for (int i=0, N=memInfos.size(); i<N; i++) { + ProcessMemInfo mi = memInfos.get(i); + if (mi.pss == 0) { + mi.pss = Debug.getPss(mi.pid, null); + } + totalPss += mi.pss; + } + Collections.sort(memInfos, new Comparator<ProcessMemInfo>() { + @Override public int compare(ProcessMemInfo lhs, ProcessMemInfo rhs) { + if (lhs.oomAdj != rhs.oomAdj) { + return lhs.oomAdj < rhs.oomAdj ? -1 : 1; + } + if (lhs.pss != rhs.pss) { + return lhs.pss < rhs.pss ? 1 : -1; + } + return 0; + } + }); + + StringBuilder tag = new StringBuilder(128); + StringBuilder stack = new StringBuilder(128); + tag.append("Low on memory -- "); + appendMemBucket(tag, totalPss, "total", false); + appendMemBucket(stack, totalPss, "total", true); + + StringBuilder fullNativeBuilder = new StringBuilder(1024); + StringBuilder shortNativeBuilder = new StringBuilder(1024); + StringBuilder fullJavaBuilder = new StringBuilder(1024); + + boolean firstLine = true; + int lastOomAdj = Integer.MIN_VALUE; + long extraNativeRam = 0; + long cachedPss = 0; + for (int i=0, N=memInfos.size(); i<N; i++) { + ProcessMemInfo mi = memInfos.get(i); + + if (mi.oomAdj >= ProcessList.CACHED_APP_MIN_ADJ) { + cachedPss += mi.pss; + } + + if (mi.oomAdj != ProcessList.NATIVE_ADJ + && (mi.oomAdj < ProcessList.SERVICE_ADJ + || mi.oomAdj == ProcessList.HOME_APP_ADJ + || mi.oomAdj == ProcessList.PREVIOUS_APP_ADJ)) { + if (lastOomAdj != mi.oomAdj) { + lastOomAdj = mi.oomAdj; + if (mi.oomAdj <= ProcessList.FOREGROUND_APP_ADJ) { + tag.append(" / "); + } + if (mi.oomAdj >= ProcessList.FOREGROUND_APP_ADJ) { + if (firstLine) { + stack.append(":"); + firstLine = false; + } + stack.append("\n\t at "); + } else { + stack.append("$"); + } + } else { + tag.append(" "); + stack.append("$"); + } + if (mi.oomAdj <= ProcessList.FOREGROUND_APP_ADJ) { + appendMemBucket(tag, mi.pss, mi.name, false); + } + appendMemBucket(stack, mi.pss, mi.name, true); + if (mi.oomAdj >= ProcessList.FOREGROUND_APP_ADJ + && ((i+1) >= N || memInfos.get(i+1).oomAdj != lastOomAdj)) { + stack.append("("); + for (int k=0; k<DUMP_MEM_OOM_ADJ.length; k++) { + if (DUMP_MEM_OOM_ADJ[k] == mi.oomAdj) { + stack.append(DUMP_MEM_OOM_LABEL[k]); + stack.append(":"); + stack.append(DUMP_MEM_OOM_ADJ[k]); + } + } + stack.append(")"); + } + } + + appendMemInfo(fullNativeBuilder, mi); + if (mi.oomAdj == ProcessList.NATIVE_ADJ) { + // The short form only has native processes that are >= 1MB. + if (mi.pss >= 1000) { + appendMemInfo(shortNativeBuilder, mi); + } else { + extraNativeRam += mi.pss; + } + } else { + // Short form has all other details, but if we have collected RAM + // from smaller native processes let's dump a summary of that. + if (extraNativeRam > 0) { + appendBasicMemEntry(shortNativeBuilder, ProcessList.NATIVE_ADJ, + -1, extraNativeRam, "(Other native)"); + shortNativeBuilder.append('\n'); + extraNativeRam = 0; + } + appendMemInfo(fullJavaBuilder, mi); + } + } + + fullJavaBuilder.append(" "); + ProcessList.appendRamKb(fullJavaBuilder, totalPss); + fullJavaBuilder.append(" kB: TOTAL\n"); + + MemInfoReader memInfo = new MemInfoReader(); + memInfo.readMemInfo(); + final long[] infos = memInfo.getRawInfo(); + + StringBuilder memInfoBuilder = new StringBuilder(1024); + Debug.getMemInfo(infos); + memInfoBuilder.append(" MemInfo: "); + memInfoBuilder.append(infos[Debug.MEMINFO_SLAB]).append(" kB slab, "); + memInfoBuilder.append(infos[Debug.MEMINFO_SHMEM]).append(" kB shmem, "); + memInfoBuilder.append(infos[Debug.MEMINFO_VM_ALLOC_USED]).append(" kB vm alloc, "); + memInfoBuilder.append(infos[Debug.MEMINFO_PAGE_TABLES]).append(" kB page tables "); + memInfoBuilder.append(infos[Debug.MEMINFO_KERNEL_STACK]).append(" kB kernel stack\n"); + memInfoBuilder.append(" "); + memInfoBuilder.append(infos[Debug.MEMINFO_BUFFERS]).append(" kB buffers, "); + memInfoBuilder.append(infos[Debug.MEMINFO_CACHED]).append(" kB cached, "); + memInfoBuilder.append(infos[Debug.MEMINFO_MAPPED]).append(" kB mapped, "); + memInfoBuilder.append(infos[Debug.MEMINFO_FREE]).append(" kB free\n"); + if (infos[Debug.MEMINFO_ZRAM_TOTAL] != 0) { + memInfoBuilder.append(" ZRAM: "); + memInfoBuilder.append(infos[Debug.MEMINFO_ZRAM_TOTAL]); + memInfoBuilder.append(" kB RAM, "); + memInfoBuilder.append(infos[Debug.MEMINFO_SWAP_TOTAL]); + memInfoBuilder.append(" kB swap total, "); + memInfoBuilder.append(infos[Debug.MEMINFO_SWAP_FREE]); + memInfoBuilder.append(" kB swap free\n"); + } + final long[] ksm = getKsmInfo(); + if (ksm[KSM_SHARING] != 0 || ksm[KSM_SHARED] != 0 || ksm[KSM_UNSHARED] != 0 + || ksm[KSM_VOLATILE] != 0) { + memInfoBuilder.append(" KSM: "); memInfoBuilder.append(ksm[KSM_SHARING]); + memInfoBuilder.append(" kB saved from shared "); + memInfoBuilder.append(ksm[KSM_SHARED]); memInfoBuilder.append(" kB\n"); + memInfoBuilder.append(" "); memInfoBuilder.append(ksm[KSM_UNSHARED]); + memInfoBuilder.append(" kB unshared; "); + memInfoBuilder.append(ksm[KSM_VOLATILE]); memInfoBuilder.append(" kB volatile\n"); + } + memInfoBuilder.append(" Free RAM: "); + memInfoBuilder.append(cachedPss + memInfo.getCachedSizeKb() + + memInfo.getFreeSizeKb()); + memInfoBuilder.append(" kB\n"); + memInfoBuilder.append(" Used RAM: "); + memInfoBuilder.append(totalPss - cachedPss + memInfo.getKernelUsedSizeKb()); + memInfoBuilder.append(" kB\n"); + memInfoBuilder.append(" Lost RAM: "); + memInfoBuilder.append(memInfo.getTotalSizeKb() + - totalPss - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb() + - memInfo.getKernelUsedSizeKb()); + memInfoBuilder.append(" kB\n"); + Slog.i(TAG, "Low on memory:"); + Slog.i(TAG, shortNativeBuilder.toString()); + Slog.i(TAG, fullJavaBuilder.toString()); + Slog.i(TAG, memInfoBuilder.toString()); + + StringBuilder dropBuilder = new StringBuilder(1024); + /* + StringWriter oomSw = new StringWriter(); + PrintWriter oomPw = new FastPrintWriter(oomSw, false, 256); + StringWriter catSw = new StringWriter(); + PrintWriter catPw = new FastPrintWriter(catSw, false, 256); + String[] emptyArgs = new String[] { }; + dumpApplicationMemoryUsage(null, oomPw, " ", emptyArgs, true, catPw); + oomPw.flush(); + String oomString = oomSw.toString(); + */ + dropBuilder.append("Low on memory:"); + dropBuilder.append(stack); + dropBuilder.append('\n'); + dropBuilder.append(fullNativeBuilder); + dropBuilder.append(fullJavaBuilder); + dropBuilder.append('\n'); + dropBuilder.append(memInfoBuilder); + dropBuilder.append('\n'); + /* + dropBuilder.append(oomString); + dropBuilder.append('\n'); + */ + StringWriter catSw = new StringWriter(); + synchronized (ActivityManagerService.this) { + PrintWriter catPw = new FastPrintWriter(catSw, false, 256); + String[] emptyArgs = new String[] { }; + catPw.println(); + dumpProcessesLocked(null, catPw, emptyArgs, 0, false, null); + catPw.println(); + mServices.dumpServicesLocked(null, catPw, emptyArgs, 0, + false, false, null); + catPw.println(); + dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false, null); + catPw.flush(); + } + dropBuilder.append(catSw.toString()); + addErrorToDropBox("lowmem", null, "system_server", null, + null, tag.toString(), dropBuilder.toString(), null, null); + //Slog.i(TAG, "Sent to dropbox:"); + //Slog.i(TAG, dropBuilder.toString()); + synchronized (ActivityManagerService.this) { + long now = SystemClock.uptimeMillis(); + if (mLastMemUsageReportTime < now) { + mLastMemUsageReportTime = now; + } + } + } + /** * Searches array of arguments for the specified string * @param args array of argument strings diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 03dd3c0c7e49..eaff6be64ed7 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -120,7 +120,7 @@ public final class ActivityStackSupervisor implements DisplayListener { static final boolean DEBUG_RELEASE = DEBUG || false; static final boolean DEBUG_SAVED_STATE = DEBUG || false; static final boolean DEBUG_SCREENSHOTS = DEBUG || false; - static final boolean DEBUG_STATES = DEBUG || false; + static final boolean DEBUG_STATES = DEBUG || true; static final boolean DEBUG_VISIBLE_BEHIND = DEBUG || false; public static final int HOME_STACK_ID = 0; @@ -444,10 +444,6 @@ public final class ActivityStackSupervisor implements DisplayListener { return mService.startHomeActivityLocked(mCurrentUser); } - void keyguardWaitingForActivityDrawn() { - mWindowManager.keyguardWaitingForActivityDrawn(); - } - TaskRecord anyTaskForIdLocked(int id) { int numDisplays = mActivityDisplays.size(); for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { diff --git a/services/core/java/com/android/server/am/LockTaskNotify.java b/services/core/java/com/android/server/am/LockTaskNotify.java index 5768ddbe8380..b3777ed30c21 100644 --- a/services/core/java/com/android/server/am/LockTaskNotify.java +++ b/services/core/java/com/android/server/am/LockTaskNotify.java @@ -19,6 +19,7 @@ package com.android.server.am; import android.content.Context; import android.os.Handler; import android.os.Message; +import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; import android.widget.Toast; @@ -56,8 +57,7 @@ public class LockTaskNotify { if (mLastToast != null) { mLastToast.cancel(); } - mLastToast = Toast.makeText(mContext, text, Toast.LENGTH_LONG); - mLastToast.show(); + mLastToast = makeAllUserToastAndShow(text); } public void show(boolean starting) { @@ -65,7 +65,15 @@ public class LockTaskNotify { if (starting) { showString = R.string.lock_to_app_start; } - Toast.makeText(mContext, mContext.getString(showString), Toast.LENGTH_LONG).show(); + makeAllUserToastAndShow(mContext.getString(showString)); + } + + private Toast makeAllUserToastAndShow(String text) { + Toast toast = Toast.makeText(mContext, text, Toast.LENGTH_LONG); + toast.getWindowParams().privateFlags |= + WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; + toast.show(); + return toast; } private final class H extends Handler { diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java index afc781fd32ee..b331c845a0e3 100644 --- a/services/core/java/com/android/server/am/TaskPersister.java +++ b/services/core/java/com/android/server/am/TaskPersister.java @@ -166,7 +166,7 @@ public class TaskPersister { break; } } - if (queueNdx < 0) { + if (queueNdx < 0 && task.isPersistable) { mWriteQueue.add(new TaskWriteQueueItem(task)); } } else { @@ -473,13 +473,15 @@ public class TaskPersister { if (DEBUG) Slog.d(TAG, "mRecents=" + tasks); for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { final TaskRecord task = tasks.get(taskNdx); - if (DEBUG) Slog.d(TAG, "LazyTaskWriter: task=" + task + " persistable=" + - task.isPersistable); - if (task.isPersistable && !task.stack.isHomeStack()) { + if (DEBUG) Slog.d(TAG, "LazyTaskWriter: task=" + task + + " persistable=" + task.isPersistable); + if ((task.isPersistable || task.inRecents) + && !task.stack.isHomeStack()) { if (DEBUG) Slog.d(TAG, "adding to persistentTaskIds task=" + task); persistentTaskIds.add(task.taskId); } else { - if (DEBUG) Slog.d(TAG, "omitting from persistentTaskIds task=" + task); + if (DEBUG) Slog.d(TAG, + "omitting from persistentTaskIds task=" + task); } } } diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 4dfd23b74bb8..ee932331f38a 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -144,7 +144,7 @@ final class TaskRecord { boolean mReuseTask = false; private Bitmap mLastThumbnail; // Last thumbnail captured for this item. - private final File mLastThumbnailFile; // File containing last thubmnail. + private final File mLastThumbnailFile; // File containing last thumbnail. private final String mFilename; CharSequence lastDescription; // Last description captured for this item. diff --git a/services/core/java/com/android/server/am/UserSwitchingDialog.java b/services/core/java/com/android/server/am/UserSwitchingDialog.java index dfc8df580a15..36263ece1f47 100644 --- a/services/core/java/com/android/server/am/UserSwitchingDialog.java +++ b/services/core/java/com/android/server/am/UserSwitchingDialog.java @@ -17,17 +17,11 @@ package com.android.server.am; import android.app.AlertDialog; -import android.app.Service; -import android.content.ActivityNotFoundException; import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; import android.content.res.Resources; -import android.os.Handler; -import android.os.Message; -import android.util.Slog; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewTreeObserver; import android.view.WindowManager; import android.widget.TextView; @@ -39,11 +33,10 @@ import com.android.internal.R; * in the background rather than just freeze the screen and not know if the user-switch affordance * was being handled. */ -final class UserSwitchingDialog extends AlertDialog { +final class UserSwitchingDialog extends AlertDialog + implements ViewTreeObserver.OnWindowShownListener { private static final String TAG = "ActivityManagerUserSwitchingDialog"; - private static final int MSG_START_USER = 1; - private final ActivityManagerService mService; private final int mUserId; @@ -74,19 +67,21 @@ final class UserSwitchingDialog extends AlertDialog { @Override public void show() { + // Slog.v(TAG, "show called"); super.show(); - // TODO: Instead of just an arbitrary delay, wait for a signal that the window was fully - // displayed by the window manager - mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_USER), 250); + final View decorView = getWindow().getDecorView(); + if (decorView != null) { + decorView.getViewTreeObserver().addOnWindowShownListener(this); + } } - private final Handler mHandler = new Handler() { - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_START_USER: - mService.startUserInForeground(mUserId, UserSwitchingDialog.this); - break; - } + @Override + public void onWindowShown() { + // Slog.v(TAG, "onWindowShown called"); + mService.startUserInForeground(mUserId, this); + final View decorView = getWindow().getDecorView(); + if (decorView != null) { + decorView.getViewTreeObserver().removeOnWindowShownListener(this); } - }; + } } diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index c382be07f6f1..576556b30648 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -17,6 +17,7 @@ package com.android.server.connectivity; import static android.net.ConnectivityManager.TYPE_MOBILE; +import static android.net.ConnectivityManager.TYPE_WIFI; import java.net.Inet4Address; @@ -43,45 +44,41 @@ import com.android.server.net.BaseNetworkObserver; * Class to manage a 464xlat CLAT daemon. */ public class Nat464Xlat extends BaseNetworkObserver { - private Context mContext; - private INetworkManagementService mNMService; - private IConnectivityManager mConnService; - // Whether we started clatd and expect it to be running. - private boolean mIsStarted; - // Whether the clatd interface exists (i.e., clatd is running). - private boolean mIsRunning; - // The LinkProperties of the clat interface. - private LinkProperties mLP; - // Current LinkProperties of the network. Includes mLP as a stacked link when clat is active. - private LinkProperties mBaseLP; + private static final String TAG = "Nat464Xlat"; + + // This must match the interface prefix in clatd.c. + private static final String CLAT_PREFIX = "v4-"; + + private final INetworkManagementService mNMService; + // ConnectivityService Handler for LinkProperties updates. - private Handler mHandler; - // Marker to connote which network we're augmenting. - private Messenger mNetworkMessenger; + private final Handler mHandler; - // This must match the interface name in clatd.conf. - private static final String CLAT_INTERFACE_NAME = "clat4"; + // The network we're running on, and its type. + private final NetworkAgentInfo mNetwork; - private static final String TAG = "Nat464Xlat"; + // Internal state variables. + // + // The possible states are: + // - Idle: start() not called. Everything is null. + // - Starting: start() called. Interfaces are non-null. isStarted() returns true. + // mIsRunning is false. + // - Running: start() called, and interfaceAdded() told us that mIface is up. Clat IP address + // is non-null. mIsRunning is true. + // + // Once mIface is non-null and isStarted() is true, methods called by ConnectivityService on + // its handler thread must not modify any internal state variables; they are only updated by the + // interface observers, called on the notification threads. + private String mBaseIface; + private String mIface; + private boolean mIsRunning; - public Nat464Xlat(Context context, INetworkManagementService nmService, - IConnectivityManager connService, Handler handler) { - mContext = context; + public Nat464Xlat( + Context context, INetworkManagementService nmService, + Handler handler, NetworkAgentInfo nai) { mNMService = nmService; - mConnService = connService; mHandler = handler; - - mIsStarted = false; - mIsRunning = false; - mLP = new LinkProperties(); - - // If this is a runtime restart, it's possible that clatd is already - // running, but we don't know about it. If so, stop it. - try { - if (mNMService.isClatdStarted()) { - mNMService.stopClatd(); - } - } catch(RemoteException e) {} // Well, we tried. + mNetwork = nai; } /** @@ -94,137 +91,196 @@ public class Nat464Xlat extends BaseNetworkObserver { final boolean connected = nai.networkInfo.isConnected(); final boolean hasIPv4Address = (nai.linkProperties != null) ? nai.linkProperties.hasIPv4Address() : false; - Slog.d(TAG, "requiresClat: netType=" + netType + - ", connected=" + connected + - ", hasIPv4Address=" + hasIPv4Address); - // Only support clat on mobile for now. - return netType == TYPE_MOBILE && connected && !hasIPv4Address; + // Only support clat on mobile and wifi for now, because these are the only IPv6-only + // networks we can connect to. + return connected && !hasIPv4Address && (netType == TYPE_MOBILE || netType == TYPE_WIFI); } - public boolean isRunningClat(NetworkAgentInfo network) { - return mNetworkMessenger == network.messenger; + /** + * Determines whether clatd is started. Always true, except a) if start has not yet been called, + * or b) if our interface was removed. + */ + public boolean isStarted() { + return mIface != null; + } + + /** + * Clears internal state. Must not be called by ConnectivityService. + */ + private void clear() { + mIface = null; + mBaseIface = null; + mIsRunning = false; } /** - * Starts the clat daemon. - * @param lp The link properties of the interface to start clatd on. + * Starts the clat daemon. Called by ConnectivityService on the handler thread. */ - public void startClat(NetworkAgentInfo network) { - if (mNetworkMessenger != null && mNetworkMessenger != network.messenger) { - Slog.e(TAG, "startClat: too many networks requesting clat"); + public void start() { + if (isStarted()) { + Slog.e(TAG, "startClat: already started"); return; } - mNetworkMessenger = network.messenger; - LinkProperties lp = network.linkProperties; - mBaseLP = new LinkProperties(lp); - if (mIsStarted) { - Slog.e(TAG, "startClat: already started"); + + if (mNetwork.linkProperties == null) { + Slog.e(TAG, "startClat: Can't start clat with null LinkProperties"); return; } - String iface = lp.getInterfaceName(); - Slog.i(TAG, "Starting clatd on " + iface + ", lp=" + lp); + try { - mNMService.startClatd(iface); + mNMService.registerObserver(this); } catch(RemoteException e) { - Slog.e(TAG, "Error starting clat daemon: " + e); + Slog.e(TAG, "startClat: Can't register interface observer for clat on " + mNetwork); + return; + } + + mBaseIface = mNetwork.linkProperties.getInterfaceName(); + if (mBaseIface == null) { + Slog.e(TAG, "startClat: Can't start clat on null interface"); + return; + } + mIface = CLAT_PREFIX + mBaseIface; + // From now on, isStarted() will return true. + + Slog.i(TAG, "Starting clatd on " + mBaseIface); + try { + mNMService.startClatd(mBaseIface); + } catch(RemoteException|IllegalStateException e) { + Slog.e(TAG, "Error starting clatd: " + e); } - mIsStarted = true; } /** - * Stops the clat daemon. + * Stops the clat daemon. Called by ConnectivityService on the handler thread. */ - public void stopClat() { - if (mIsStarted) { + public void stop() { + if (isStarted()) { Slog.i(TAG, "Stopping clatd"); try { - mNMService.stopClatd(); - } catch(RemoteException e) { - Slog.e(TAG, "Error stopping clat daemon: " + e); + mNMService.stopClatd(mBaseIface); + } catch(RemoteException|IllegalStateException e) { + Slog.e(TAG, "Error stopping clatd: " + e); } - mIsStarted = false; - mIsRunning = false; - mNetworkMessenger = null; - mBaseLP = null; - mLP.clear(); + // When clatd stops and its interface is deleted, interfaceRemoved() will notify + // ConnectivityService and call clear(). } else { - Slog.e(TAG, "stopClat: already stopped"); + Slog.e(TAG, "clatd: already stopped"); } } - private void updateConnectivityService() { - Message msg = mHandler.obtainMessage( - NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED, mBaseLP); - msg.replyTo = mNetworkMessenger; + private void updateConnectivityService(LinkProperties lp) { + Message msg = mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED, lp); + msg.replyTo = mNetwork.messenger; Slog.i(TAG, "sending message to ConnectivityService: " + msg); msg.sendToTarget(); } - // Copies the stacked clat link in oldLp, if any, to the LinkProperties in nai. - public void fixupLinkProperties(NetworkAgentInfo nai, LinkProperties oldLp) { - if (isRunningClat(nai) && - nai.linkProperties != null && - !nai.linkProperties.getAllInterfaceNames().contains(CLAT_INTERFACE_NAME)) { - Slog.d(TAG, "clatd running, updating NAI for " + nai.linkProperties.getInterfaceName()); + /** + * Copies the stacked clat link in oldLp, if any, to the LinkProperties in mNetwork. + * This is necessary because the LinkProperties in mNetwork come from the transport layer, which + * has no idea that 464xlat is running on top of it. + */ + public void fixupLinkProperties(LinkProperties oldLp) { + if (mNetwork.clatd != null && + mIsRunning && + mNetwork.linkProperties != null && + !mNetwork.linkProperties.getAllInterfaceNames().contains(mIface)) { + Slog.d(TAG, "clatd running, updating NAI for " + mIface); for (LinkProperties stacked: oldLp.getStackedLinks()) { - if (CLAT_INTERFACE_NAME.equals(stacked.getInterfaceName())) { - nai.linkProperties.addStackedLink(stacked); + if (mIface.equals(stacked.getInterfaceName())) { + mNetwork.linkProperties.addStackedLink(stacked); break; } } } } + private LinkProperties makeLinkProperties(LinkAddress clatAddress) { + LinkProperties stacked = new LinkProperties(); + stacked.setInterfaceName(mIface); + + // Although the clat interface is a point-to-point tunnel, we don't + // point the route directly at the interface because some apps don't + // understand routes without gateways (see, e.g., http://b/9597256 + // http://b/9597516). Instead, set the next hop of the route to the + // clat IPv4 address itself (for those apps, it doesn't matter what + // the IP of the gateway is, only that there is one). + RouteInfo ipv4Default = new RouteInfo( + new LinkAddress(Inet4Address.ANY, 0), + clatAddress.getAddress(), mIface); + stacked.addRoute(ipv4Default); + stacked.addLinkAddress(clatAddress); + return stacked; + } + + private LinkAddress getLinkAddress(String iface) { + try { + InterfaceConfiguration config = mNMService.getInterfaceConfig(iface); + return config.getLinkAddress(); + } catch(RemoteException|IllegalStateException e) { + Slog.e(TAG, "Error getting link properties: " + e); + return null; + } + } + + private void maybeSetIpv6NdOffload(String iface, boolean on) { + if (mNetwork.networkInfo.getType() != TYPE_WIFI) { + return; + } + try { + Slog.d(TAG, (on ? "En" : "Dis") + "abling ND offload on " + iface); + mNMService.setInterfaceIpv6NdOffload(iface, on); + } catch(RemoteException|IllegalStateException e) { + Slog.w(TAG, "Changing IPv6 ND offload on " + iface + "failed: " + e); + } + } + @Override public void interfaceAdded(String iface) { - if (iface.equals(CLAT_INTERFACE_NAME)) { - Slog.i(TAG, "interface " + CLAT_INTERFACE_NAME + - " added, mIsRunning = " + mIsRunning + " -> true"); - mIsRunning = true; - - // Create the LinkProperties for the clat interface by fetching the - // IPv4 address for the interface and adding an IPv4 default route, - // then stack the LinkProperties on top of the link it's running on. - try { - InterfaceConfiguration config = mNMService.getInterfaceConfig(iface); - LinkAddress clatAddress = config.getLinkAddress(); - mLP.clear(); - mLP.setInterfaceName(iface); - - // Although the clat interface is a point-to-point tunnel, we don't - // point the route directly at the interface because some apps don't - // understand routes without gateways (see, e.g., http://b/9597256 - // http://b/9597516). Instead, set the next hop of the route to the - // clat IPv4 address itself (for those apps, it doesn't matter what - // the IP of the gateway is, only that there is one). - RouteInfo ipv4Default = new RouteInfo(new LinkAddress(Inet4Address.ANY, 0), - clatAddress.getAddress(), iface); - mLP.addRoute(ipv4Default); - mLP.addLinkAddress(clatAddress); - mBaseLP.addStackedLink(mLP); - Slog.i(TAG, "Adding stacked link. tracker LP: " + mBaseLP); - updateConnectivityService(); - } catch(RemoteException e) { - Slog.e(TAG, "Error getting link properties: " + e); + // Called by the InterfaceObserver on its own thread, so can race with stop(). + if (isStarted() && mIface.equals(iface)) { + Slog.i(TAG, "interface " + iface + " added, mIsRunning " + mIsRunning + "->true"); + + if (!mIsRunning) { + LinkAddress clatAddress = getLinkAddress(iface); + if (clatAddress == null) { + return; + } + mIsRunning = true; + maybeSetIpv6NdOffload(mBaseIface, false); + LinkProperties lp = new LinkProperties(mNetwork.linkProperties); + lp.addStackedLink(makeLinkProperties(clatAddress)); + Slog.i(TAG, "Adding stacked link " + mIface + " on top of " + mBaseIface); + updateConnectivityService(lp); } } } @Override public void interfaceRemoved(String iface) { - if (iface == CLAT_INTERFACE_NAME) { + if (isStarted() && mIface.equals(iface)) { + Slog.i(TAG, "interface " + iface + " removed, mIsRunning " + mIsRunning + "->false"); + if (mIsRunning) { - NetworkUtils.resetConnections( - CLAT_INTERFACE_NAME, - NetworkUtils.RESET_IPV4_ADDRESSES); - mBaseLP.removeStackedLink(mLP); - updateConnectivityService(); + // The interface going away likely means clatd has crashed. Ask netd to stop it, + // because otherwise when we try to start it again on the same base interface netd + // will complain that it's already started. + // + // Note that this method can be called by the interface observer at the same time + // that ConnectivityService calls stop(). In this case, the second call to + // stopClatd() will just throw IllegalStateException, which we'll ignore. + try { + mNMService.unregisterObserver(this); + mNMService.stopClatd(mBaseIface); + } catch (RemoteException|IllegalStateException e) { + // Well, we tried. + } + maybeSetIpv6NdOffload(mBaseIface, true); + LinkProperties lp = new LinkProperties(mNetwork.linkProperties); + lp.removeStackedLink(mIface); + clear(); + updateConnectivityService(lp); } - Slog.i(TAG, "interface " + CLAT_INTERFACE_NAME + - " removed, mIsRunning = " + mIsRunning + " -> false"); - mIsRunning = false; - mLP.clear(); - Slog.i(TAG, "mLP = " + mLP); } } -}; +} diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 15ffc0d89154..4cf2a4acb86e 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -63,6 +63,9 @@ public class NetworkAgentInfo { public final Messenger messenger; public final AsyncChannel asyncChannel; + // Used by ConnectivityService to keep track of 464xlat. + public Nat464Xlat clatd; + public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, NetworkInfo info, LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler, NetworkMisc misc) { diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java index 07fe7ba79582..7d1da01b8ca6 100644 --- a/services/core/java/com/android/server/connectivity/PacManager.java +++ b/services/core/java/com/android/server/connectivity/PacManager.java @@ -265,14 +265,9 @@ public class PacManager { } Intent intent = new Intent(); intent.setClassName(PAC_PACKAGE, PAC_SERVICE); - // Already bound no need to bind again. if ((mProxyConnection != null) && (mConnection != null)) { - if (mLastPort != -1) { - sendPacBroadcast(new ProxyInfo(mPacUrl, mLastPort)); - } else { - Log.e(TAG, "Received invalid port from Local Proxy," - + " PAC will not be operational"); - } + // Already bound no need to bind again, just download the new file. + IoThread.getHandler().post(mPacDownloader); return; } mConnection = new ServiceConnection() { diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 3f6b71a556c9..83756aa8cd06 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -215,7 +215,7 @@ public class Vpn { */ public synchronized boolean prepare(String oldPackage, String newPackage) { // Return false if the package does not match. - if (oldPackage != null && !oldPackage.equals(mPackage)) { + if (oldPackage != null && getAppUid(oldPackage, mUserHandle) != mOwnerUID) { // The package doesn't match. If this VPN was not previously authorized, return false // to force user authorization. Otherwise, revoke the VPN anyway. if (!oldPackage.equals(VpnConfig.LEGACY_VPN) && isVpnUserPreConsented(oldPackage)) { @@ -234,8 +234,8 @@ public class Vpn { } // Return true if we do not need to revoke. - if (newPackage == null || - (newPackage.equals(mPackage) && !newPackage.equals(VpnConfig.LEGACY_VPN))) { + if (newPackage == null || (!newPackage.equals(VpnConfig.LEGACY_VPN) && + getAppUid(newPackage, mUserHandle) == mOwnerUID)) { return true; } diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java index 3b23b6add8a0..f51453145842 100644 --- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java +++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java @@ -248,6 +248,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter { mInfo.width = mWidth; mInfo.height = mHeight; mInfo.refreshRate = mRefreshRate; + mInfo.supportedRefreshRates = new float[] { mRefreshRate }; mInfo.densityDpi = mDensityDpi; mInfo.xDpi = mDensityDpi; mInfo.yDpi = mDensityDpi; diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java index c2b4478e5f3c..0232bad0605c 100644 --- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java +++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java @@ -257,6 +257,7 @@ final class VirtualDisplayAdapter extends DisplayAdapter { mInfo.width = mWidth; mInfo.height = mHeight; mInfo.refreshRate = 60; + mInfo.supportedRefreshRates = new float[] { 60.0f }; mInfo.densityDpi = mDensityDpi; mInfo.xDpi = mDensityDpi; mInfo.yDpi = mDensityDpi; diff --git a/services/core/java/com/android/server/display/WifiDisplayAdapter.java b/services/core/java/com/android/server/display/WifiDisplayAdapter.java index a17d7319e20f..6b010d9a2c86 100644 --- a/services/core/java/com/android/server/display/WifiDisplayAdapter.java +++ b/services/core/java/com/android/server/display/WifiDisplayAdapter.java @@ -625,6 +625,7 @@ final class WifiDisplayAdapter extends DisplayAdapter { mInfo.width = mWidth; mInfo.height = mHeight; mInfo.refreshRate = mRefreshRate; + mInfo.supportedRefreshRates = new float[] { mRefreshRate }; mInfo.presentationDeadlineNanos = 1000000000L / (int) mRefreshRate; // 1 frame mInfo.flags = mFlags; mInfo.type = Display.TYPE_WIFI; diff --git a/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java b/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java index cb921125230f..9593a9cb8e8a 100644 --- a/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java +++ b/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java @@ -57,8 +57,9 @@ final class ActiveSourceHandler { * Handles the incoming active source command. * * @param newActive new active source information + * @param deviceType device type of the new active source */ - void process(ActiveSource newActive) { + void process(ActiveSource newActive, int deviceType) { // Seq #17 HdmiCecLocalDeviceTv tv = mSource; ActiveSource activeSource = tv.getActiveSource(); @@ -68,7 +69,7 @@ final class ActiveSourceHandler { } HdmiDeviceInfo device = mService.getDeviceInfo(newActive.logicalAddress); if (device == null) { - tv.startNewDeviceAction(newActive); + tv.startNewDeviceAction(newActive, deviceType); } if (!tv.isProhibitMode()) { diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java index b0a3a6601df9..bb12eae614a6 100644 --- a/services/core/java/com/android/server/hdmi/Constants.java +++ b/services/core/java/com/android/server/hdmi/Constants.java @@ -205,13 +205,6 @@ final class Constants { static final int UNKNOWN_VOLUME = -1; - // IRT(Initiator Repetition Time) in millisecond as recommended in the standard. - // Outgoing UCP commands, when in 'Press and Hold' mode, should be this much apart - // from the adjacent one so as not to place unnecessarily heavy load on the CEC line. - // TODO: This value might need tweaking per product basis. Consider putting it - // in config.xml to allow customization. - static final int IRT_MS = 300; - static final String PROPERTY_PREFERRED_ADDRESS_PLAYBACK = "persist.sys.hdmi.addr.playback"; static final String PROPERTY_PREFERRED_ADDRESS_TV = "persist.sys.hdmi.addr.tv"; diff --git a/services/core/java/com/android/server/hdmi/DevicePowerStatusAction.java b/services/core/java/com/android/server/hdmi/DevicePowerStatusAction.java index d965caaadc14..3dd152253f0d 100644 --- a/services/core/java/com/android/server/hdmi/DevicePowerStatusAction.java +++ b/services/core/java/com/android/server/hdmi/DevicePowerStatusAction.java @@ -70,7 +70,8 @@ final class DevicePowerStatusAction extends HdmiCecFeatureAction { @Override boolean processCommand(HdmiCecMessage cmd) { - if (mState != STATE_WAITING_FOR_REPORT_POWER_STATUS) { + if (mState != STATE_WAITING_FOR_REPORT_POWER_STATUS + || mTargetAddress != cmd.getSource()) { return false; } if (cmd.getOpcode() == Constants.MESSAGE_REPORT_POWER_STATUS) { diff --git a/services/core/java/com/android/server/hdmi/DeviceSelectAction.java b/services/core/java/com/android/server/hdmi/DeviceSelectAction.java index d155e849d46e..5a1d896c74a6 100644 --- a/services/core/java/com/android/server/hdmi/DeviceSelectAction.java +++ b/services/core/java/com/android/server/hdmi/DeviceSelectAction.java @@ -95,7 +95,7 @@ final class DeviceSelectAction extends HdmiCecFeatureAction { sendCommand(mGivePowerStatus, new SendMessageCallback() { @Override public void onSendCompleted(int error) { - if (error == Constants.SEND_RESULT_NAK) { + if (error != Constants.SEND_RESULT_SUCCESS) { invokeCallback(HdmiControlManager.RESULT_COMMUNICATION_FAILED); finish(); return; @@ -168,6 +168,10 @@ final class DeviceSelectAction extends HdmiCecFeatureAction { } private void sendSetStreamPath() { + // Turn the active source invalidated, which remains so till <Active Source> comes from + // the selected device. + tv().getActiveSource().invalidate(); + tv().setActivePath(mTarget.getPhysicalAddress()); sendCommand(HdmiCecMessageBuilder.buildSetStreamPath( getSourceAddress(), mTarget.getPhysicalAddress())); invokeCallback(HdmiControlManager.RESULT_SUCCESS); diff --git a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java index fc53c50c3fcb..d26be575f214 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java @@ -85,8 +85,7 @@ abstract class HdmiCecFeatureAction { * Process the command. Called whenever a new command arrives. * * @param cmd command to process - * @return true if the command was consumed in the process; Otherwise false, which - * indicates that the command shall be handled by other actions. + * @return true if the command was consumed in the process; Otherwise false. */ abstract boolean processCommand(HdmiCecMessage cmd); diff --git a/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java b/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java index 61c94247b599..2eca42b94d6b 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java @@ -18,6 +18,10 @@ package com.android.server.hdmi; import android.view.KeyEvent; +import libcore.util.EmptyArray; + +import java.util.Arrays; + /** * Helper class to translate android keycode to hdmi cec keycode and vice versa. */ @@ -156,46 +160,60 @@ final class HdmiCecKeycode { /** * A mapping between Android and CEC keycode. + * <p> + * Normal implementation of this looks like * - * <p>Normal implementation of this looks like * <pre> - * new KeycodeEntry(KeyEvent.KEYCODE_DPAD_CENTER, CEC_KEYCODE_SELECT); + * new KeycodeEntry(KeyEvent.KEYCODE_DPAD_CENTER, CEC_KEYCODE_SELECT); * </pre> - * <p>However, some keys in CEC requires additional parameter. - * In order to use parameterized cec key, add unique android keycode (existing or custom) - * corresponding to a pair of cec keycode and and its param. + * <p> + * However, some keys in CEC requires additional parameter. In order to use parameterized cec + * key, add unique android keycode (existing or custom) corresponding to a pair of cec keycode + * and and its param. + * * <pre> - * new KeycodeEntry(CUSTOME_ANDORID_KEY_1, CEC_KEYCODE_SELECT_BROADCAST_TYPE, - * UI_BROADCAST_TOGGLE_ALL); - * new KeycodeEntry(CUSTOME_ANDORID_KEY_2, CEC_KEYCODE_SELECT_BROADCAST_TYPE, - * UI_BROADCAST_ANALOGUE); + * new KeycodeEntry(CUSTOME_ANDORID_KEY_1, CEC_KEYCODE_SELECT_BROADCAST_TYPE, + * UI_BROADCAST_TOGGLE_ALL); + * new KeycodeEntry(CUSTOME_ANDORID_KEY_2, CEC_KEYCODE_SELECT_BROADCAST_TYPE, + * UI_BROADCAST_ANALOGUE); * </pre> */ private static class KeycodeEntry { private final int mAndroidKeycode; - private final int mCecKeycode; private final boolean mIsRepeatable; + private final byte[] mCecKeycodeAndParams; - private KeycodeEntry(int androidKeycode, int cecKeycode, boolean isRepeatable) { + private KeycodeEntry(int androidKeycode, int cecKeycode, boolean isRepeatable, + byte[] cecParams) { mAndroidKeycode = androidKeycode; - mCecKeycode = cecKeycode; mIsRepeatable = isRepeatable; + mCecKeycodeAndParams = new byte[cecParams.length + 1]; + System.arraycopy(cecParams, 0, mCecKeycodeAndParams, 1, cecParams.length); + mCecKeycodeAndParams[0] = (byte) (cecKeycode & 0xFF); + } + + private KeycodeEntry(int androidKeycode, int cecKeycode, boolean isRepeatable) { + this(androidKeycode, cecKeycode, isRepeatable, EmptyArray.BYTE); + } + + private KeycodeEntry(int androidKeycode, int cecKeycode, byte[] cecParams) { + this(androidKeycode, cecKeycode, true, cecParams); } private KeycodeEntry(int androidKeycode, int cecKeycode) { - this(androidKeycode, cecKeycode, true); + this(androidKeycode, cecKeycode, true, EmptyArray.BYTE); } - private int toCecKeycodeIfMatched(int androidKeycode) { + private byte[] toCecKeycodeAndParamIfMatched(int androidKeycode) { if (mAndroidKeycode == androidKeycode) { - return mCecKeycode; + return mCecKeycodeAndParams; } else { - return UNSUPPORTED_KEYCODE; + return null; } } - private int toAndroidKeycodeIfMatched(int cecKeycode) { - if (cecKeycode == mCecKeycode) { + private int toAndroidKeycodeIfMatched(byte[] cecKeycodeAndParams) { + if (Arrays.equals(mCecKeycodeAndParams, cecKeycodeAndParams)) { return mAndroidKeycode; } else { return UNSUPPORTED_KEYCODE; @@ -211,6 +229,11 @@ final class HdmiCecKeycode { } } + private static byte[] intToSingleByteArray(int value) { + return new byte[] { + (byte) (value & 0xFF) }; + } + // Keycode entry container for all mappings. // Note that order of entry is the same as above cec keycode definition. private static final KeycodeEntry[] KEYCODE_ENTRIES = new KeycodeEntry[] { @@ -227,19 +250,25 @@ final class HdmiCecKeycode { new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_LEFT_UP), // No Android keycode defined for CEC_KEYCODE_LEFT_DOWN new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_LEFT_DOWN), - new KeycodeEntry(KeyEvent.KEYCODE_HOME, CEC_KEYCODE_ROOT_MENU, false), - new KeycodeEntry(KeyEvent.KEYCODE_SETTINGS, CEC_KEYCODE_SETUP_MENU, false), - new KeycodeEntry(KeyEvent.KEYCODE_MENU, CEC_KEYCODE_CONTENTS_MENU, false), + new KeycodeEntry(KeyEvent.KEYCODE_HOME, CEC_KEYCODE_ROOT_MENU), + new KeycodeEntry(KeyEvent.KEYCODE_SETTINGS, CEC_KEYCODE_SETUP_MENU), + new KeycodeEntry(KeyEvent.KEYCODE_TV_CONTENTS_MENU, CEC_KEYCODE_CONTENTS_MENU, false), // No Android keycode defined for CEC_KEYCODE_FAVORITE_MENU new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_FAVORITE_MENU), + // Note that both BACK and ESCAPE are mapped to EXIT of CEC keycode. + // This would be problematic when translates CEC keycode to Android keycode. + // In current implementation, we pick BACK as mapping of EXIT key. + // If you'd like to map CEC EXIT to Android EXIT key, change order of + // the following two definition. new KeycodeEntry(KeyEvent.KEYCODE_BACK, CEC_KEYCODE_EXIT), + new KeycodeEntry(KeyEvent.KEYCODE_ESCAPE, CEC_KEYCODE_EXIT), // RESERVED new KeycodeEntry(KeyEvent.KEYCODE_MEDIA_TOP_MENU, CEC_KEYCODE_MEDIA_TOP_MENU), - // No Android keycode defined for CEC_KEYCODE_MEDIA_CONTEXT_SENSITIVE_MENU - new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_MEDIA_CONTEXT_SENSITIVE_MENU), + new KeycodeEntry(KeyEvent.KEYCODE_TV_MEDIA_CONTEXT_MENU, + CEC_KEYCODE_MEDIA_CONTEXT_SENSITIVE_MENU), // RESERVED // No Android keycode defined for CEC_KEYCODE_NUMBER_ENTRY_MODE - new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_NUMBER_ENTRY_MODE), + new KeycodeEntry(KeyEvent.KEYCODE_TV_NUMBER_ENTRY, CEC_KEYCODE_NUMBER_ENTRY_MODE), new KeycodeEntry(KeyEvent.KEYCODE_11, CEC_KEYCODE_NUMBER_11), new KeycodeEntry(KeyEvent.KEYCODE_12, CEC_KEYCODE_NUMBER_12), new KeycodeEntry(KeyEvent.KEYCODE_0, CEC_KEYCODE_NUMBER_0_OR_NUMBER_10), @@ -276,7 +305,12 @@ final class HdmiCecKeycode { new KeycodeEntry(KeyEvent.KEYCODE_VOLUME_MUTE, CEC_KEYCODE_MUTE, false), new KeycodeEntry(KeyEvent.KEYCODE_MEDIA_PLAY, CEC_KEYCODE_PLAY), new KeycodeEntry(KeyEvent.KEYCODE_MEDIA_STOP, CEC_KEYCODE_STOP), + // Note that we map both MEDIA_PAUSE and MEDIA_PLAY_PAUSE to CEC PAUSE key. + // When it translates CEC PAUSE key, it picks Android MEDIA_PAUSE key as a mapping of + // it. If you'd like to choose MEDIA_PLAY_PAUSE, please change order of the following + // two lines. new KeycodeEntry(KeyEvent.KEYCODE_MEDIA_PAUSE, CEC_KEYCODE_PAUSE), + new KeycodeEntry(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, CEC_KEYCODE_PAUSE), new KeycodeEntry(KeyEvent.KEYCODE_MEDIA_RECORD, CEC_KEYCODE_RECORD), new KeycodeEntry(KeyEvent.KEYCODE_MEDIA_REWIND, CEC_KEYCODE_REWIND), new KeycodeEntry(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, CEC_KEYCODE_FAST_FORWARD), @@ -291,48 +325,61 @@ final class HdmiCecKeycode { new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_RESERVED), // No Android keycode defined for CEC_KEYCODE_ANGLE new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_ANGLE), - // No Android keycode defined for CEC_KEYCODE_SUB_PICTURE - new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_SUB_PICTURE), + new KeycodeEntry(KeyEvent.KEYCODE_CAPTIONS, CEC_KEYCODE_SUB_PICTURE), // No Android keycode defined for CEC_KEYCODE_VIDEO_ON_DEMAND new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_VIDEO_ON_DEMAND), new KeycodeEntry(KeyEvent.KEYCODE_GUIDE, CEC_KEYCODE_ELECTRONIC_PROGRAM_GUIDE), - // No Android keycode defined for CEC_KEYCODE_TIMER_PROGRAMMING - new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_TIMER_PROGRAMMING), + new KeycodeEntry(KeyEvent.KEYCODE_TV_TIMER_PROGRAMMING, CEC_KEYCODE_TIMER_PROGRAMMING), // No Android keycode defined for CEC_KEYCODE_INITIAL_CONFIGURATION new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_INITIAL_CONFIGURATION), // No Android keycode defined for CEC_KEYCODE_SELECT_BROADCAST_TYPE new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_SELECT_BROADCAST_TYPE), + new KeycodeEntry(KeyEvent.KEYCODE_TV_TERRESTRIAL_ANALOG, + CEC_KEYCODE_SELECT_BROADCAST_TYPE, true, + intToSingleByteArray(UI_BROADCAST_ANALOGUE)), + new KeycodeEntry(KeyEvent.KEYCODE_TV_TERRESTRIAL_DIGITAL, + CEC_KEYCODE_SELECT_BROADCAST_TYPE, true, + intToSingleByteArray(UI_BROADCAST_DIGITAL_TERRESTRIAL)), + new KeycodeEntry(KeyEvent.KEYCODE_TV_SATELLITE_BS, + CEC_KEYCODE_SELECT_BROADCAST_TYPE, true, + intToSingleByteArray(UI_BROADCAST_DIGITAL_SATELLITE)), + new KeycodeEntry(KeyEvent.KEYCODE_TV_SATELLITE_CS, + CEC_KEYCODE_SELECT_BROADCAST_TYPE, true, + intToSingleByteArray(UI_BROADCAST_DIGITAL_COMMNICATIONS_SATELLITE)), + new KeycodeEntry(KeyEvent.KEYCODE_TV_NETWORK, + CEC_KEYCODE_SELECT_BROADCAST_TYPE, true, + intToSingleByteArray(UI_BROADCAST_TOGGLE_ANALOGUE_DIGITAL)), // No Android keycode defined for CEC_KEYCODE_SELECT_SOUND_PRESENTATION new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_SELECT_SOUND_PRESENTATION), // RESERVED // The following deterministic key definitions do not need key mapping // since they are supposed to be generated programmatically only. // No Android keycode defined for CEC_KEYCODE_PLAY_FUNCTION - new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_PLAY_FUNCTION), + new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_PLAY_FUNCTION, false), // No Android keycode defined for CEC_KEYCODE_PAUSE_PLAY_FUNCTION - new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_PAUSE_PLAY_FUNCTION), + new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_PAUSE_PLAY_FUNCTION, false), // No Android keycode defined for CEC_KEYCODE_RECORD_FUNCTION - new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_RECORD_FUNCTION), + new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_RECORD_FUNCTION, false), // No Android keycode defined for CEC_KEYCODE_PAUSE_RECORD_FUNCTION - new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_PAUSE_RECORD_FUNCTION), + new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_PAUSE_RECORD_FUNCTION, false), // No Android keycode defined for CEC_KEYCODE_STOP_FUNCTION - new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_STOP_FUNCTION), + new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_STOP_FUNCTION, false), // No Android keycode defined for CEC_KEYCODE_MUTE_FUNCTION new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_MUTE_FUNCTION, false), // No Android keycode defined for CEC_KEYCODE_RESTORE_VOLUME_FUNCTION new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_RESTORE_VOLUME_FUNCTION, false), // No Android keycode defined for CEC_KEYCODE_TUNE_FUNCTION - new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_TUNE_FUNCTION), + new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_TUNE_FUNCTION, false), // No Android keycode defined for CEC_KEYCODE_SELECT_MEDIA_FUNCTION - new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_SELECT_MEDIA_FUNCTION), + new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_SELECT_MEDIA_FUNCTION, false), // No Android keycode defined for CEC_KEYCODE_SELECT_AV_INPUT_FUNCTION - new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_SELECT_AV_INPUT_FUNCTION), + new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_SELECT_AV_INPUT_FUNCTION, false), // No Android keycode defined for CEC_KEYCODE_SELECT_AUDIO_INPUT_FUNCTION - new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_SELECT_AUDIO_INPUT_FUNCTION), + new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_SELECT_AUDIO_INPUT_FUNCTION, false), // No Android keycode defined for CEC_KEYCODE_POWER_TOGGLE_FUNCTION - new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_POWER_TOGGLE_FUNCTION), + new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_POWER_TOGGLE_FUNCTION, false), // No Android keycode defined for CEC_KEYCODE_POWER_OFF_FUNCTION - new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_POWER_OFF_FUNCTION), + new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_POWER_OFF_FUNCTION, false), // No Android keycode defined for CEC_KEYCODE_POWER_ON_FUNCTION new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_POWER_ON_FUNCTION, false), // RESERVED @@ -347,31 +394,31 @@ final class HdmiCecKeycode { }; /** - * Translate Android keycode to Hdmi Cec keycode. + * Translate Android keycode to Hdmi Cec keycode and params. * * @param keycode Android keycode. For details, refer {@link KeyEvent} - * @return single byte CEC keycode if matched. + * @return byte array of CEC keycode and params if matched. Otherwise, return null. */ - static int androidKeyToCecKey(int keycode) { + static byte[] androidKeyToCecKey(int keycode) { for (int i = 0; i < KEYCODE_ENTRIES.length; ++i) { - int cecKeycode = KEYCODE_ENTRIES[i].toCecKeycodeIfMatched(keycode); - if (cecKeycode != UNSUPPORTED_KEYCODE) { - return cecKeycode; + byte[] cecKeycodeAndParams = KEYCODE_ENTRIES[i].toCecKeycodeAndParamIfMatched(keycode); + if (cecKeycodeAndParams != null) { + return cecKeycodeAndParams; } } - return UNSUPPORTED_KEYCODE; + return null; } /** - * Translate Hdmi CEC keycode to Android keycode. + * Translate Hdmi CEC keycode with params to Android keycode. * - * @param keycode CEC keycode - * @return cec keycode corresponding to the given android keycode. - * If finds no matched keycode, return {@link #UNSUPPORTED_KEYCODE} + * @param cecKeycodeAndParams CEC keycode and params + * @return cec keycode corresponding to the given android keycode. If finds no matched keycode, + * return {@link #UNSUPPORTED_KEYCODE} */ - static int cecKeyToAndroidKey(int keycode) { + static int cecKeycodeAndParamsToAndroidKey(byte[] cecKeycodeAndParams) { for (int i = 0; i < KEYCODE_ENTRIES.length; ++i) { - int androidKey = KEYCODE_ENTRIES[i].toAndroidKeycodeIfMatched(keycode); + int androidKey = KEYCODE_ENTRIES[i].toAndroidKeycodeIfMatched(cecKeycodeAndParams); if (androidKey != UNSUPPORTED_KEYCODE) { return androidKey; } @@ -399,7 +446,6 @@ final class HdmiCecKeycode { * Returns {@code true} if given Android keycode is supported, otherwise {@code false}. */ static boolean isSupportedKeycode(int androidKeycode) { - return HdmiCecKeycode.androidKeyToCecKey(androidKeycode) - != HdmiCecKeycode.UNSUPPORTED_KEYCODE; - } + return HdmiCecKeycode.androidKeyToCecKey(androidKeycode) != null; + } } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java index 8f9af61980a3..4f8b9fbc71f5 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java @@ -34,7 +34,6 @@ import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; /** @@ -125,7 +124,7 @@ abstract class HdmiCecLocalDevice { // A collection of FeatureAction. // Note that access to this collection should happen in service thread. - private final LinkedList<HdmiCecFeatureAction> mActions = new LinkedList<>(); + private final ArrayList<HdmiCecFeatureAction> mActions = new ArrayList<>(); private final Handler mHandler = new Handler () { @Override @@ -290,12 +289,14 @@ abstract class HdmiCecLocalDevice { @ServiceThreadOnly private boolean dispatchMessageToAction(HdmiCecMessage message) { assertRunOnServiceThread(); - for (HdmiCecFeatureAction action : mActions) { - if (action.processCommand(message)) { - return true; - } + boolean processed = false; + // Use copied action list in that processCommand may remove itself. + for (HdmiCecFeatureAction action : new ArrayList<>(mActions)) { + // Iterates all actions to check whether incoming message is consumed. + boolean result = action.processCommand(message); + processed = processed || result; } - return false; + return processed; } @ServiceThreadOnly @@ -425,9 +426,7 @@ abstract class HdmiCecLocalDevice { final long downTime = SystemClock.uptimeMillis(); final byte[] params = message.getParams(); - // Note that we don't support parameterized keycode now. - // TODO: translate parameterized keycode as well. - final int keycode = HdmiCecKeycode.cecKeyToAndroidKey(params[0]); + final int keycode = HdmiCecKeycode.cecKeycodeAndParamsToAndroidKey(params); int keyRepeatCount = 0; if (mLastKeycode != HdmiCecKeycode.UNSUPPORTED_KEYCODE) { if (keycode == mLastKeycode) { @@ -517,8 +516,8 @@ abstract class HdmiCecLocalDevice { } protected boolean handleVendorCommand(HdmiCecMessage message) { - if (!mService.invokeVendorCommandListeners(mDeviceType, message.getSource(), - message.getParams(), false)) { + if (!mService.invokeVendorCommandListenersOnReceived(mDeviceType, message.getSource(), + message.getDestination(), message.getParams(), false)) { // Vendor command listener may not have been registered yet. Respond with // <Feature Abort> [NOT_IN_CORRECT_MODE] so that the sender can try again later. mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE); @@ -530,8 +529,8 @@ abstract class HdmiCecLocalDevice { byte[] params = message.getParams(); int vendorId = HdmiUtils.threeBytesToInt(params); if (vendorId == mService.getVendorId()) { - if (!mService.invokeVendorCommandListeners(mDeviceType, message.getSource(), params, - true)) { + if (!mService.invokeVendorCommandListenersOnReceived(mDeviceType, message.getSource(), + message.getDestination(), params, true)) { mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE); } } else if (message.getDestination() != Constants.ADDR_BROADCAST && diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java index 780d54bb98b4..85a1a152b9ca 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java @@ -50,6 +50,8 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice { assertRunOnServiceThread(); mService.sendCecCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( mAddress, mService.getPhysicalAddress(), mDeviceType)); + mService.sendCecCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand( + mAddress, mService.getVendorId())); startQueuedActions(); } @@ -156,7 +158,7 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice { assertRunOnServiceThread(); int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams()); maySetActiveSource(physicalAddress); - maySendActiveSource(); + maySendActiveSource(message.getSource()); wakeUpIfActiveSource(); return true; // Broadcast message. } @@ -196,10 +198,13 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice { } } - private void maySendActiveSource() { + private void maySendActiveSource(int dest) { if (mIsActiveSource) { mService.sendCecCommand(HdmiCecMessageBuilder.buildActiveSource( mAddress, mService.getPhysicalAddress())); + // Always reports menu-status active to receive RCP. + mService.sendCecCommand(HdmiCecMessageBuilder.buildReportMenuStatus( + mAddress, dest, Constants.MENU_STATE_ACTIVATED)); } } @@ -207,7 +212,7 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice { @ServiceThreadOnly protected boolean handleRequestActiveSource(HdmiCecMessage message) { assertRunOnServiceThread(); - maySendActiveSource(); + maySendActiveSource(message.getSource()); return true; // Broadcast message. } @@ -230,4 +235,4 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice { super.dump(pw); pw.println("mIsActiveSource: " + mIsActiveSource); } -}
\ No newline at end of file +} diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index 0fb4b480a80f..6bae761c7478 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -110,6 +110,9 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { // If true, TV wakes itself up when receiving <Text/Image View On>. private boolean mAutoWakeup; + // List of the logical address of local CEC devices. Unmodifiable, thread-safe. + private List<Integer> mLocalDeviceAddresses; + private final HdmiCecStandbyModeHandler mStandbyHandler; // If true, do not do routing control/send active source for internal source. @@ -141,10 +144,22 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { mSkipRoutingControl = (reason == HdmiControlService.INITIATED_BY_WAKE_UP_MESSAGE); launchRoutingControl(reason != HdmiControlService.INITIATED_BY_ENABLE_CEC && reason != HdmiControlService.INITIATED_BY_BOOT_UP); + mLocalDeviceAddresses = initLocalDeviceAddresses(); launchDeviceDiscovery(); startQueuedActions(); } + + @ServiceThreadOnly + private List<Integer> initLocalDeviceAddresses() { + assertRunOnServiceThread(); + List<Integer> addresses = new ArrayList<>(); + for (HdmiCecLocalDevice device : mService.getAllLocalDevices()) { + addresses.add(device.getDeviceInfo().getLogicalAddress()); + } + return Collections.unmodifiableList(addresses); + } + @Override @ServiceThreadOnly protected int getPreferredAddress() { @@ -351,13 +366,26 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { if (!action.isEmpty()) { action.get(0).processKeyEvent(keyCode, isPressed); } else { - if (isPressed && getActiveSource().isValid()) { - int logicalAddress = getActiveSource().logicalAddress; - addAndStartAction(new SendKeyAction(this, logicalAddress, keyCode)); - } else { - Slog.w(TAG, "Discard key event: " + keyCode + " pressed:" + isPressed); + if (isPressed) { + int logicalAddress = findKeyReceiverAddress(); + if (logicalAddress != Constants.ADDR_INVALID) { + addAndStartAction(new SendKeyAction(this, logicalAddress, keyCode)); + return; + } } + Slog.w(TAG, "Discard key event: " + keyCode + " pressed:" + isPressed); + } + } + + private int findKeyReceiverAddress() { + if (getActiveSource().isValid()) { + return getActiveSource().logicalAddress; + } + HdmiDeviceInfo info = getDeviceInfoByPath(getActivePath()); + if (info != null) { + return info.getLogicalAddress(); } + return Constants.ADDR_INVALID; } private static void invokeCallback(IHdmiControlCallback callback, int result) { @@ -377,11 +405,12 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { assertRunOnServiceThread(); int logicalAddress = message.getSource(); int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams()); - if (getCecDeviceInfo(logicalAddress) == null) { + HdmiDeviceInfo info = getCecDeviceInfo(logicalAddress); + if (info == null) { handleNewDeviceAtTheTailOfActivePath(physicalAddress); } else { ActiveSource activeSource = ActiveSource.of(logicalAddress, physicalAddress); - ActiveSourceHandler.create(this, null).process(activeSource); + ActiveSourceHandler.create(this, null).process(activeSource, info.getDeviceType()); } return true; } @@ -471,7 +500,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { if (!isInDeviceList(address, path)) { handleNewDeviceAtTheTailOfActivePath(path); } - startNewDeviceAction(ActiveSource.of(address, path)); + startNewDeviceAction(ActiveSource.of(address, path), type); return true; } @@ -507,7 +536,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { return false; } - void startNewDeviceAction(ActiveSource activeSource) { + void startNewDeviceAction(ActiveSource activeSource, int deviceType) { for (NewDeviceAction action : getActions(NewDeviceAction.class)) { // If there is new device action which has the same logical address and path // ignore new request. @@ -523,7 +552,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { } addAndStartAction(new NewDeviceAction(this, activeSource.logicalAddress, - activeSource.physicalAddress)); + activeSource.physicalAddress, deviceType)); } private void handleNewDeviceAtTheTailOfActivePath(int path) { @@ -1182,15 +1211,8 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { } } - @ServiceThreadOnly private boolean isLocalDeviceAddress(int address) { - assertRunOnServiceThread(); - for (HdmiCecLocalDevice device : mService.getAllLocalDevices()) { - if (device.isAddressOf(address)) { - return true; - } - } - return false; + return mLocalDeviceAddresses.contains(address); } @ServiceThreadOnly @@ -1240,6 +1262,17 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { } } + List<HdmiDeviceInfo> getSafeCecDevicesLocked() { + ArrayList<HdmiDeviceInfo> infoList = new ArrayList<>(); + for (HdmiDeviceInfo info : mSafeAllDeviceInfos) { + if (isLocalDeviceAddress(info.getLogicalAddress())) { + continue; + } + infoList.add(info); + } + return infoList; + } + /** * Called when a device is newly added or a new device is detected or * existing device is updated. diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 60d152005e5c..aeb21dbfa136 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -90,6 +90,8 @@ import java.util.Locale; */ public final class HdmiControlService extends SystemService { private static final String TAG = "HdmiControlService"; + private final Locale HONG_KONG = new Locale("zh", "HK"); + private final Locale MACAU = new Locale("zh", "MO"); static final String PERMISSION = "android.permission.HDMI_CEC"; @@ -146,13 +148,25 @@ public final class HdmiControlService extends SystemService { } break; case Intent.ACTION_CONFIGURATION_CHANGED: - String language = Locale.getDefault().getISO3Language(); + String language = getMenuLanguage(); if (!mLanguage.equals(language)) { onLanguageChanged(language); } break; } } + + private String getMenuLanguage() { + Locale locale = Locale.getDefault(); + if (locale.equals(Locale.TAIWAN) || locale.equals(HONG_KONG) || locale.equals(MACAU)) { + // Android always returns "zho" for all Chinese variants. + // Use "bibliographic" code defined in CEC639-2 for traditional + // Chinese used in Taiwan/Hong Kong/Macau. + return "chi"; + } else { + return locale.getISO3Language(); + } + } } // A thread to handle synchronous IO of CEC and MHL control service. @@ -303,6 +317,7 @@ public final class HdmiControlService extends SystemService { } } else { Slog.i(TAG, "Device does not support HDMI-CEC."); + return; } mMhlController = HdmiMhlControllerStub.create(this); @@ -315,20 +330,23 @@ public final class HdmiControlService extends SystemService { mMessageValidator = new HdmiCecMessageValidator(this); publishBinderService(Context.HDMI_CONTROL_SERVICE, new BinderService()); - // Register broadcast receiver for power state change. if (mCecController != null) { + // Register broadcast receiver for power state change. IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); getContext().registerReceiver(mHdmiControlBroadcastReceiver, filter); + + // Register ContentObserver to monitor the settings change. + registerContentObserver(); } } /** * Called when the initialization of local devices is complete. */ - private void onInitializeCecComplete() { + private void onInitializeCecComplete(int initiatedBy) { if (mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON) { mPowerStatus = HdmiControlManager.POWER_STATUS_ON; } @@ -336,7 +354,22 @@ public final class HdmiControlService extends SystemService { if (isTvDevice()) { mCecController.setOption(OPTION_CEC_AUTO_WAKEUP, toInt(tv().getAutoWakeup())); - registerContentObserver(); + } + int reason = -1; + switch (initiatedBy) { + case INITIATED_BY_BOOT_UP: + reason = HdmiControlManager.CONTROL_STATE_CHANGED_REASON_START; + break; + case INITIATED_BY_ENABLE_CEC: + reason = HdmiControlManager.CONTROL_STATE_CHANGED_REASON_SETTING; + break; + case INITIATED_BY_SCREEN_ON: + case INITIATED_BY_WAKE_UP_MESSAGE: + reason = HdmiControlManager.CONTROL_STATE_CHANGED_REASON_WAKEUP; + break; + } + if (reason != -1) { + invokeVendorCommandListenersOnControlStateChanged(true, reason); } } @@ -401,10 +434,6 @@ public final class HdmiControlService extends SystemService { Global.putInt(cr, key, toInt(value)); } - private void unregisterSettingsObserver() { - getContext().getContentResolver().unregisterContentObserver(mSettingsObserver); - } - private void initializeCec(int initiatedBy) { mCecController.setOption(OPTION_CEC_SERVICE_CONTROL, ENABLED); initializeLocalDevices(initiatedBy); @@ -459,7 +488,7 @@ public final class HdmiControlService extends SystemService { if (initiatedBy != INITIATED_BY_HOTPLUG) { // In case of the hotplug we don't call onInitializeCecComplete() // since we reallocate the logical address only. - onInitializeCecComplete(); + onInitializeCecComplete(initiatedBy); } notifyAddressAllocated(allocatedDevices, initiatedBy); } @@ -729,20 +758,18 @@ public final class HdmiControlService extends SystemService { void onHotplug(int portId, boolean connected) { assertRunOnServiceThread(); - ArrayList<HdmiCecLocalDevice> localDevices = new ArrayList<>(); - for (int type : mLocalDevices) { - if (type == HdmiDeviceInfo.DEVICE_TV) { - // Skip the reallocation of the logical address on TV. - continue; - } - HdmiCecLocalDevice localDevice = mCecController.getLocalDevice(type); - if (localDevice == null) { - localDevice = HdmiCecLocalDevice.create(this, type); - localDevice.init(); + if (connected && !isTvDevice()) { + ArrayList<HdmiCecLocalDevice> localDevices = new ArrayList<>(); + for (int type : mLocalDevices) { + HdmiCecLocalDevice localDevice = mCecController.getLocalDevice(type); + if (localDevice == null) { + localDevice = HdmiCecLocalDevice.create(this, type); + localDevice.init(); + } + localDevices.add(localDevice); } - localDevices.add(localDevice); + allocateLogicalAddress(localDevices, INITIATED_BY_HOTPLUG); } - allocateLogicalAddress(localDevices, INITIATED_BY_HOTPLUG); for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) { device.onHotplug(portId, connected); @@ -827,6 +854,7 @@ public final class HdmiControlService extends SystemService { @ServiceThreadOnly void handleMhlHotplugEvent(int portId, boolean connected) { assertRunOnServiceThread(); + // Hotplug event is used to add/remove MHL devices as TV input. if (connected) { HdmiMhlLocalDeviceStub newDevice = new HdmiMhlLocalDeviceStub(this, portId); HdmiMhlLocalDeviceStub oldDevice = mMhlController.addLocalDevice(newDevice); @@ -834,17 +862,14 @@ public final class HdmiControlService extends SystemService { oldDevice.onDeviceRemoved(); Slog.i(TAG, "Old device of port " + portId + " is removed"); } + invokeDeviceEventListeners(newDevice.getInfo(), DEVICE_EVENT_ADD_DEVICE); + updateSafeMhlInput(); } else { HdmiMhlLocalDeviceStub device = mMhlController.removeLocalDevice(portId); if (device != null) { device.onDeviceRemoved(); - // There is no explicit event for device removal. - // Hence we remove the device on hotplug event. - HdmiDeviceInfo deviceInfo = device.getInfo(); - if (deviceInfo != null) { - invokeDeviceEventListeners(deviceInfo, DEVICE_EVENT_REMOVE_DEVICE); - updateSafeMhlInput(); - } + invokeDeviceEventListeners(device.getInfo(), DEVICE_EVENT_REMOVE_DEVICE); + updateSafeMhlInput(); } else { Slog.w(TAG, "No device to remove:[portId=" + portId); } @@ -880,11 +905,8 @@ public final class HdmiControlService extends SystemService { assertRunOnServiceThread(); HdmiMhlLocalDeviceStub device = mMhlController.getLocalDevice(portId); - // Hotplug event should already have been called before device status change event. if (device != null) { device.setDeviceStatusChange(adopterId, deviceId); - invokeDeviceEventListeners(device.getInfo(), DEVICE_EVENT_ADD_DEVICE); - updateSafeMhlInput(); } else { Slog.w(TAG, "No mhl device exists for device status event[portId:" + portId + ", adopterId:" + adopterId + ", deviceId:" + deviceId + "]"); @@ -1025,6 +1047,7 @@ public final class HdmiControlService extends SystemService { @Override public HdmiDeviceInfo getActiveSource() { + enforceAccessPermission(); HdmiCecLocalDeviceTv tv = tv(); if (tv == null) { Slog.w(TAG, "Local tv device not available"); @@ -1238,6 +1261,19 @@ public final class HdmiControlService extends SystemService { } } + // Returns all the CEC devices on the bus including system audio, switch, + // even those of reserved type. + @Override + public List<HdmiDeviceInfo> getDeviceList() { + enforceAccessPermission(); + HdmiCecLocalDeviceTv tv = tv(); + synchronized (mLock) { + return (tv == null) + ? Collections.<HdmiDeviceInfo>emptyList() + : tv.getSafeCecDevicesLocked(); + } + } + @Override public void setSystemAudioVolume(final int oldIndex, final int newIndex, final int maxIndex) { @@ -1344,11 +1380,13 @@ public final class HdmiControlService extends SystemService { @Override public void setHdmiRecordListener(IHdmiRecordListener listener) { + enforceAccessPermission(); HdmiControlService.this.setHdmiRecordListener(listener); } @Override public void startOneTouchRecord(final int recorderAddress, final byte[] recordSource) { + enforceAccessPermission(); runOnServiceThread(new Runnable() { @Override public void run() { @@ -1363,6 +1401,7 @@ public final class HdmiControlService extends SystemService { @Override public void stopOneTouchRecord(final int recorderAddress) { + enforceAccessPermission(); runOnServiceThread(new Runnable() { @Override public void run() { @@ -1378,6 +1417,7 @@ public final class HdmiControlService extends SystemService { @Override public void startTimerRecording(final int recorderAddress, final int sourceType, final byte[] recordSource) { + enforceAccessPermission(); runOnServiceThread(new Runnable() { @Override public void run() { @@ -1393,6 +1433,7 @@ public final class HdmiControlService extends SystemService { @Override public void clearTimerRecording(final int recorderAddress, final int sourceType, final byte[] recordSource) { + enforceAccessPermission(); runOnServiceThread(new Runnable() { @Override public void run() { @@ -1696,7 +1737,7 @@ public final class HdmiControlService extends SystemService { } boolean isTvDevice() { - return tv() != null; + return mLocalDevices.contains(HdmiDeviceInfo.DEVICE_TV); } private HdmiCecLocalDevicePlayback playback() { @@ -1782,6 +1823,8 @@ public final class HdmiControlService extends SystemService { private void onStandby() { assertRunOnServiceThread(); mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY; + invokeVendorCommandListenersOnControlStateChanged(false, + HdmiControlManager.CONTROL_STATE_CHANGED_REASON_STANDBY); final List<HdmiCecLocalDevice> devices = getAllLocalDevices(); disableDevices(new PendingActionClearedCallback() { @@ -1820,9 +1863,6 @@ public final class HdmiControlService extends SystemService { for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) { device.disableDevice(mStandbyMessageReceived, callback); } - if (isTvDevice()) { - unregisterSettingsObserver(); - } } mMhlController.clearAllLocalDevices(); @@ -1867,8 +1907,8 @@ public final class HdmiControlService extends SystemService { } } - boolean invokeVendorCommandListeners(int deviceType, int srcAddress, byte[] params, - boolean hasVendorId) { + boolean invokeVendorCommandListenersOnReceived(int deviceType, int srcAddress, int destAddress, + byte[] params, boolean hasVendorId) { synchronized (mLock) { if (mVendorCommandListenerRecords.isEmpty()) { return false; @@ -1878,7 +1918,7 @@ public final class HdmiControlService extends SystemService { continue; } try { - record.mListener.onReceived(srcAddress, params, hasVendorId); + record.mListener.onReceived(srcAddress, destAddress, params, hasVendorId); } catch (RemoteException e) { Slog.e(TAG, "Failed to notify vendor command reception", e); } @@ -1887,6 +1927,22 @@ public final class HdmiControlService extends SystemService { } } + boolean invokeVendorCommandListenersOnControlStateChanged(boolean enabled, int reason) { + synchronized (mLock) { + if (mVendorCommandListenerRecords.isEmpty()) { + return false; + } + for (VendorCommandListenerRecord record : mVendorCommandListenerRecords) { + try { + record.mListener.onControlStateChanged(enabled, reason); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to notify control-state-changed to vendor handler", e); + } + } + return true; + } + } + private void addHdmiMhlVendorCommandListener(IHdmiMhlVendorCommandListener listener) { HdmiMhlVendorCommandListenerRecord record = new HdmiMhlVendorCommandListenerRecord(listener); @@ -1936,6 +1992,11 @@ public final class HdmiControlService extends SystemService { void setControlEnabled(boolean enabled) { assertRunOnServiceThread(); + if (!enabled) { + // Call the vendor handler before the service is disabled. + invokeVendorCommandListenersOnControlStateChanged(false, + HdmiControlManager.CONTROL_STATE_CHANGED_REASON_SETTING); + } int value = toInt(enabled); mCecController.setOption(OPTION_CEC_ENABLE, value); mMhlController.setOption(OPTION_MHL_ENABLE, value); @@ -2008,9 +2069,7 @@ public final class HdmiControlService extends SystemService { // may not be the MHL-enabled one. In this case the device info to be passed to // input change listener should be the one describing the corresponding HDMI port. HdmiMhlLocalDeviceStub device = mMhlController.getLocalDevice(portId); - HdmiDeviceInfo info = (device != null && device.getInfo() != null) - ? device.getInfo() - : mPortDeviceMap.get(portId); + HdmiDeviceInfo info = (device != null) ? device.getInfo() : mPortDeviceMap.get(portId); invokeInputChangeListener(info); } @@ -2042,7 +2101,7 @@ public final class HdmiControlService extends SystemService { assertRunOnServiceThread(); Intent intent = new Intent(HdmiControlManager.ACTION_OSD_MESSAGE); intent.putExtra(HdmiControlManager.EXTRA_MESSAGE_ID, messageId); - intent.putExtra(HdmiControlManager.EXTRA_MESSAGE_EXTRAM_PARAM1, extra); + intent.putExtra(HdmiControlManager.EXTRA_MESSAGE_EXTRA_PARAM1, extra); getContext().sendBroadcastAsUser(intent, UserHandle.ALL, HdmiControlService.PERMISSION); } diff --git a/services/core/java/com/android/server/hdmi/NewDeviceAction.java b/services/core/java/com/android/server/hdmi/NewDeviceAction.java index 207408515c91..998889bc270d 100644 --- a/services/core/java/com/android/server/hdmi/NewDeviceAction.java +++ b/services/core/java/com/android/server/hdmi/NewDeviceAction.java @@ -47,6 +47,7 @@ final class NewDeviceAction extends HdmiCecFeatureAction { private final int mDeviceLogicalAddress; private final int mDevicePhysicalAddress; + private final int mDeviceType; private int mVendorId; private String mDisplayName; @@ -57,12 +58,14 @@ final class NewDeviceAction extends HdmiCecFeatureAction { * @param source {@link HdmiCecLocalDevice} instance * @param deviceLogicalAddress logical address of the device in interest * @param devicePhysicalAddress physical address of the device in interest + * @param deviceType type of the device */ NewDeviceAction(HdmiCecLocalDevice source, int deviceLogicalAddress, - int devicePhysicalAddress) { + int devicePhysicalAddress, int deviceType) { super(source); mDeviceLogicalAddress = deviceLogicalAddress; mDevicePhysicalAddress = devicePhysicalAddress; + mDeviceType = deviceType; mVendorId = Constants.UNKNOWN_VENDOR_ID; } @@ -155,8 +158,7 @@ final class NewDeviceAction extends HdmiCecFeatureAction { HdmiDeviceInfo deviceInfo = new HdmiDeviceInfo( mDeviceLogicalAddress, mDevicePhysicalAddress, tv().getPortId(mDevicePhysicalAddress), - HdmiUtils.getTypeFromAddress(mDeviceLogicalAddress), - mVendorId, mDisplayName); + mDeviceType, mVendorId, mDisplayName); tv().addCecDevice(deviceInfo); if (HdmiUtils.getTypeFromAddress(mDeviceLogicalAddress) diff --git a/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java b/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java index 7db991a65f84..e764a1c85c79 100644 --- a/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java +++ b/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java @@ -92,7 +92,8 @@ final class OneTouchPlayAction extends HdmiCecFeatureAction { @Override boolean processCommand(HdmiCecMessage cmd) { - if (mState != STATE_WAITING_FOR_REPORT_POWER_STATUS) { + if (mState != STATE_WAITING_FOR_REPORT_POWER_STATUS + || mTargetAddress != cmd.getSource()) { return false; } if (cmd.getOpcode() == Constants.MESSAGE_REPORT_POWER_STATUS) { diff --git a/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java b/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java index 39c0d7fbc671..906944bf1921 100644 --- a/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java +++ b/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java @@ -68,23 +68,21 @@ public class OneTouchRecordAction extends HdmiCecFeatureAction { finish(); return; } - - mState = STATE_WAITING_FOR_RECORD_STATUS; - addTimer(mState, RECORD_STATUS_TIMEOUT_MS); } }); + mState = STATE_WAITING_FOR_RECORD_STATUS; + addTimer(mState, RECORD_STATUS_TIMEOUT_MS); } @Override boolean processCommand(HdmiCecMessage cmd) { - if (mState != STATE_WAITING_FOR_RECORD_STATUS) { + if (mState != STATE_WAITING_FOR_RECORD_STATUS || mRecorderAddress != cmd.getSource()) { return false; } switch (cmd.getOpcode()) { case Constants.MESSAGE_RECORD_STATUS: return handleRecordStatus(cmd); - } return false; } diff --git a/services/core/java/com/android/server/hdmi/SendKeyAction.java b/services/core/java/com/android/server/hdmi/SendKeyAction.java index ed978e011dd1..eef5010f00d2 100644 --- a/services/core/java/com/android/server/hdmi/SendKeyAction.java +++ b/services/core/java/com/android/server/hdmi/SendKeyAction.java @@ -15,7 +15,7 @@ */ package com.android.server.hdmi; -import static com.android.server.hdmi.Constants.IRT_MS; +import static com.android.server.hdmi.HdmiConfig.IRT_MS; import android.util.Slog; import android.view.KeyEvent; @@ -35,6 +35,11 @@ import android.view.KeyEvent; final class SendKeyAction extends HdmiCecFeatureAction { private static final String TAG = "SendKeyAction"; + // Amount of time this action waits for a new release key input event. When timed out, + // the action sends out UCR and finishes its lifecycle. Used to deal with missing key release + // event, which can lead the device on the receiving end to generating unintended key repeats. + private static final int AWAIT_RELEASE_KEY_MS = 1000; + // State in which the action is at work. The state is set in {@link #start()} and // persists throughout the process till it is set back to {@code STATE_NONE} at the end. private static final int STATE_PROCESSING_KEYCODE = 1; @@ -45,6 +50,10 @@ final class SendKeyAction extends HdmiCecFeatureAction { // The key code of the last key press event the action is passed via processKeyEvent. private int mLastKeycode; + // The time stamp when the last CEC key command was sent. Used to determine the press-and-hold + // operation. + private long mLastSendKeyTime; + /** * Constructor. * @@ -61,6 +70,7 @@ final class SendKeyAction extends HdmiCecFeatureAction { @Override public boolean start() { sendKeyDown(mLastKeycode); + mLastSendKeyTime = getCurrentTime(); // finish action for non-repeatable key. if (!HdmiCecKeycode.isRepeatableKey(mLastKeycode)) { sendKeyUp(); @@ -68,10 +78,14 @@ final class SendKeyAction extends HdmiCecFeatureAction { return true; } mState = STATE_PROCESSING_KEYCODE; - addTimer(mState, IRT_MS); + addTimer(mState, AWAIT_RELEASE_KEY_MS); return true; } + private long getCurrentTime() { + return System.currentTimeMillis(); + } + /** * Called when a key event should be handled for the action. * @@ -83,24 +97,32 @@ final class SendKeyAction extends HdmiCecFeatureAction { Slog.w(TAG, "Not in a valid state"); return; } - // A new key press event that comes in with a key code different from the last - // one sets becomes a new key code to be used for press-and-hold operation. - // Removes any pending timer and starts a new timer for itself. - // Key release event indicates that the action shall be finished. Send UCR - // command and terminate the action. Other release events are ignored. if (isPressed) { + // A new key press event that comes in with a key code different from the last + // one becomes a new key code to be used for press-and-hold operation. if (keycode != mLastKeycode) { sendKeyDown(keycode); + mLastSendKeyTime = getCurrentTime(); if (!HdmiCecKeycode.isRepeatableKey(keycode)) { sendKeyUp(); finish(); return; } - mActionTimer.clearTimerMessage(); - addTimer(mState, IRT_MS); - mLastKeycode = keycode; + } else { + // Press-and-hold key transmission takes place if Android key inputs are + // repeatedly coming in and more than IRT_MS has passed since the last + // press-and-hold key transmission. + if (getCurrentTime() - mLastSendKeyTime >= IRT_MS) { + sendKeyDown(keycode); + mLastSendKeyTime = getCurrentTime(); + } } + mActionTimer.clearTimerMessage(); + addTimer(mState, AWAIT_RELEASE_KEY_MS); + mLastKeycode = keycode; } else { + // Key release event indicates that the action shall be finished. Send UCR + // command and terminate the action. Other release events are ignored. if (keycode == mLastKeycode) { sendKeyUp(); finish(); @@ -109,12 +131,12 @@ final class SendKeyAction extends HdmiCecFeatureAction { } private void sendKeyDown(int keycode) { - int cecKeycode = HdmiCecKeycode.androidKeyToCecKey(keycode); - if (cecKeycode == HdmiCecKeycode.UNSUPPORTED_KEYCODE) { + byte[] cecKeycodeAndParams = HdmiCecKeycode.androidKeyToCecKey(keycode); + if (cecKeycodeAndParams == null) { return; } sendCommand(HdmiCecMessageBuilder.buildUserControlPressed(getSourceAddress(), - mTargetAddress, new byte[] { (byte) (cecKeycode & 0xFF) })); + mTargetAddress, cecKeycodeAndParams)); } private void sendKeyUp() { @@ -130,15 +152,12 @@ final class SendKeyAction extends HdmiCecFeatureAction { @Override public void handleTimerEvent(int state) { - // Timer event occurs every IRT_MS milliseconds to perform key-repeat (or press-and-hold) - // operation. If the last received key code is as same as the one with which the action - // is started, plus there was no key release event in last IRT_MS timeframe, send a UCP - // command and start another timer to schedule the next press-and-hold command. + // Timeout on waiting for the release key event. Send UCR and quit the action. if (mState != STATE_PROCESSING_KEYCODE) { Slog.w(TAG, "Not in a valid state"); return; } - sendKeyDown(mLastKeycode); - addTimer(mState, IRT_MS); + sendKeyUp(); + finish(); } } diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAction.java index 0871194b268f..6023354bd6c7 100644 --- a/services/core/java/com/android/server/hdmi/SystemAudioAction.java +++ b/services/core/java/com/android/server/hdmi/SystemAudioAction.java @@ -125,6 +125,9 @@ abstract class SystemAudioAction extends HdmiCecFeatureAction { @Override final boolean processCommand(HdmiCecMessage cmd) { + if (cmd.getSource() != mAvrLogicalAddress) { + return false; + } switch (mState) { case STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE: if (cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java index 3653aacdd094..50f8475cfa32 100644 --- a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java +++ b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java @@ -58,17 +58,16 @@ final class SystemAudioAutoInitiationAction extends HdmiCecFeatureAction { @Override boolean processCommand(HdmiCecMessage cmd) { - if (mState != STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS) { + if (mState != STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS + || mAvrAddress != cmd.getSource()) { return false; } - switch (cmd.getOpcode()) { - case Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS: - handleSystemAudioModeStatusMessage(); - return true; - default: - return false; + if (cmd.getOpcode() == Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS) { + handleSystemAudioModeStatusMessage(); + return true; } + return false; } private void handleSystemAudioModeStatusMessage() { diff --git a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java index bfcda5032258..dba3591cbdb4 100644 --- a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java +++ b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java @@ -79,7 +79,7 @@ final class SystemAudioStatusAction extends HdmiCecFeatureAction { @Override boolean processCommand(HdmiCecMessage cmd) { - if (mState != STATE_WAIT_FOR_REPORT_AUDIO_STATUS) { + if (mState != STATE_WAIT_FOR_REPORT_AUDIO_STATUS || mAvrAddress != cmd.getSource()) { return false; } diff --git a/services/core/java/com/android/server/hdmi/TimerRecordingAction.java b/services/core/java/com/android/server/hdmi/TimerRecordingAction.java index 8fc0182fc60c..5fcbc91d0e60 100644 --- a/services/core/java/com/android/server/hdmi/TimerRecordingAction.java +++ b/services/core/java/com/android/server/hdmi/TimerRecordingAction.java @@ -96,11 +96,8 @@ public class TimerRecordingAction extends HdmiCecFeatureAction { @Override boolean processCommand(HdmiCecMessage cmd) { - if (mState != STATE_WAITING_FOR_TIMER_STATUS) { - return false; - } - - if (cmd.getSource() != mRecorderAddress) { + if (mState != STATE_WAITING_FOR_TIMER_STATUS + || cmd.getSource() != mRecorderAddress) { return false; } diff --git a/services/core/java/com/android/server/hdmi/VolumeControlAction.java b/services/core/java/com/android/server/hdmi/VolumeControlAction.java index 4338fc7dd673..cd38b1fb2ac6 100644 --- a/services/core/java/com/android/server/hdmi/VolumeControlAction.java +++ b/services/core/java/com/android/server/hdmi/VolumeControlAction.java @@ -16,10 +16,10 @@ package com.android.server.hdmi; -import static com.android.server.hdmi.Constants.IRT_MS; import static com.android.server.hdmi.Constants.MESSAGE_FEATURE_ABORT; import static com.android.server.hdmi.Constants.MESSAGE_REPORT_AUDIO_STATUS; import static com.android.server.hdmi.Constants.MESSAGE_USER_CONTROL_PRESSED; +import static com.android.server.hdmi.HdmiConfig.IRT_MS; import android.media.AudioManager; @@ -45,6 +45,7 @@ final class VolumeControlAction extends HdmiCecFeatureAction { private boolean mIsVolumeUp; private long mLastKeyUpdateTime; private int mLastAvrVolume; + private boolean mLastAvrMute; private boolean mSentKeyPressed; /** @@ -74,6 +75,7 @@ final class VolumeControlAction extends HdmiCecFeatureAction { mAvrAddress = avrAddress; mIsVolumeUp = isVolumeUp; mLastAvrVolume = UNKNOWN_AVR_VOLUME; + mLastAvrMute = false; mSentKeyPressed = false; updateLastKeyUpdateTime(); @@ -108,6 +110,8 @@ final class VolumeControlAction extends HdmiCecFeatureAction { HdmiLogger.debug("Volume Key Status Changed[old:%b new:%b]", mIsVolumeUp, isVolumeUp); sendVolumeKeyReleased(); mIsVolumeUp = isVolumeUp; + sendVolumeKeyPressed(); + resetTimer(); } updateLastKeyUpdateTime(); } @@ -129,9 +133,8 @@ final class VolumeControlAction extends HdmiCecFeatureAction { return handleReportAudioStatus(cmd); case MESSAGE_FEATURE_ABORT: return handleFeatureAbort(cmd); - default: - return false; } + return false; } private boolean handleReportAudioStatus(HdmiCecMessage cmd) { @@ -139,9 +142,12 @@ final class VolumeControlAction extends HdmiCecFeatureAction { boolean mute = (params[0] & 0x80) == 0x80; int volume = params[0] & 0x7F; mLastAvrVolume = volume; + mLastAvrMute = mute; if (shouldUpdateAudioVolume(mute)) { HdmiLogger.debug("Force volume change[mute:%b, volume=%d]", mute, volume); tv().setAudioStatus(mute, volume); + mLastAvrVolume = UNKNOWN_AVR_VOLUME; + mLastAvrMute = false; } return true; } @@ -182,8 +188,9 @@ final class VolumeControlAction extends HdmiCecFeatureAction { sendVolumeKeyReleased(); } if (mLastAvrVolume != UNKNOWN_AVR_VOLUME) { - tv().setAudioStatus(false, mLastAvrVolume); + tv().setAudioStatus(mLastAvrMute, mLastAvrVolume); mLastAvrVolume = UNKNOWN_AVR_VOLUME; + mLastAvrMute = false; } } diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index c6d2db2ccf6e..83d6986a410f 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -137,11 +137,15 @@ public class JobSchedulerService extends com.android.server.SystemService public void onReceive(Context context, Intent intent) { Slog.d(TAG, "Receieved: " + intent.getAction()); if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) { - int uidRemoved = intent.getIntExtra(Intent.EXTRA_UID, -1); - if (DEBUG) { - Slog.d(TAG, "Removing jobs for uid: " + uidRemoved); + // If this is an outright uninstall rather than the first half of an + // app update sequence, cancel the jobs associated with the app. + if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { + int uidRemoved = intent.getIntExtra(Intent.EXTRA_UID, -1); + if (DEBUG) { + Slog.d(TAG, "Removing jobs for uid: " + uidRemoved); + } + cancelJobsForUid(uidRemoved); } - cancelJobsForUid(uidRemoved); } else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) { final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); if (DEBUG) { diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java index 0198e46b786e..c2cb4b1da1f0 100644 --- a/services/core/java/com/android/server/location/GpsLocationProvider.java +++ b/services/core/java/com/android/server/location/GpsLocationProvider.java @@ -473,14 +473,7 @@ public class GpsLocationProvider implements LocationProviderInterface { checkSmsSuplInit(intent); } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) { checkWapSuplInit(intent); - } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { - int networkState; - if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false)) { - networkState = LocationProvider.TEMPORARILY_UNAVAILABLE; - } else { - networkState = LocationProvider.AVAILABLE; - } - + } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE)) { // retrieve NetworkInfo result for this UID NetworkInfo info = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO); @@ -488,6 +481,15 @@ public class GpsLocationProvider implements LocationProviderInterface { mContext.getSystemService(Context.CONNECTIVITY_SERVICE); info = connManager.getNetworkInfo(info.getType()); + int networkState; + if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false) || + !info.isConnected()) { + networkState = LocationProvider.TEMPORARILY_UNAVAILABLE; + } else { + networkState = LocationProvider.AVAILABLE; + } + + updateNetworkState(networkState, info); } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action) || Intent.ACTION_SCREEN_OFF.equals(action) @@ -715,7 +717,7 @@ public class GpsLocationProvider implements LocationProviderInterface { intentFilter = new IntentFilter(); intentFilter.addAction(ALARM_WAKEUP); intentFilter.addAction(ALARM_TIMEOUT); - intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE); intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED); intentFilter.addAction(Intent.ACTION_SCREEN_OFF); intentFilter.addAction(Intent.ACTION_SCREEN_ON); diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java index 531d20a12f9e..e9b3f8b6ff1b 100644 --- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java +++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java @@ -326,7 +326,7 @@ public final class MediaProjectionManagerService extends SystemService final long token = Binder.clearCallingIdentity(); try { - dump(pw); + MediaProjectionManagerService.this.dump(pw); } finally { Binder.restoreCallingIdentity(token); } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index b5aa4d83fd0e..150ad34669da 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -45,7 +45,6 @@ import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES; import static android.provider.Settings.Global.NETSTATS_DEV_ROTATE_AGE; import static android.provider.Settings.Global.NETSTATS_GLOBAL_ALERT_BYTES; import static android.provider.Settings.Global.NETSTATS_POLL_INTERVAL; -import static android.provider.Settings.Global.NETSTATS_REPORT_XT_OVER_DEV; import static android.provider.Settings.Global.NETSTATS_SAMPLE_ENABLED; import static android.provider.Settings.Global.NETSTATS_TIME_CACHE_MAX_AGE; import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION; @@ -184,7 +183,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public long getPollInterval(); public long getTimeCacheMaxAge(); public boolean getSampleEnabled(); - public boolean getReportXtOverDev(); public static class Config { public final long bucketDuration; @@ -229,8 +227,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private NetworkStatsRecorder mUidRecorder; private NetworkStatsRecorder mUidTagRecorder; - /** Cached {@link #mDevRecorder} stats. */ - private NetworkStatsCollection mDevStatsCached; /** Cached {@link #mXtRecorder} stats. */ private NetworkStatsCollection mXtStatsCached; @@ -305,7 +301,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // read historical network stats from disk, since policy service // might need them right away. - mDevStatsCached = mDevRecorder.getOrLoadCompleteLocked(); mXtStatsCached = mXtRecorder.getOrLoadCompleteLocked(); // bootstrap initial stats to prevent double-counting later @@ -386,7 +381,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mUidRecorder = null; mUidTagRecorder = null; - mDevStatsCached = null; mXtStatsCached = null; mSystemReady = false; @@ -523,48 +517,24 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } /** - * Return network summary, splicing between {@link #mDevStatsCached} - * and {@link #mXtStatsCached} when appropriate. + * Return network summary, splicing between DEV and XT stats when + * appropriate. */ private NetworkStats internalGetSummaryForNetwork( NetworkTemplate template, long start, long end) { - if (!mSettings.getReportXtOverDev()) { - // shortcut when XT reporting disabled - return mDevStatsCached.getSummary(template, start, end); - } - - // splice stats between DEV and XT, switching over from DEV to XT at - // first atomic bucket. - final long firstAtomicBucket = mXtStatsCached.getFirstAtomicBucketMillis(); - final NetworkStats dev = mDevStatsCached.getSummary( - template, Math.min(start, firstAtomicBucket), Math.min(end, firstAtomicBucket)); - final NetworkStats xt = mXtStatsCached.getSummary( - template, Math.max(start, firstAtomicBucket), Math.max(end, firstAtomicBucket)); - - xt.combineAllValues(dev); - return xt; + // We've been using pure XT stats long enough that we no longer need to + // splice DEV and XT together. + return mXtStatsCached.getSummary(template, start, end); } /** - * Return network history, splicing between {@link #mDevStatsCached} - * and {@link #mXtStatsCached} when appropriate. + * Return network history, splicing between DEV and XT stats when + * appropriate. */ private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template, int fields) { - if (!mSettings.getReportXtOverDev()) { - // shortcut when XT reporting disabled - return mDevStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields); - } - - // splice stats between DEV and XT, switching over from DEV to XT at - // first atomic bucket. - final long firstAtomicBucket = mXtStatsCached.getFirstAtomicBucketMillis(); - final NetworkStatsHistory dev = mDevStatsCached.getHistory( - template, UID_ALL, SET_ALL, TAG_NONE, fields, Long.MIN_VALUE, firstAtomicBucket); - final NetworkStatsHistory xt = mXtStatsCached.getHistory( - template, UID_ALL, SET_ALL, TAG_NONE, fields, firstAtomicBucket, Long.MAX_VALUE); - - xt.recordEntireHistory(dev); - return xt; + // We've been using pure XT stats long enough that we no longer need to + // splice DEV and XT together. + return mXtStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields); } @Override @@ -1329,10 +1299,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return getGlobalBoolean(NETSTATS_SAMPLE_ENABLED, true); } @Override - public boolean getReportXtOverDev() { - return getGlobalBoolean(NETSTATS_REPORT_XT_OVER_DEV, true); - } - @Override public Config getDevConfig() { return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS), getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS), diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java index 97f0a1ec263d..24fc45508bc1 100644 --- a/services/core/java/com/android/server/notification/NotificationDelegate.java +++ b/services/core/java/com/android/server/notification/NotificationDelegate.java @@ -20,6 +20,7 @@ public interface NotificationDelegate { void onSetDisabled(int status); void onClearAll(int callingUid, int callingPid, int userId); void onNotificationClick(int callingUid, int callingPid, String key); + void onNotificationActionClick(int callingUid, int callingPid, String key, int actionIndex); void onNotificationClear(int callingUid, int callingPid, String pkg, String tag, int id, int userId); void onNotificationError(int callingUid, int callingPid, diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 22f060f9c8e2..42a855165c20 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -41,6 +41,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; +import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; @@ -541,6 +542,20 @@ public class NotificationManagerService extends SystemService { } @Override + public void onNotificationActionClick(int callingUid, int callingPid, String key, + int actionIndex) { + synchronized (mNotificationList) { + EventLogTags.writeNotificationActionClicked(key, actionIndex); + NotificationRecord r = mNotificationsByKey.get(key); + if (r == null) { + Log.w(TAG, "No notification with key: " + key); + return; + } + // TODO: Log action click via UsageStats. + } + } + + @Override public void onNotificationClear(int callingUid, int callingPid, String pkg, String tag, int id, int userId) { cancelNotification(callingUid, callingPid, pkg, tag, id, 0, @@ -643,7 +658,7 @@ public class NotificationManagerService extends SystemService { } }; - private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { + private final BroadcastReceiver mPackageIntentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); @@ -659,6 +674,8 @@ public class NotificationManagerService extends SystemService { || (packageChanged=action.equals(Intent.ACTION_PACKAGE_CHANGED)) || (queryRestart=action.equals(Intent.ACTION_QUERY_PACKAGE_RESTART)) || action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) { + int changeUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, + UserHandle.USER_ALL); String pkgList[] = null; boolean queryReplace = queryRemove && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); @@ -679,8 +696,10 @@ public class NotificationManagerService extends SystemService { if (packageChanged) { // We cancel notifications for packages which have just been disabled try { - final int enabled = getContext().getPackageManager() - .getApplicationEnabledSetting(pkgName); + final IPackageManager pm = AppGlobals.getPackageManager(); + final int enabled = pm.getApplicationEnabledSetting(pkgName, + changeUserId != UserHandle.USER_ALL ? changeUserId : + UserHandle.USER_OWNER); if (enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED || enabled == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) { cancelNotifications = false; @@ -691,6 +710,8 @@ public class NotificationManagerService extends SystemService { if (DBG) { Slog.i(TAG, "Exception trying to look up app enabled setting", e); } + } catch (RemoteException e) { + // Failed to talk to PackageManagerService Should never happen! } } pkgList = new String[]{pkgName}; @@ -700,13 +721,22 @@ public class NotificationManagerService extends SystemService { for (String pkgName : pkgList) { if (cancelNotifications) { cancelAllNotificationsInt(MY_UID, MY_PID, pkgName, 0, 0, !queryRestart, - UserHandle.USER_ALL, REASON_PACKAGE_CHANGED, null); + changeUserId, REASON_PACKAGE_CHANGED, null); } } } mListeners.onPackagesChanged(queryReplace, pkgList); mConditionProviders.onPackagesChanged(queryReplace, pkgList); - } else if (action.equals(Intent.ACTION_SCREEN_ON)) { + } + } + }; + + private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + + if (action.equals(Intent.ACTION_SCREEN_ON)) { // Keep track of screen on/off state, but do not turn off the notification light // until user passes through the lock screen or views the notification. mScreenOn = true; @@ -889,6 +919,7 @@ public class NotificationManagerService extends SystemService { filter.addAction(Intent.ACTION_USER_SWITCHED); filter.addAction(Intent.ACTION_USER_ADDED); getContext().registerReceiver(mIntentReceiver, filter); + IntentFilter pkgFilter = new IntentFilter(); pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED); pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); @@ -896,9 +927,12 @@ public class NotificationManagerService extends SystemService { pkgFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED); pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); pkgFilter.addDataScheme("package"); - getContext().registerReceiver(mIntentReceiver, pkgFilter); + getContext().registerReceiverAsUser(mPackageIntentReceiver, UserHandle.ALL, pkgFilter, null, + null); + IntentFilter sdFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); - getContext().registerReceiver(mIntentReceiver, sdFilter); + getContext().registerReceiverAsUser(mPackageIntentReceiver, UserHandle.ALL, sdFilter, null, + null); mSettingsObserver = new SettingsObserver(mHandler); @@ -1698,14 +1732,6 @@ public class NotificationManagerService extends SystemService { } } - // This conditional is a dirty hack to limit the logging done on - // behalf of the download manager without affecting other apps. - if (!pkg.equals("com.android.providers.downloads") - || Log.isLoggable("DownloadManager", Log.VERBOSE)) { - EventLogTags.writeNotificationEnqueue(callingUid, callingPid, - pkg, id, tag, userId, notification.toString()); - } - if (pkg == null || notification == null) { throw new IllegalArgumentException("null not allowed: pkg=" + pkg + " id=" + id + " notification=" + notification); @@ -1755,6 +1781,14 @@ public class NotificationManagerService extends SystemService { } mRankingHelper.extractSignals(r); + // This conditional is a dirty hack to limit the logging done on + // behalf of the download manager without affecting other apps. + if (!pkg.equals("com.android.providers.downloads") + || Log.isLoggable("DownloadManager", Log.VERBOSE)) { + EventLogTags.writeNotificationEnqueue(callingUid, callingPid, + pkg, id, tag, userId, notification.toString(), + (old != null) ? 1 : 0); + } // 3. Apply local rules // blocked apps @@ -2358,6 +2392,8 @@ public class NotificationManagerService extends SystemService { // Save it for users of getHistoricalNotifications() mArchive.record(r.sbn); + + EventLogTags.writeNotificationCanceled(r.getKey(), reason); } /** diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java index a7eebf832f09..cb9a45e41768 100644 --- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java +++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java @@ -23,9 +23,9 @@ import android.app.job.JobService; import android.content.ComponentName; import android.content.Context; import android.os.ServiceManager; +import android.util.ArraySet; import android.util.Log; -import java.util.HashSet; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -59,7 +59,7 @@ public class BackgroundDexOptService extends JobService { if (pm.isStorageLow()) { return false; } - final HashSet<String> pkgs = pm.getPackagesThatNeedDexOpt(); + final ArraySet<String> pkgs = pm.getPackagesThatNeedDexOpt(); if (pkgs == null) { return false; } diff --git a/services/core/java/com/android/server/pm/GrantedPermissions.java b/services/core/java/com/android/server/pm/GrantedPermissions.java index 14258a46a564..8f0f93542861 100644 --- a/services/core/java/com/android/server/pm/GrantedPermissions.java +++ b/services/core/java/com/android/server/pm/GrantedPermissions.java @@ -17,13 +17,12 @@ package com.android.server.pm; import android.content.pm.ApplicationInfo; - -import java.util.HashSet; +import android.util.ArraySet; class GrantedPermissions { int pkgFlags; - HashSet<String> grantedPermissions = new HashSet<String>(); + ArraySet<String> grantedPermissions = new ArraySet<String>(); int[] gids; @@ -34,7 +33,7 @@ class GrantedPermissions { @SuppressWarnings("unchecked") GrantedPermissions(GrantedPermissions base) { pkgFlags = base.pkgFlags; - grantedPermissions = (HashSet<String>) base.grantedPermissions.clone(); + grantedPermissions = new ArraySet<>(base.grantedPermissions); if (base.gids != null) { gids = base.gids.clone(); diff --git a/services/core/java/com/android/server/pm/PackageKeySetData.java b/services/core/java/com/android/server/pm/PackageKeySetData.java index 9f9bafd39035..8f12c03b8646 100644 --- a/services/core/java/com/android/server/pm/PackageKeySetData.java +++ b/services/core/java/com/android/server/pm/PackageKeySetData.java @@ -16,10 +16,9 @@ package com.android.server.pm; -import com.android.internal.util.ArrayUtils; +import android.util.ArrayMap; -import java.util.HashMap; -import java.util.Map; +import com.android.internal.util.ArrayUtils; public class PackageKeySetData { @@ -34,7 +33,7 @@ public class PackageKeySetData { private long[] mDefinedKeySets; - private final Map<String, Long> mKeySetAliases = new HashMap<String, Long>(); + private final ArrayMap<String, Long> mKeySetAliases = new ArrayMap<String, Long>(); PackageKeySetData() { mProperSigningKeySet = KEYSET_UNASSIGNED; @@ -132,7 +131,7 @@ public class PackageKeySetData { return mDefinedKeySets; } - protected Map<String, Long> getAliases() { + protected ArrayMap<String, Long> getAliases() { return mKeySetAliases; } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index b79e15756a11..f9a85dfd4929 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -84,6 +84,8 @@ import android.app.AppGlobals; import android.app.IActivityManager; import android.app.admin.IDevicePolicyManager; import android.app.backup.IBackupManager; +import android.app.usage.UsageStats; +import android.app.usage.UsageStatsManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -199,8 +201,6 @@ import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -329,9 +329,11 @@ public class PackageManagerService extends IPackageManager.Stub { final boolean mFactoryTest; final boolean mOnlyCore; final boolean mLazyDexOpt; + final long mDexOptLRUThresholdInMills; final DisplayMetrics mMetrics; final int mDefParseFlags; final String[] mSeparateProcesses; + final boolean mIsUpgrade; // This is where all application persistent data goes. final File mAppDataDir; @@ -371,20 +373,20 @@ public class PackageManagerService extends IPackageManager.Stub { // Keys are String (package name), values are Package. This also serves // as the lock for the global state. Methods that must be called with // this lock held have the prefix "LP". - final HashMap<String, PackageParser.Package> mPackages = - new HashMap<String, PackageParser.Package>(); + final ArrayMap<String, PackageParser.Package> mPackages = + new ArrayMap<String, PackageParser.Package>(); // Tracks available target package names -> overlay package paths. - final HashMap<String, HashMap<String, PackageParser.Package>> mOverlays = - new HashMap<String, HashMap<String, PackageParser.Package>>(); + final ArrayMap<String, ArrayMap<String, PackageParser.Package>> mOverlays = + new ArrayMap<String, ArrayMap<String, PackageParser.Package>>(); final Settings mSettings; boolean mRestoredSettings; // System configuration read by SystemConfig. final int[] mGlobalGids; - final SparseArray<HashSet<String>> mSystemPermissions; - final HashMap<String, FeatureInfo> mAvailableFeatures; + final SparseArray<ArraySet<String>> mSystemPermissions; + final ArrayMap<String, FeatureInfo> mAvailableFeatures; // If mac_permissions.xml was found for seinfo labeling. boolean mFoundPolicyFile; @@ -403,8 +405,8 @@ public class PackageManagerService extends IPackageManager.Stub { } // Currently known shared libraries. - final HashMap<String, SharedLibraryEntry> mSharedLibraries = - new HashMap<String, SharedLibraryEntry>(); + final ArrayMap<String, SharedLibraryEntry> mSharedLibraries = + new ArrayMap<String, SharedLibraryEntry>(); // All available activities, for your resolving pleasure. final ActivityIntentResolver mActivities = @@ -422,23 +424,23 @@ public class PackageManagerService extends IPackageManager.Stub { // Mapping from provider base names (first directory in content URI codePath) // to the provider information. - final HashMap<String, PackageParser.Provider> mProvidersByAuthority = - new HashMap<String, PackageParser.Provider>(); + final ArrayMap<String, PackageParser.Provider> mProvidersByAuthority = + new ArrayMap<String, PackageParser.Provider>(); // Mapping from instrumentation class names to info about them. - final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation = - new HashMap<ComponentName, PackageParser.Instrumentation>(); + final ArrayMap<ComponentName, PackageParser.Instrumentation> mInstrumentation = + new ArrayMap<ComponentName, PackageParser.Instrumentation>(); // Mapping from permission names to info about them. - final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups = - new HashMap<String, PackageParser.PermissionGroup>(); + final ArrayMap<String, PackageParser.PermissionGroup> mPermissionGroups = + new ArrayMap<String, PackageParser.PermissionGroup>(); // Packages whose data we have transfered into another package, thus // should no longer exist. - final HashSet<String> mTransferedPackages = new HashSet<String>(); + final ArraySet<String> mTransferedPackages = new ArraySet<String>(); // Broadcast actions that are only available to the system. - final HashSet<String> mProtectedBroadcasts = new HashSet<String>(); + final ArraySet<String> mProtectedBroadcasts = new ArraySet<String>(); /** List of packages waiting for verification. */ final SparseArray<PackageVerificationState> mPendingVerification @@ -449,7 +451,7 @@ public class PackageManagerService extends IPackageManager.Stub { final PackageInstallerService mInstallerService; - HashSet<PackageParser.Package> mDeferredDexOpt = null; + ArraySet<PackageParser.Package> mDeferredDexOpt = null; // Cache of users who need badging. SparseBooleanArray mUserNeedsBadging = new SparseBooleanArray(); @@ -473,24 +475,24 @@ public class PackageManagerService extends IPackageManager.Stub { // Set of pending broadcasts for aggregating enable/disable of components. static class PendingPackageBroadcasts { // for each user id, a map of <package name -> components within that package> - final SparseArray<HashMap<String, ArrayList<String>>> mUidMap; + final SparseArray<ArrayMap<String, ArrayList<String>>> mUidMap; public PendingPackageBroadcasts() { - mUidMap = new SparseArray<HashMap<String, ArrayList<String>>>(2); + mUidMap = new SparseArray<ArrayMap<String, ArrayList<String>>>(2); } public ArrayList<String> get(int userId, String packageName) { - HashMap<String, ArrayList<String>> packages = getOrAllocate(userId); + ArrayMap<String, ArrayList<String>> packages = getOrAllocate(userId); return packages.get(packageName); } public void put(int userId, String packageName, ArrayList<String> components) { - HashMap<String, ArrayList<String>> packages = getOrAllocate(userId); + ArrayMap<String, ArrayList<String>> packages = getOrAllocate(userId); packages.put(packageName, components); } public void remove(int userId, String packageName) { - HashMap<String, ArrayList<String>> packages = mUidMap.get(userId); + ArrayMap<String, ArrayList<String>> packages = mUidMap.get(userId); if (packages != null) { packages.remove(packageName); } @@ -508,7 +510,7 @@ public class PackageManagerService extends IPackageManager.Stub { return mUidMap.keyAt(n); } - public HashMap<String, ArrayList<String>> packagesForUserId(int userId) { + public ArrayMap<String, ArrayList<String>> packagesForUserId(int userId) { return mUidMap.get(userId); } @@ -525,10 +527,10 @@ public class PackageManagerService extends IPackageManager.Stub { mUidMap.clear(); } - private HashMap<String, ArrayList<String>> getOrAllocate(int userId) { - HashMap<String, ArrayList<String>> map = mUidMap.get(userId); + private ArrayMap<String, ArrayList<String>> getOrAllocate(int userId) { + ArrayMap<String, ArrayList<String>> map = mUidMap.get(userId); if (map == null) { - map = new HashMap<String, ArrayList<String>>(); + map = new ArrayMap<String, ArrayList<String>>(); mUidMap.put(userId, map); } return map; @@ -565,7 +567,7 @@ public class PackageManagerService extends IPackageManager.Stub { static UserManagerService sUserManager; // Stores a list of users whose package restrictions file needs to be updated - private HashSet<Integer> mDirtyUsers = new HashSet<Integer>(); + private ArraySet<Integer> mDirtyUsers = new ArraySet<Integer>(); final private DefaultContainerConnection mDefContainerConn = new DefaultContainerConnection(); @@ -1294,6 +1296,15 @@ public class PackageManagerService extends IPackageManager.Stub { mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID, ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED); + // TODO: add a property to control this? + long dexOptLRUThresholdInMinutes; + if (mLazyDexOpt) { + dexOptLRUThresholdInMinutes = 30; // only last 30 minutes of apps for eng builds. + } else { + dexOptLRUThresholdInMinutes = 7 * 24 * 60; // apps used in the 7 days for users. + } + mDexOptLRUThresholdInMills = dexOptLRUThresholdInMinutes * 60 * 1000; + String separateProcesses = SystemProperties.get("debug.separate_processes"); if (separateProcesses != null && separateProcesses.length() > 0) { if ("*".equals(separateProcesses)) { @@ -1384,7 +1395,7 @@ public class PackageManagerService extends IPackageManager.Stub { // scanning install directories. final int scanFlags = SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING; - final HashSet<String> alreadyDexOpted = new HashSet<String>(); + final ArraySet<String> alreadyDexOpted = new ArraySet<String>(); /** * Add everything in the in the boot class path to the @@ -1750,7 +1761,8 @@ public class PackageManagerService extends IPackageManager.Stub { // If this is first boot after an OTA, and a normal boot, then // we need to clear code cache directories. - if (!Build.FINGERPRINT.equals(mSettings.mFingerprint) && !onlyCore) { + mIsUpgrade = !Build.FINGERPRINT.equals(mSettings.mFingerprint); + if (mIsUpgrade && !onlyCore) { Slog.i(TAG, "Build fingerprint changed; clearing code caches"); for (String pkgName : mSettings.mPackages.keySet()) { deleteCodeCacheDirsLI(pkgName); @@ -1790,6 +1802,11 @@ public class PackageManagerService extends IPackageManager.Stub { return mOnlyCore; } + @Override + public boolean isUpgrade() { + return mIsUpgrade; + } + private String getRequiredVerifierLPr() { final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION); final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE, @@ -2369,7 +2386,7 @@ public class PackageManagerService extends IPackageManager.Stub { return PackageManager.PERMISSION_GRANTED; } } else { - HashSet<String> perms = mSystemPermissions.get(uid); + ArraySet<String> perms = mSystemPermissions.get(uid); if (perms != null && perms.contains(permName)) { return PackageManager.PERMISSION_GRANTED; } @@ -2790,11 +2807,11 @@ public class PackageManagerService extends IPackageManager.Stub { PackageManager.SIGNATURE_NO_MATCH; } - HashSet<Signature> set1 = new HashSet<Signature>(); + ArraySet<Signature> set1 = new ArraySet<Signature>(); for (Signature sig : s1) { set1.add(sig); } - HashSet<Signature> set2 = new HashSet<Signature>(); + ArraySet<Signature> set2 = new ArraySet<Signature>(); for (Signature sig : s2) { set2.add(sig); } @@ -2829,11 +2846,11 @@ public class PackageManagerService extends IPackageManager.Stub { return PackageManager.SIGNATURE_NO_MATCH; } - HashSet<Signature> existingSet = new HashSet<Signature>(); + ArraySet<Signature> existingSet = new ArraySet<Signature>(); for (Signature sig : existingSigs.mSignatures) { existingSet.add(sig); } - HashSet<Signature> scannedCompatSet = new HashSet<Signature>(); + ArraySet<Signature> scannedCompatSet = new ArraySet<Signature>(); for (Signature sig : scannedPkg.mSignatures) { try { Signature[] chainSignatures = sig.getChainSignatures(); @@ -3249,7 +3266,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (DEBUG_PREFERRED) { Slog.v(TAG, "Preferred activity bookkeeping changed; writing restrictions"); } - mSettings.writePackageRestrictionsLPr(userId); + scheduleWritePackageRestrictionsLocked(userId); } } } @@ -4023,7 +4040,7 @@ public class PackageManagerService extends IPackageManager.Stub { } private void createIdmapsForPackageLI(PackageParser.Package pkg) { - HashMap<String, PackageParser.Package> overlays = mOverlays.get(pkg.packageName); + ArrayMap<String, PackageParser.Package> overlays = mOverlays.get(pkg.packageName); if (overlays == null) { Slog.w(TAG, "Unable to create idmap for " + pkg.packageName + ": no overlay packages"); return; @@ -4044,7 +4061,7 @@ public class PackageManagerService extends IPackageManager.Stub { opkg.baseCodePath + ": overlay not trusted"); return false; } - HashMap<String, PackageParser.Package> overlaySet = mOverlays.get(pkg.packageName); + ArrayMap<String, PackageParser.Package> overlaySet = mOverlays.get(pkg.packageName); if (overlaySet == null) { Slog.e(TAG, "was about to create idmap for " + pkg.baseCodePath + " and " + opkg.baseCodePath + " but target package has no known overlays"); @@ -4465,7 +4482,7 @@ public class PackageManagerService extends IPackageManager.Stub { public void performBootDexOpt() { enforceSystemOrRoot("Only the system can request dexopt be performed"); - final HashSet<PackageParser.Package> pkgs; + final ArraySet<PackageParser.Package> pkgs; synchronized (mPackages) { pkgs = mDeferredDexOpt; mDeferredDexOpt = null; @@ -4488,7 +4505,7 @@ public class PackageManagerService extends IPackageManager.Stub { } // Give priority to system apps that listen for pre boot complete. Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED); - HashSet<String> pkgNames = getPackageNamesForIntent(intent); + ArraySet<String> pkgNames = getPackageNamesForIntent(intent); for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) { PackageParser.Package pkg = it.next(); if (pkgNames.contains(pkg.packageName)) { @@ -4562,28 +4579,19 @@ public class PackageManagerService extends IPackageManager.Stub { } } - private void filterRecentlyUsedApps(HashSet<PackageParser.Package> pkgs) { + private void filterRecentlyUsedApps(ArraySet<PackageParser.Package> pkgs) { // Filter out packages that aren't recently used. // // The exception is first boot of a non-eng device (aka !mLazyDexOpt), which // should do a full dexopt. if (mLazyDexOpt || (!isFirstBoot() && mPackageUsage.isHistoricalPackageUsageAvailable())) { - // TODO: add a property to control this? - long dexOptLRUThresholdInMinutes; - if (mLazyDexOpt) { - dexOptLRUThresholdInMinutes = 30; // only last 30 minutes of apps for eng builds. - } else { - dexOptLRUThresholdInMinutes = 7 * 24 * 60; // apps used in the 7 days for users. - } - long dexOptLRUThresholdInMills = dexOptLRUThresholdInMinutes * 60 * 1000; - int total = pkgs.size(); int skipped = 0; long now = System.currentTimeMillis(); for (Iterator<PackageParser.Package> i = pkgs.iterator(); i.hasNext();) { PackageParser.Package pkg = i.next(); long then = pkg.mLastPackageUsageTimeInMills; - if (then + dexOptLRUThresholdInMills < now) { + if (then + mDexOptLRUThresholdInMills < now) { if (DEBUG_DEXOPT) { Log.i(TAG, "Skipping dexopt of " + pkg.packageName + " last resumed: " + ((then == 0) ? "never" : new Date(then))); @@ -4598,14 +4606,14 @@ public class PackageManagerService extends IPackageManager.Stub { } } - private HashSet<String> getPackageNamesForIntent(Intent intent) { + private ArraySet<String> getPackageNamesForIntent(Intent intent) { List<ResolveInfo> ris = null; try { ris = AppGlobals.getPackageManager().queryIntentReceivers( intent, null, 0, UserHandle.USER_OWNER); } catch (RemoteException e) { } - HashSet<String> pkgNames = new HashSet<String>(); + ArraySet<String> pkgNames = new ArraySet<String>(); if (ris != null) { for (ResolveInfo ri : ris) { pkgNames.add(ri.activityInfo.packageName); @@ -4683,8 +4691,8 @@ public class PackageManagerService extends IPackageManager.Stub { } } - public HashSet<String> getPackagesThatNeedDexOpt() { - HashSet<String> pkgs = null; + public ArraySet<String> getPackagesThatNeedDexOpt() { + ArraySet<String> pkgs = null; synchronized (mPackages) { for (PackageParser.Package p : mPackages.values()) { if (DEBUG_DEXOPT) { @@ -4694,7 +4702,7 @@ public class PackageManagerService extends IPackageManager.Stub { continue; } if (pkgs == null) { - pkgs = new HashSet<String>(); + pkgs = new ArraySet<String>(); } pkgs.add(p.packageName); } @@ -4707,7 +4715,7 @@ public class PackageManagerService extends IPackageManager.Stub { } private void performDexOptLibsLI(ArrayList<String> libs, String[] instructionSets, - boolean forceDex, boolean defer, HashSet<String> done) { + boolean forceDex, boolean defer, ArraySet<String> done) { for (int i=0; i<libs.size(); i++) { PackageParser.Package libPkg; String libName; @@ -4732,7 +4740,7 @@ public class PackageManagerService extends IPackageManager.Stub { static final int DEX_OPT_FAILED = -1; private int performDexOptLI(PackageParser.Package pkg, String[] targetInstructionSets, - boolean forceDex, boolean defer, HashSet<String> done) { + boolean forceDex, boolean defer, ArraySet<String> done) { final String[] instructionSets = targetInstructionSets != null ? targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo); @@ -4810,7 +4818,7 @@ public class PackageManagerService extends IPackageManager.Stub { // our list of deferred dexopts. if (defer && isDexOptNeeded != DexFile.UP_TO_DATE) { if (mDeferredDexOpt == null) { - mDeferredDexOpt = new HashSet<PackageParser.Package>(); + mDeferredDexOpt = new ArraySet<PackageParser.Package>(); } mDeferredDexOpt.add(pkg); return DEX_OPT_DEFERRED; @@ -4907,7 +4915,7 @@ public class PackageManagerService extends IPackageManager.Stub { } private static String[] getDexCodeInstructionSets(String[] instructionSets) { - HashSet<String> dexCodeInstructionSets = new HashSet<String>(instructionSets.length); + ArraySet<String> dexCodeInstructionSets = new ArraySet<String>(instructionSets.length); for (String instructionSet : instructionSets) { dexCodeInstructionSets.add(getDexCodeInstructionSet(instructionSet)); } @@ -4950,9 +4958,9 @@ public class PackageManagerService extends IPackageManager.Stub { private int performDexOptLI(PackageParser.Package pkg, String[] instructionSets, boolean forceDex, boolean defer, boolean inclDependencies) { - HashSet<String> done; + ArraySet<String> done; if (inclDependencies && (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null)) { - done = new HashSet<String>(); + done = new ArraySet<String>(); done.add(pkg.packageName); } else { done = null; @@ -6137,7 +6145,7 @@ public class PackageManagerService extends IPackageManager.Stub { r = null; for (i=0; i<N; i++) { PackageParser.Permission p = pkg.permissions.get(i); - HashMap<String, BasePermission> permissionMap = + ArrayMap<String, BasePermission> permissionMap = p.tree ? mSettings.mPermissionTrees : mSettings.mPermissions; p.group = mPermissionGroups.get(p.info.group); @@ -6265,9 +6273,9 @@ public class PackageManagerService extends IPackageManager.Stub { if (pkg.mOverlayTarget != null && !pkg.mOverlayTarget.equals("android")) { if (!mOverlays.containsKey(pkg.mOverlayTarget)) { mOverlays.put(pkg.mOverlayTarget, - new HashMap<String, PackageParser.Package>()); + new ArrayMap<String, PackageParser.Package>()); } - HashMap<String, PackageParser.Package> map = mOverlays.get(pkg.mOverlayTarget); + ArrayMap<String, PackageParser.Package> map = mOverlays.get(pkg.mOverlayTarget); map.put(pkg.packageName, pkg); PackageParser.Package orig = mPackages.get(pkg.mOverlayTarget); if (orig != null && !createIdmapForPackagePairLI(orig, pkg)) { @@ -6928,13 +6936,13 @@ public class PackageManagerService extends IPackageManager.Stub { return; } final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps; - HashSet<String> origPermissions = gp.grantedPermissions; + ArraySet<String> origPermissions = gp.grantedPermissions; boolean changedPermission = false; if (replace) { ps.permissionsFixed = false; if (gp == ps) { - origPermissions = new HashSet<String>(gp.grantedPermissions); + origPermissions = new ArraySet<String>(gp.grantedPermissions); gp.grantedPermissions.clear(); gp.gids = mGlobalGids; } @@ -7081,7 +7089,7 @@ public class PackageManagerService extends IPackageManager.Stub { } private boolean grantSignaturePermission(String perm, PackageParser.Package pkg, - BasePermission bp, HashSet<String> origPermissions) { + BasePermission bp, ArraySet<String> origPermissions) { boolean allowed; allowed = (compareSignatures( bp.packageSetting.signatures.mSignatures, pkg.mSignatures) @@ -7339,8 +7347,8 @@ public class PackageManagerService extends IPackageManager.Stub { // } // Keys are String (activity class name), values are Activity. - private final HashMap<ComponentName, PackageParser.Activity> mActivities - = new HashMap<ComponentName, PackageParser.Activity>(); + private final ArrayMap<ComponentName, PackageParser.Activity> mActivities + = new ArrayMap<ComponentName, PackageParser.Activity>(); private int mFlags; } @@ -7538,8 +7546,8 @@ public class PackageManagerService extends IPackageManager.Stub { // } // Keys are String (activity class name), values are Activity. - private final HashMap<ComponentName, PackageParser.Service> mServices - = new HashMap<ComponentName, PackageParser.Service>(); + private final ArrayMap<ComponentName, PackageParser.Service> mServices + = new ArrayMap<ComponentName, PackageParser.Service>(); private int mFlags; }; @@ -7732,8 +7740,8 @@ public class PackageManagerService extends IPackageManager.Stub { out.println(Integer.toHexString(System.identityHashCode(filter))); } - private final HashMap<ComponentName, PackageParser.Provider> mProviders - = new HashMap<ComponentName, PackageParser.Provider>(); + private final ArrayMap<ComponentName, PackageParser.Provider> mProviders + = new ArrayMap<ComponentName, PackageParser.Provider>(); private int mFlags; }; @@ -10402,6 +10410,60 @@ public class PackageManagerService extends IPackageManager.Stub { String oldCodePath = null; boolean systemApp = false; synchronized (mPackages) { + // Check if installing already existing package + if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) { + String oldName = mSettings.mRenamedPackages.get(pkgName); + if (pkg.mOriginalPackages != null + && pkg.mOriginalPackages.contains(oldName) + && mPackages.containsKey(oldName)) { + // This package is derived from an original package, + // and this device has been updating from that original + // name. We must continue using the original name, so + // rename the new package here. + pkg.setPackageName(oldName); + pkgName = pkg.packageName; + replace = true; + if (DEBUG_INSTALL) Slog.d(TAG, "Replacing existing renamed package: oldName=" + + oldName + " pkgName=" + pkgName); + } else if (mPackages.containsKey(pkgName)) { + // This package, under its official name, already exists + // on the device; we should replace it. + replace = true; + if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing pacakge: " + pkgName); + } + } + + PackageSetting ps = mSettings.mPackages.get(pkgName); + if (ps != null) { + if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps); + + // Quick sanity check that we're signed correctly if updating; + // we'll check this again later when scanning, but we want to + // bail early here before tripping over redefined permissions. + if (!ps.keySetData.isUsingUpgradeKeySets() || ps.sharedUser != null) { + try { + verifySignaturesLP(ps, pkg); + } catch (PackageManagerException e) { + res.setError(e.error, e.getMessage()); + return; + } + } else { + if (!checkUpgradeKeySetLP(ps, pkg)) { + res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package " + + pkg.packageName + " upgrade keys do not match the " + + "previously installed version"); + return; + } + } + + oldCodePath = mSettings.mPackages.get(pkgName).codePathString; + if (ps.pkg != null && ps.pkg.applicationInfo != null) { + systemApp = (ps.pkg.applicationInfo.flags & + ApplicationInfo.FLAG_SYSTEM) != 0; + } + res.origUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true); + } + // Check whether the newly-scanned package wants to define an already-defined perm int N = pkg.permissions.size(); for (int i = N-1; i >= 0; i--) { @@ -10442,38 +10504,6 @@ public class PackageManagerService extends IPackageManager.Stub { } } - // Check if installing already existing package - if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) { - String oldName = mSettings.mRenamedPackages.get(pkgName); - if (pkg.mOriginalPackages != null - && pkg.mOriginalPackages.contains(oldName) - && mPackages.containsKey(oldName)) { - // This package is derived from an original package, - // and this device has been updating from that original - // name. We must continue using the original name, so - // rename the new package here. - pkg.setPackageName(oldName); - pkgName = pkg.packageName; - replace = true; - if (DEBUG_INSTALL) Slog.d(TAG, "Replacing existing renamed package: oldName=" - + oldName + " pkgName=" + pkgName); - } else if (mPackages.containsKey(pkgName)) { - // This package, under its official name, already exists - // on the device; we should replace it. - replace = true; - if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing pacakge: " + pkgName); - } - } - PackageSetting ps = mSettings.mPackages.get(pkgName); - if (ps != null) { - if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps); - oldCodePath = mSettings.mPackages.get(pkgName).codePathString; - if (ps.pkg != null && ps.pkg.applicationInfo != null) { - systemApp = (ps.pkg.applicationInfo.flags & - ApplicationInfo.FLAG_SYSTEM) != 0; - } - res.origUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true); - } } if (systemApp && onSd) { @@ -11536,7 +11566,7 @@ public class PackageManagerService extends IPackageManager.Stub { + userId + ":"); filter.dump(new LogPrinter(Log.INFO, TAG), " "); pir.addFilter(new PreferredActivity(filter, match, set, activity, always)); - mSettings.writePackageRestrictionsLPr(userId); + scheduleWritePackageRestrictionsLocked(userId); } } @@ -11652,8 +11682,7 @@ public class PackageManagerService extends IPackageManager.Stub { int user = UserHandle.getCallingUserId(); if (clearPackagePreferredActivitiesLPw(packageName, user)) { - mSettings.writePackageRestrictionsLPr(user); - scheduleWriteSettingsLocked(); + scheduleWritePackageRestrictionsLocked(user); } } } @@ -11703,8 +11732,7 @@ public class PackageManagerService extends IPackageManager.Stub { int user = UserHandle.getCallingUserId(); clearPackagePreferredActivitiesLPw(null, user); mSettings.readDefaultPreferredAppsLPw(this, user); - mSettings.writePackageRestrictionsLPr(user); - scheduleWriteSettingsLocked(); + scheduleWritePackageRestrictionsLocked(user); } } @@ -11756,7 +11784,7 @@ public class PackageManagerService extends IPackageManager.Stub { filter.dump(new LogPrinter(Log.INFO, TAG), " "); mSettings.editPersistentPreferredActivitiesLPw(userId).addFilter( new PersistentPreferredActivity(filter, activity)); - mSettings.writePackageRestrictionsLPr(userId); + scheduleWritePackageRestrictionsLocked(userId); } } @@ -11798,7 +11826,7 @@ public class PackageManagerService extends IPackageManager.Stub { } if (changed) { - mSettings.writePackageRestrictionsLPr(userId); + scheduleWritePackageRestrictionsLocked(userId); } } } @@ -11819,7 +11847,7 @@ public class PackageManagerService extends IPackageManager.Stub { CrossProfileIntentFilter filter = new CrossProfileIntentFilter(intentFilter, ownerPackage, UserHandle.getUserId(callingUid), targetUserId, flags); mSettings.editCrossProfileIntentResolverLPw(sourceUserId).addFilter(filter); - mSettings.writePackageRestrictionsLPr(sourceUserId); + scheduleWritePackageRestrictionsLocked(sourceUserId); } } @@ -11835,15 +11863,15 @@ public class PackageManagerService extends IPackageManager.Stub { synchronized (mPackages) { CrossProfileIntentResolver resolver = mSettings.editCrossProfileIntentResolverLPw(sourceUserId); - HashSet<CrossProfileIntentFilter> set = - new HashSet<CrossProfileIntentFilter>(resolver.filterSet()); + ArraySet<CrossProfileIntentFilter> set = + new ArraySet<CrossProfileIntentFilter>(resolver.filterSet()); for (CrossProfileIntentFilter filter : set) { if (filter.getOwnerPackage().equals(ownerPackage) && filter.getOwnerUserId() == callingUserId) { resolver.removeFilter(filter); } } - mSettings.writePackageRestrictionsLPr(sourceUserId); + scheduleWritePackageRestrictionsLocked(sourceUserId); } } @@ -13381,4 +13409,25 @@ public class PackageManagerService extends IPackageManager.Stub { return false; } } + + public void getUsageStatsIfNoPackageUsageInfo() { + if (!mPackageUsage.isHistoricalPackageUsageAvailable()) { + UsageStatsManager usm = (UsageStatsManager) mContext.getSystemService(Context.USAGE_STATS_SERVICE); + if (usm == null) { + throw new IllegalStateException("UsageStatsManager must be initialized"); + } + long now = System.currentTimeMillis(); + Map<String, UsageStats> stats = usm.queryAndAggregateUsageStats(now - mDexOptLRUThresholdInMills, now); + for (Map.Entry<String, UsageStats> entry : stats.entrySet()) { + String packageName = entry.getKey(); + PackageParser.Package pkg = mPackages.get(packageName); + if (pkg == null) { + continue; + } + UsageStats usage = entry.getValue(); + pkg.mLastPackageUsageTimeInMills = usage.getLastTimeUsed(); + mPackageUsage.mIsHistoricalPackageUsageAvailable = true; + } + } + } } diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java index bf13fd97f5c6..1dcadb41089e 100644 --- a/services/core/java/com/android/server/pm/PackageSettingBase.java +++ b/services/core/java/com/android/server/pm/PackageSettingBase.java @@ -21,10 +21,10 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; import android.content.pm.PackageUserState; +import android.util.ArraySet; import android.util.SparseArray; import java.io.File; -import java.util.HashSet; /** * Settings base class for pending and resolved classes. @@ -321,8 +321,8 @@ class PackageSettingBase extends GrantedPermissions { void setUserState(int userId, int enabled, boolean installed, boolean stopped, boolean notLaunched, boolean hidden, - String lastDisableAppCaller, HashSet<String> enabledComponents, - HashSet<String> disabledComponents, boolean blockUninstall) { + String lastDisableAppCaller, ArraySet<String> enabledComponents, + ArraySet<String> disabledComponents, boolean blockUninstall) { PackageUserState state = modifyUserState(userId); state.enabled = enabled; state.installed = installed; @@ -335,39 +335,39 @@ class PackageSettingBase extends GrantedPermissions { state.blockUninstall = blockUninstall; } - HashSet<String> getEnabledComponents(int userId) { + ArraySet<String> getEnabledComponents(int userId) { return readUserState(userId).enabledComponents; } - HashSet<String> getDisabledComponents(int userId) { + ArraySet<String> getDisabledComponents(int userId) { return readUserState(userId).disabledComponents; } - void setEnabledComponents(HashSet<String> components, int userId) { + void setEnabledComponents(ArraySet<String> components, int userId) { modifyUserState(userId).enabledComponents = components; } - void setDisabledComponents(HashSet<String> components, int userId) { + void setDisabledComponents(ArraySet<String> components, int userId) { modifyUserState(userId).disabledComponents = components; } - void setEnabledComponentsCopy(HashSet<String> components, int userId) { + void setEnabledComponentsCopy(ArraySet<String> components, int userId) { modifyUserState(userId).enabledComponents = components != null - ? new HashSet<String>(components) : null; + ? new ArraySet<String>(components) : null; } - void setDisabledComponentsCopy(HashSet<String> components, int userId) { + void setDisabledComponentsCopy(ArraySet<String> components, int userId) { modifyUserState(userId).disabledComponents = components != null - ? new HashSet<String>(components) : null; + ? new ArraySet<String>(components) : null; } PackageUserState modifyUserStateComponents(int userId, boolean disabled, boolean enabled) { PackageUserState state = modifyUserState(userId); if (disabled && state.disabledComponents == null) { - state.disabledComponents = new HashSet<String>(1); + state.disabledComponents = new ArraySet<String>(1); } if (enabled && state.enabledComponents == null) { - state.enabledComponents = new HashSet<String>(1); + state.enabledComponents = new ArraySet<String>(1); } return state; } diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 7de56c890f6b..200eb5f16afb 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -63,6 +63,8 @@ import android.content.pm.Signature; import android.content.pm.UserInfo; import android.content.pm.PackageUserState; import android.content.pm.VerifierDeviceIdentity; +import android.util.ArrayMap; +import android.util.ArraySet; import android.util.Log; import android.util.Slog; import android.util.SparseArray; @@ -78,8 +80,6 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -159,11 +159,11 @@ final class Settings { private final File mStoppedPackagesFilename; private final File mBackupStoppedPackagesFilename; - final HashMap<String, PackageSetting> mPackages = - new HashMap<String, PackageSetting>(); + final ArrayMap<String, PackageSetting> mPackages = + new ArrayMap<String, PackageSetting>(); // List of replaced system applications - private final HashMap<String, PackageSetting> mDisabledSysPackages = - new HashMap<String, PackageSetting>(); + private final ArrayMap<String, PackageSetting> mDisabledSysPackages = + new ArrayMap<String, PackageSetting>(); private static int mFirstAvailableUid = 0; @@ -206,8 +206,8 @@ final class Settings { final SparseArray<CrossProfileIntentResolver> mCrossProfileIntentResolvers = new SparseArray<CrossProfileIntentResolver>(); - final HashMap<String, SharedUserSetting> mSharedUsers = - new HashMap<String, SharedUserSetting>(); + final ArrayMap<String, SharedUserSetting> mSharedUsers = + new ArrayMap<String, SharedUserSetting>(); private final ArrayList<Object> mUserIds = new ArrayList<Object>(); private final SparseArray<Object> mOtherUserIds = new SparseArray<Object>(); @@ -217,12 +217,12 @@ final class Settings { new ArrayList<Signature>(); // Mapping from permission names to info about them. - final HashMap<String, BasePermission> mPermissions = - new HashMap<String, BasePermission>(); + final ArrayMap<String, BasePermission> mPermissions = + new ArrayMap<String, BasePermission>(); // Mapping from permission tree names to info about them. - final HashMap<String, BasePermission> mPermissionTrees = - new HashMap<String, BasePermission>(); + final ArrayMap<String, BasePermission> mPermissionTrees = + new ArrayMap<String, BasePermission>(); // Packages that have been uninstalled and still need their external // storage data deleted. @@ -232,7 +232,7 @@ final class Settings { // Keys are the new names of the packages, values are the original // names. The packages appear everwhere else under their original // names. - final HashMap<String, String> mRenamedPackages = new HashMap<String, String>(); + final ArrayMap<String, String> mRenamedPackages = new ArrayMap<String, String>(); final StringBuilder mReadMessages = new StringBuilder(); @@ -437,7 +437,7 @@ final class Settings { void transferPermissionsLPw(String origPkg, String newPkg) { // Transfer ownership of permissions to the new package. for (int i=0; i<2; i++) { - HashMap<String, BasePermission> permissions = + ArrayMap<String, BasePermission> permissions = i == 0 ? mPermissionTrees : mPermissions; for (BasePermission bp : permissions.values()) { if (origPkg.equals(bp.sourcePackage)) { @@ -582,7 +582,7 @@ final class Settings { } p.appId = dis.appId; // Clone permissions - p.grantedPermissions = new HashSet<String>(dis.grantedPermissions); + p.grantedPermissions = new ArraySet<String>(dis.grantedPermissions); // Clone component info List<UserInfo> users = getAllUsers(); if (users != null) { @@ -1138,8 +1138,8 @@ final class Settings { final boolean blockUninstall = blockUninstallStr == null ? false : Boolean.parseBoolean(blockUninstallStr); - HashSet<String> enabledComponents = null; - HashSet<String> disabledComponents = null; + ArraySet<String> enabledComponents = null; + ArraySet<String> disabledComponents = null; int packageDepth = parser.getDepth(); while ((type=parser.next()) != XmlPullParser.END_DOCUMENT @@ -1189,9 +1189,9 @@ final class Settings { } } - private HashSet<String> readComponentsLPr(XmlPullParser parser) + private ArraySet<String> readComponentsLPr(XmlPullParser parser) throws IOException, XmlPullParserException { - HashSet<String> components = null; + ArraySet<String> components = null; int type; int outerDepth = parser.getDepth(); String tagName; @@ -1207,7 +1207,7 @@ final class Settings { String componentName = parser.getAttributeValue(null, ATTR_NAME); if (componentName != null) { if (components == null) { - components = new HashSet<String>(); + components = new ArraySet<String>(); } components.add(componentName); } @@ -1921,7 +1921,7 @@ final class Settings { } ArrayList<PackageSetting> getListOfIncompleteInstallPackagesLPr() { - final HashSet<String> kList = new HashSet<String>(mPackages.keySet()); + final ArraySet<String> kList = new ArraySet<String>(mPackages.keySet()); final Iterator<String> its = kList.iterator(); final ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>(); while (its.hasNext()) { @@ -2511,7 +2511,7 @@ final class Settings { return defValue; } - private void readPermissionsLPw(HashMap<String, BasePermission> out, XmlPullParser parser) + private void readPermissionsLPw(ArrayMap<String, BasePermission> out, XmlPullParser parser) throws IOException, XmlPullParserException { int outerDepth = parser.getDepth(); int type; @@ -3016,7 +3016,7 @@ final class Settings { } } - private void readGrantedPermissionsLPw(XmlPullParser parser, HashSet<String> outPerms) + private void readGrantedPermissionsLPw(XmlPullParser parser, ArraySet<String> outPerms) throws IOException, XmlPullParserException { int outerDepth = parser.getDepth(); int type; @@ -3090,8 +3090,8 @@ final class Settings { int sourceUserId = mCrossProfileIntentResolvers.keyAt(i); CrossProfileIntentResolver cpir = mCrossProfileIntentResolvers.get(sourceUserId); boolean needsWriting = false; - HashSet<CrossProfileIntentFilter> cpifs = - new HashSet<CrossProfileIntentFilter>(cpir.filterSet()); + ArraySet<CrossProfileIntentFilter> cpifs = + new ArraySet<CrossProfileIntentFilter>(cpir.filterSet()); for (CrossProfileIntentFilter cpif : cpifs) { if (cpif.getTargetUserId() == userId) { needsWriting = true; @@ -3147,7 +3147,7 @@ final class Settings { return ps; } - private String compToString(HashSet<String> cmp) { + private String compToString(ArraySet<String> cmp) { return cmp != null ? Arrays.toString(cmp.toArray()) : "[]"; } @@ -3477,7 +3477,7 @@ final class Settings { pw.print(prefix); pw.print(" lastDisabledCaller: "); pw.println(lastDisabledAppCaller); } - HashSet<String> cmp = ps.getDisabledComponents(user.id); + ArraySet<String> cmp = ps.getDisabledComponents(user.id); if (cmp != null && cmp.size() > 0) { pw.print(prefix); pw.println(" disabledComponents:"); for (String s : cmp) { diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java index ca1eeea69745..2b406f775d75 100644 --- a/services/core/java/com/android/server/pm/SharedUserSetting.java +++ b/services/core/java/com/android/server/pm/SharedUserSetting.java @@ -16,7 +16,7 @@ package com.android.server.pm; -import java.util.HashSet; +import android.util.ArraySet; /** * Settings data for a particular shared user ID we know about. @@ -29,7 +29,7 @@ final class SharedUserSetting extends GrantedPermissions { // flags that are associated with this uid, regardless of any package flags int uidFlags; - final HashSet<PackageSetting> packages = new HashSet<PackageSetting>(); + final ArraySet<PackageSetting> packages = new ArraySet<PackageSetting>(); final PackageSignatures signatures = new PackageSignatures(); diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index f85e2d9a29b6..15e0bf03d2e0 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -26,6 +26,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; import android.util.Slog; +import android.view.WindowManager; import com.android.internal.statusbar.IStatusBar; import com.android.internal.statusbar.IStatusBarService; @@ -295,9 +296,10 @@ public class StatusBarManagerService extends IStatusBarService.Stub { } } - /** + /** * Hide or show the on-screen Menu key. Only call this from the window manager, typically in - * response to a window with FLAG_NEEDS_MENU_KEY set. + * response to a window with {@link android.view.WindowManager.LayoutParams#needsMenuKey} set + * to {@link android.view.WindowManager.LayoutParams#NEEDS_MENU_SET_TRUE}. */ @Override public void topAppWindowChanged(final boolean menuVisible) { @@ -523,6 +525,20 @@ public class StatusBarManagerService extends IStatusBarService.Stub { } @Override + public void onNotificationActionClick(String key, int actionIndex) { + enforceStatusBarService(); + final int callingUid = Binder.getCallingUid(); + final int callingPid = Binder.getCallingPid(); + long identity = Binder.clearCallingIdentity(); + try { + mNotificationDelegate.onNotificationActionClick(callingUid, callingPid, key, + actionIndex); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override public void onNotificationError(String pkg, String tag, int id, int uid, int initialPid, String message, int userId) { enforceStatusBarService(); diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index f9b170443d8d..65cb35b5a910 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -16,6 +16,7 @@ package com.android.server.trust; +import com.android.internal.annotations.GuardedBy; import com.android.internal.content.PackageMonitor; import com.android.internal.widget.LockPatternUtils; import com.android.server.SystemService; @@ -24,6 +25,7 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import android.Manifest; +import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.admin.DevicePolicyManager; import android.app.trust.ITrustListener; @@ -41,6 +43,7 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.graphics.drawable.Drawable; +import android.os.Binder; import android.os.DeadObjectException; import android.os.Handler; import android.os.IBinder; @@ -100,8 +103,10 @@ public class TrustManagerService extends SystemService { /* package */ final TrustArchive mArchive = new TrustArchive(); private final Context mContext; private final LockPatternUtils mLockPatternUtils; + private final UserManager mUserManager; - private UserManager mUserManager; + @GuardedBy("mUserIsTrusted") + private final SparseBooleanArray mUserIsTrusted = new SparseBooleanArray(); public TrustManagerService(Context context) { super(context); @@ -117,11 +122,15 @@ public class TrustManagerService extends SystemService { @Override public void onBootPhase(int phase) { - if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY && !isSafeMode()) { + if (isSafeMode()) { + // No trust agents in safe mode. + return; + } + if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true); mReceiver.register(mContext); refreshAgentList(UserHandle.USER_ALL); - } else if (phase == SystemService.PHASE_BOOT_COMPLETED && !isSafeMode()) { + } else if (phase == SystemService.PHASE_BOOT_COMPLETED) { maybeEnableFactoryTrustAgents(mLockPatternUtils, UserHandle.USER_OWNER); } } @@ -160,11 +169,19 @@ public class TrustManagerService extends SystemService { public void updateTrust(int userId, boolean initiatedByUser) { dispatchOnTrustManagedChanged(aggregateIsTrustManaged(userId), userId); - dispatchOnTrustChanged(aggregateIsTrusted(userId), userId, initiatedByUser); + boolean trusted = aggregateIsTrusted(userId); + synchronized (mUserIsTrusted) { + mUserIsTrusted.put(userId, trusted); + } + dispatchOnTrustChanged(trusted, userId, initiatedByUser); } void refreshAgentList(int userId) { if (DEBUG) Slog.d(TAG, "refreshAgentList()"); + if (isSafeMode()) { + // Don't ever bind to trust agents in safe mode. + return; + } if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_OWNER) { Log.e(TAG, "refreshAgentList(userId=" + userId + "): Invalid user handle," + " must be USER_ALL or a specific user.", new Throwable("here")); @@ -547,6 +564,16 @@ public class TrustManagerService extends SystemService { mHandler.obtainMessage(MSG_UNREGISTER_LISTENER, trustListener).sendToTarget(); } + @Override + public boolean isTrusted(int userId) throws RemoteException { + userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId, + false /* allowAll */, true /* requireFull */, "isTrusted", null); + userId = resolveProfileParent(userId); + synchronized (mUserIsTrusted) { + return mUserIsTrusted.get(userId); + } + } + private void enforceReportPermission() { mContext.enforceCallingOrSelfPermission( Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, "reporting trust events"); @@ -561,6 +588,10 @@ public class TrustManagerService extends SystemService { protected void dump(FileDescriptor fd, final PrintWriter fout, String[] args) { mContext.enforceCallingPermission(Manifest.permission.DUMP, "dumping TrustManagerService"); + if (isSafeMode()) { + fout.println("disabled because the system is in safe mode."); + return; + } final UserInfo currentUser; final List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */); try { @@ -623,6 +654,19 @@ public class TrustManagerService extends SystemService { } }; + private int resolveProfileParent(int userId) { + long identity = Binder.clearCallingIdentity(); + try { + UserInfo parent = mUserManager.getProfileParent(userId); + if (parent != null) { + return parent.getUserHandle().getIdentifier(); + } + return userId; + } finally { + Binder.restoreCallingIdentity(identity); + } + } + private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { diff --git a/services/core/java/com/android/server/tv/TvInputHal.java b/services/core/java/com/android/server/tv/TvInputHal.java index 558ffb5e3ddd..c12dd633c07f 100644 --- a/services/core/java/com/android/server/tv/TvInputHal.java +++ b/services/core/java/com/android/server/tv/TvInputHal.java @@ -55,7 +55,7 @@ final class TvInputHal implements Handler.Callback { private native long nativeOpen(); - private static native int nativeAddStream(long ptr, int deviceId, int streamId, + private static native int nativeAddOrUpdateStream(long ptr, int deviceId, int streamId, Surface surface); private static native int nativeRemoveStream(long ptr, int deviceId, int streamId); private static native TvStreamConfig[] nativeGetStreamConfigs(long ptr, int deviceId, @@ -80,7 +80,7 @@ final class TvInputHal implements Handler.Callback { } } - public int addStream(int deviceId, Surface surface, TvStreamConfig streamConfig) { + public int addOrUpdateStream(int deviceId, Surface surface, TvStreamConfig streamConfig) { synchronized (mLock) { if (mPtr == 0) { return ERROR_NO_INIT; @@ -89,7 +89,7 @@ final class TvInputHal implements Handler.Callback { if (generation != streamConfig.getGeneration()) { return ERROR_STALE_CONFIG; } - if (nativeAddStream(mPtr, deviceId, streamConfig.getStreamId(), surface) == 0) { + if (nativeAddOrUpdateStream(mPtr, deviceId, streamConfig.getStreamId(), surface) == 0) { return SUCCESS; } else { return ERROR_UNKNOWN; diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java index 77ab33b6eb1d..85659cf78c80 100644 --- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java +++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java @@ -122,6 +122,8 @@ class TvInputHardwareManager implements TvInputHal.Callback { } catch (RemoteException e) { Slog.w(TAG, "Error registering listeners to HdmiControlService:", e); } + } else { + Slog.w(TAG, "HdmiControlService is not available"); } } } @@ -186,6 +188,11 @@ class TvInputHardwareManager implements TvInputHal.Callback { return; } connection.updateConfigsLocked(configs); + String inputId = mHardwareInputIdMap.get(deviceId); + if (inputId != null) { + mHandler.obtainMessage(ListenerHandler.STATE_CHANGED, + convertConnectedToState(configs.length > 0), 0, inputId).sendToTarget(); + } try { connection.getCallbackLocked().onStreamConfigChanged(configs); } catch (RemoteException e) { @@ -255,6 +262,9 @@ class TvInputHardwareManager implements TvInputHal.Callback { mHardwareInputIdMap.put(deviceId, info.getId()); mInputMap.put(info.getId(), info); + // Process pending state changes + + // For logical HDMI devices, they have information from HDMI CEC signals. for (int i = 0; i < mHdmiStateMap.size(); ++i) { TvInputHardwareInfo hardwareInfo = findHardwareInfoForHdmiPortLocked(mHdmiStateMap.keyAt(i)); @@ -266,8 +276,17 @@ class TvInputHardwareManager implements TvInputHal.Callback { mHandler.obtainMessage(ListenerHandler.STATE_CHANGED, convertConnectedToState(mHdmiStateMap.valueAt(i)), 0, inputId).sendToTarget(); + return; } } + // For the rest of the devices, we can tell by the number of available streams. + Connection connection = mConnections.get(deviceId); + if (connection != null) { + mHandler.obtainMessage(ListenerHandler.STATE_CHANGED, + convertConnectedToState(connection.getConfigsLocked().length > 0), 0, + info.getId()).sendToTarget(); + return; + } } } @@ -666,14 +685,14 @@ class TvInputHardwareManager implements TvInputHal.Callback { result = mHal.removeStream(mInfo.getDeviceId(), mActiveConfig); mActiveConfig = null; } else { - if (config != mActiveConfig && mActiveConfig != null) { + if (!config.equals(mActiveConfig)) { result = mHal.removeStream(mInfo.getDeviceId(), mActiveConfig); if (result != TvInputHal.SUCCESS) { mActiveConfig = null; return false; } } - result = mHal.addStream(mInfo.getDeviceId(), surface, config); + result = mHal.addOrUpdateStream(mInfo.getDeviceId(), surface, config); if (result == TvInputHal.SUCCESS) { mActiveConfig = config; } @@ -743,7 +762,7 @@ class TvInputHardwareManager implements TvInputHal.Callback { && sinkConfig.channelMask() != mDesiredChannelMask) || (mDesiredFormat != AudioFormat.ENCODING_DEFAULT && sinkConfig.format() != mDesiredFormat)) { - sinkConfig = mAudioSource.buildConfig(mDesiredSamplingRate, mDesiredChannelMask, + sinkConfig = mAudioSink.buildConfig(mDesiredSamplingRate, mDesiredChannelMask, mDesiredFormat, null); shouldRecreateAudioPatch = true; } @@ -799,7 +818,7 @@ class TvInputHardwareManager implements TvInputHal.Callback { return false; } - int result = mHal.addStream(mInfo.getDeviceId(), surface, config); + int result = mHal.addOrUpdateStream(mInfo.getDeviceId(), surface, config); return result == TvInputHal.SUCCESS; } } @@ -914,11 +933,18 @@ class TvInputHardwareManager implements TvInputHal.Callback { break; } case HDMI_DEVICE_UPDATED: { - SomeArgs args = (SomeArgs) msg.obj; - String inputId = (String) args.arg1; - HdmiDeviceInfo info = (HdmiDeviceInfo) args.arg2; - args.recycle(); - mListener.onHdmiDeviceUpdated(inputId, info); + HdmiDeviceInfo info = (HdmiDeviceInfo) msg.obj; + String inputId = null; + synchronized (mLock) { + inputId = mHdmiInputIdMap.get(info.getId()); + } + if (inputId != null) { + mListener.onHdmiDeviceUpdated(inputId, info); + } else { + Slog.w(TAG, "Could not resolve input ID matching the device info; " + + "ignoring."); + } + break; } default: { Slog.w(TAG, "Unhandled message: " + msg); @@ -986,11 +1012,7 @@ class TvInputHardwareManager implements TvInputHal.Callback { } mHdmiDeviceList.add(deviceInfo); messageType = ListenerHandler.HDMI_DEVICE_UPDATED; - String inputId = mHdmiInputIdMap.get(deviceInfo.getId()); - SomeArgs args = SomeArgs.obtain(); - args.arg1 = inputId; - args.arg2 = deviceInfo; - obj = args; + obj = deviceInfo; break; } } diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index fa1c0ff26017..f947b6ab8654 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -346,8 +346,7 @@ final class AccessibilityController { case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG: case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR: case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY: - case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL: - case WindowManager.LayoutParams.TYPE_RECENTS_OVERLAY: { + case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL: { Rect magnifiedRegionBounds = mTempRect2; mMagnifedViewport.getMagnifiedFrameInContentCoordsLocked( magnifiedRegionBounds); @@ -993,8 +992,7 @@ final class AccessibilityController { final int flags = windowState.mAttrs.flags; - // If the window is not touchable, do not report it but take into account - // the space it takes since the content behind it cannot be touched. + // If the window is not touchable - ignore. if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) { continue; } @@ -1015,9 +1013,14 @@ final class AccessibilityController { } } - // Account for the space this window takes. - unaccountedSpace.op(boundsInScreen, unaccountedSpace, - Region.Op.REVERSE_DIFFERENCE); + // Account for the space this window takes if the window + // is not an accessibility overlay which does not change + // the reported windows. + if (windowState.mAttrs.type == WindowManager.LayoutParams + .TYPE_ACCESSIBILITY_OVERLAY) { + unaccountedSpace.op(boundsInScreen, unaccountedSpace, + Region.Op.REVERSE_DIFFERENCE); + } // We figured out what is touchable for the entire screen - done. if (unaccountedSpace.isEmpty()) { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 30589b1c27a0..b0feca8fadab 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -376,10 +376,9 @@ class DisplayContent { stack.dump(prefix + " ", pw); } pw.println(); - pw.println(" Application tokens in bottom up Z order:"); + pw.println(" Application tokens in top down Z order:"); int ndx = 0; - final int numStacks = mStacks.size(); - for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { ArrayList<Task> tasks = mStacks.get(stackNdx).getTasks(); for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { AppTokenList tokens = tasks.get(taskNdx).mAppTokens; diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 69d31914fdb0..61ea1e8d061f 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -20,6 +20,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; +import static com.android.server.wm.WindowManagerService.DEBUG_KEYGUARD; import static com.android.server.wm.WindowManagerService.LayoutFields.SET_UPDATE_ROTATION; import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_MAY_CHANGE; import static com.android.server.wm.WindowManagerService.LayoutFields.SET_FORCE_HIDING_CHANGED; @@ -29,7 +30,6 @@ import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPA import android.content.Context; import android.os.Debug; import android.os.SystemClock; -import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; @@ -233,12 +233,17 @@ public class WindowAnimator { final WindowStateAnimator winAnimator = win.mWinAnimator; if ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { if (!winAnimator.mAnimating) { + if (DEBUG_KEYGUARD) Slog.d(TAG, + "updateWindowsLocked: creating delay animation"); + // Create a new animation to delay until keyguard is gone on its own. winAnimator.mAnimation = new AlphaAnimation(1.0f, 1.0f); winAnimator.mAnimation.setDuration(KEYGUARD_ANIM_TIMEOUT_MS); winAnimator.mAnimationIsEntrance = false; } } else { + if (DEBUG_KEYGUARD) Slog.d(TAG, + "updateWindowsLocked: StatusBar is no longer keyguard"); mKeyguardGoingAway = false; winAnimator.clearAnimation(); } @@ -282,7 +287,7 @@ public class WindowAnimator { if (mPolicy.isForceHiding(win.mAttrs)) { if (!wasAnimating && nowAnimating) { - if (WindowManagerService.DEBUG_ANIM || + if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_ANIM || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, "Animation started that could impact force hide: " + win); mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED; @@ -310,7 +315,7 @@ public class WindowAnimator { mForceHiding = win.isDrawnLw() ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN; } } - if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, + if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, "Force hide " + forceHidingToString() + " hasSurface=" + win.mHasSurface + " policyVis=" + win.mPolicyVisibility @@ -327,12 +332,12 @@ public class WindowAnimator { && (!winAnimator.isAnimating() || hideWhenLocked)) || ((mForceHiding == KEYGUARD_SHOWN) && hideWhenLocked)) { changed = win.hideLw(false, false); - if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG, - "Now policy hidden: " + win); + if ((DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) + && changed) Slog.v(TAG, "Now policy hidden: " + win); } else { changed = win.showLw(false, false); - if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG, - "Now policy shown: " + win); + if ((DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) + && changed) Slog.v(TAG, "Now policy shown: " + win); if (changed) { if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0 && win.isVisibleNow() /*w.isReadyForDisplay()*/) { @@ -404,6 +409,11 @@ public class WindowAnimator { if (!mKeyguardGoingAwayDisableWindowAnimations) { a = mPolicy.createForceHideEnterAnimation(wallpaperInUnForceHiding, mKeyguardGoingAwayToNotificationShade); + if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: created anim=" + a + + " for win=" + unForceHiding.get(i)); + } else { + if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: skipping anim for win=" + + unForceHiding.get(i)); } if (a != null) { final WindowStateAnimator winAnimator = unForceHiding.get(i); @@ -422,6 +432,7 @@ public class WindowAnimator { // Wallpaper is going away in un-force-hide motion, animate it as well. if (!wallpaperInUnForceHiding && wallpaper != null && !mKeyguardGoingAwayDisableWindowAnimations) { + if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: wallpaper animating away"); Animation a = mPolicy.createForceHideWallpaperExitAnimation( mKeyguardGoingAwayToNotificationShade); if (a != null) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 23543696b0bd..a48d39f41b61 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -166,6 +166,7 @@ public class WindowManagerService extends IWindowManager.Stub static final boolean DEBUG_FOCUS = false; static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false; static final boolean DEBUG_ANIM = false; + static final boolean DEBUG_KEYGUARD = false; static final boolean DEBUG_LAYOUT = false; static final boolean DEBUG_RESIZE = false; static final boolean DEBUG_LAYERS = false; @@ -2337,6 +2338,11 @@ public class WindowManagerService extends IWindowManager.Stub + attrs.token + ". Aborting."); return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } + if (type == TYPE_ACCESSIBILITY_OVERLAY) { + Slog.w(TAG, "Attempted to add Accessibility overlay window with unknown token " + + attrs.token + ". Aborting."); + return WindowManagerGlobal.ADD_BAD_APP_TOKEN; + } token = new WindowToken(this, attrs.token, -1, false); addToken = true; } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { @@ -2380,6 +2386,12 @@ public class WindowManagerService extends IWindowManager.Stub + attrs.token + ". Aborting."); return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } + } else if (type == TYPE_ACCESSIBILITY_OVERLAY) { + if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) { + Slog.w(TAG, "Attempted to add Accessibility overlay window with bad token " + + attrs.token + ". Aborting."); + return WindowManagerGlobal.ADD_BAD_APP_TOKEN; + } } else if (token.appWindowToken != null) { Slog.w(TAG, "Non-null appWindowToken for system window of type=" + type); // It is not valid to use an app token with other system types; we will @@ -2476,7 +2488,9 @@ public class WindowManagerService extends IWindowManager.Stub } } - win.mWinAnimator.mEnterAnimationPending = true; + final WindowStateAnimator winAnimator = win.mWinAnimator; + winAnimator.mEnterAnimationPending = true; + winAnimator.mEnteringAnimation = true; if (displayContent.isDefaultDisplay) { mPolicy.getContentInsetHintLw(attrs, outContentInsets); @@ -2515,9 +2529,8 @@ public class WindowManagerService extends IWindowManager.Stub } mInputMonitor.updateInputWindowsLw(false /*force*/); - if (localLOGV) Slog.v( - TAG, "New client " + client.asBinder() - + ": window=" + win); + if (true || localLOGV) Slog.v(TAG, "addWindow: New client " + client.asBinder() + + ": window=" + win + " Callers=" + Debug.getCallers(5)); if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) { reportNewConfig = true; @@ -2681,7 +2694,8 @@ public class WindowManagerService extends IWindowManager.Stub mPolicy.removeWindowLw(win); win.removeLocked(); - if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win); + if (true || DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win + + " Callers=" + Debug.getCallers(5)); mWindowMap.remove(win.mClient.asBinder()); if (win.mAppOp != AppOpsManager.OP_NONE) { mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage()); @@ -2986,8 +3000,8 @@ public class WindowManagerService extends IWindowManager.Stub return 0; } WindowStateAnimator winAnimator = win.mWinAnimator; - if (win.mRequestedWidth != requestedWidth - || win.mRequestedHeight != requestedHeight) { + if (viewVisibility != View.GONE && (win.mRequestedWidth != requestedWidth + || win.mRequestedHeight != requestedHeight)) { win.mLayoutNeeded = true; win.mRequestedWidth = requestedWidth; win.mRequestedHeight = requestedHeight; @@ -3088,6 +3102,7 @@ public class WindowManagerService extends IWindowManager.Stub if (oldVisibility == View.GONE) { winAnimator.mEnterAnimationPending = true; } + winAnimator.mEnteringAnimation = true; if (toBeDisplayed) { if (win.isDrawnLw() && okToDisplay()) { winAnimator.applyEnterAnimationLocked(); @@ -3156,6 +3171,7 @@ public class WindowManagerService extends IWindowManager.Stub } } else { winAnimator.mEnterAnimationPending = false; + winAnimator.mEnteringAnimation = false; if (winAnimator.mSurfaceControl != null) { if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win + ": mExiting=" + win.mExiting); @@ -5348,6 +5364,8 @@ public class WindowManagerService extends IWindowManager.Stub != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Requires DISABLE_KEYGUARD permission"); } + if (DEBUG_KEYGUARD) Slog.d(TAG, "keyguardGoingAway: disableWinAnim=" + + disableWindowAnimations + " kgToNotifShade=" + keyguardGoingToNotificationShade); synchronized (mWindowMap) { mAnimator.mKeyguardGoingAway = true; mAnimator.mKeyguardGoingAwayToNotificationShade = keyguardGoingToNotificationShade; @@ -5357,12 +5375,15 @@ public class WindowManagerService extends IWindowManager.Stub } public void keyguardWaitingForActivityDrawn() { + if (DEBUG_KEYGUARD) Slog.d(TAG, "keyguardWaitingForActivityDrawn"); synchronized (mWindowMap) { mKeyguardWaitingForActivityDrawn = true; } } public void notifyActivityDrawnForKeyguard() { + if (DEBUG_KEYGUARD) Slog.d(TAG, "notifyActivityDrawnForKeyguard: waiting=" + + mKeyguardWaitingForActivityDrawn); synchronized (mWindowMap) { if (mKeyguardWaitingForActivityDrawn) { mPolicy.notifyActivityDrawnForKeyguardLw(); @@ -6038,6 +6059,10 @@ public class WindowManagerService extends IWindowManager.Stub while (true) { if (retryCount++ > 0) { + // Reset max/min layers on retries so we don't accidentally take a screenshot of a + // layer based on the previous try. + maxLayer = 0; + minLayer = Integer.MAX_VALUE; try { Thread.sleep(100); } catch (InterruptedException e) { @@ -6060,7 +6085,17 @@ public class WindowManagerService extends IWindowManager.Stub continue; } } else if (ws.mIsWallpaper) { - // Fall through. + if (appWin == null) { + // We have not ran across the target window yet, so it is probably + // behind the wallpaper. This can happen when the keyguard is up and + // all windows are moved behind the wallpaper. We don't want to + // include the wallpaper layer in the screenshot as it will coverup + // the layer of the target window. + continue; + } + // Fall through. The target window is in front of the wallpaper. For this + // case we want to include the wallpaper layer in the screenshot because + // the target window might have some transparent areas. } else if (appToken != null) { if (ws.mAppToken == null || ws.mAppToken.token != appToken) { // This app window is of no interest if it is not associated with the @@ -9378,7 +9413,6 @@ public class WindowManagerService extends IWindowManager.Stub final int type = attrs.type; if (canBeSeen && (type == TYPE_SYSTEM_DIALOG - || type == TYPE_RECENTS_OVERLAY || type == TYPE_SYSTEM_ERROR || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) { mInnerFields.mSyswin = true; @@ -11628,5 +11662,23 @@ public class WindowManagerService extends IWindowManager.Stub checkDrawnWindowsLocked(); } } + + @Override + public void addWindowToken(IBinder token, int type) { + WindowManagerService.this.addWindowToken(token, type); + } + + @Override + public void removeWindowToken(IBinder token, boolean removeWindows) { + synchronized(mWindowMap) { + if (removeWindows) { + WindowToken wtoken = mTokenMap.remove(token); + if (wtoken != null) { + wtoken.removeAllWindows(); + } + } + WindowManagerService.this.removeWindowToken(token); + } + } } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index b4a7f04272d9..f9efc809162d 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -29,6 +29,7 @@ import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import android.app.AppOpsManager; @@ -227,13 +228,33 @@ final class WindowState implements WindowManagerPolicy.WindowState { final Rect mCompatFrame = new Rect(); final Rect mContainingFrame = new Rect(); + + final Rect mParentFrame = new Rect(); + + // The entire screen area of the device. final Rect mDisplayFrame = new Rect(); + + // The region of the display frame that the display type supports displaying content on. This + // is mostly a special case for TV where some displays don’t have the entire display usable. + // {@link WindowManager.LayoutParams#FLAG_LAYOUT_IN_OVERSCAN} flag can be used to allow + // window display contents to extend into the overscan region. final Rect mOverscanFrame = new Rect(); + + // The display frame minus the stable insets. This value is always constant regardless of if + // the status bar or navigation bar is visible. + final Rect mStableFrame = new Rect(); + + // The area not occupied by the status and navigation bars. So, if both status and navigation + // bars are visible, the decor frame is equal to the stable frame. + final Rect mDecorFrame = new Rect(); + + // Equal to the decor frame if the IME (e.g. keyboard) is not present. Equal to the decor frame + // minus the area occupied by the IME if the IME is present. final Rect mContentFrame = new Rect(); - final Rect mParentFrame = new Rect(); + + // Legacy stuff. Generally equal to the content frame expect when the IME for older apps + // displays hint text. final Rect mVisibleFrame = new Rect(); - final Rect mDecorFrame = new Rect(); - final Rect mStableFrame = new Rect(); boolean mContentChanged; @@ -704,9 +725,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { WindowState ws = this; WindowList windows = getWindowList(); while (true) { - if ((ws.mAttrs.privateFlags - & WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY) != 0) { - return (ws.mAttrs.flags & WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0; + if (ws.mAttrs.needsMenuKey != WindowManager.LayoutParams.NEEDS_MENU_UNSET) { + return ws.mAttrs.needsMenuKey == WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE; } // If we reached the bottom of the range of windows we are considering, // assume no menu is needed. @@ -883,7 +903,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { */ boolean isVisibleNow() { return mHasSurface && mPolicyVisibility && !mAttachedHidden - && !mRootToken.hidden && !mExiting && !mDestroying; + && (!mRootToken.hidden || mAttrs.type == TYPE_APPLICATION_STARTING) + && !mExiting && !mDestroying; } /** diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 0c727f33172e..fc3f2c275d2f 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -40,6 +40,7 @@ import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; import android.os.Debug; +import android.os.RemoteException; import android.os.UserHandle; import android.util.Slog; import android.view.Display; @@ -141,6 +142,11 @@ class WindowStateAnimator { // an enter animation. boolean mEnterAnimationPending; + /** Used to indicate that this window is undergoing an enter animation. Used for system + * windows to make the callback to View.dispatchOnWindowShownCallback(). Set when the + * window is first added or shown, cleared when the callback has been made. */ + boolean mEnteringAnimation; + boolean keyguardGoingAwayAnimation; /** This is set when there is no Surface */ @@ -428,6 +434,14 @@ class WindowStateAnimator { mWin.mChildWindows.get(i).mWinAnimator.finishExit(); } + if (mEnteringAnimation && mWin.mAppToken == null) { + try { + mEnteringAnimation = false; + mWin.mClient.dispatchWindowShown(); + } catch (RemoteException e) { + } + } + if (!mWin.mExiting) { return; } diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index 22671234c538..1a672e682814 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -17,6 +17,7 @@ package com.android.server.wm; import android.os.IBinder; +import android.util.Slog; import java.io.PrintWriter; @@ -29,7 +30,7 @@ import java.io.PrintWriter; class WindowToken { // The window manager! final WindowManagerService service; - + // The actual token. final IBinder token; @@ -77,6 +78,15 @@ class WindowToken { explicit = _explicit; } + void removeAllWindows() { + for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { + WindowState win = windows.get(winNdx); + if (WindowManagerService.DEBUG_WINDOW_MOVEMENT) Slog.w(WindowManagerService.TAG, + "removeAllWindows: removing win=" + win); + win.mService.removeWindowLocked(win.mSession, win); + } + } + void dump(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("windows="); pw.println(windows); pw.print(prefix); pw.print("windowType="); pw.print(windowType); diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp index d5abe0c25dae..5cb05431fe9e 100644 --- a/services/core/jni/com_android_server_tv_TvInputHal.cpp +++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp @@ -235,7 +235,7 @@ public: static JTvInputHal* createInstance(JNIEnv* env, jobject thiz); - int addStream(int deviceId, int streamId, const sp<Surface>& surface); + int addOrUpdateStream(int deviceId, int streamId, const sp<Surface>& surface); int removeStream(int deviceId, int streamId); const tv_stream_config_t* getStreamConfigs(int deviceId, int* numConfigs); @@ -312,7 +312,7 @@ JTvInputHal* JTvInputHal::createInstance(JNIEnv* env, jobject thiz) { return new JTvInputHal(env, thiz, device); } -int JTvInputHal::addStream(int deviceId, int streamId, const sp<Surface>& surface) { +int JTvInputHal::addOrUpdateStream(int deviceId, int streamId, const sp<Surface>& surface) { KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId); if (connections.indexOfKey(streamId) < 0) { connections.add(streamId, Connection()); @@ -555,14 +555,14 @@ static jlong nativeOpen(JNIEnv* env, jobject thiz) { return (jlong)JTvInputHal::createInstance(env, thiz); } -static int nativeAddStream(JNIEnv* env, jclass clazz, +static int nativeAddOrUpdateStream(JNIEnv* env, jclass clazz, jlong ptr, jint deviceId, jint streamId, jobject jsurface) { JTvInputHal* tvInputHal = (JTvInputHal*)ptr; if (!jsurface) { return BAD_VALUE; } sp<Surface> surface(android_view_Surface_getSurface(env, jsurface)); - return tvInputHal->addStream(deviceId, streamId, surface); + return tvInputHal->addOrUpdateStream(deviceId, streamId, surface); } static int nativeRemoveStream(JNIEnv* env, jclass clazz, @@ -612,8 +612,8 @@ static JNINativeMethod gTvInputHalMethods[] = { /* name, signature, funcPtr */ { "nativeOpen", "()J", (void*) nativeOpen }, - { "nativeAddStream", "(JIILandroid/view/Surface;)I", - (void*) nativeAddStream }, + { "nativeAddOrUpdateStream", "(JIILandroid/view/Surface;)I", + (void*) nativeAddOrUpdateStream }, { "nativeRemoveStream", "(JII)I", (void*) nativeRemoveStream }, { "nativeGetStreamConfigs", "(JII)[Landroid/media/tv/TvStreamConfig;", diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 9ee44b99876f..308fcd802b4f 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -4788,6 +4788,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Slog.e(LOG_TAG, "Failed to talk to AudioService.", re); } } + sendChangedNotification(userHandle); } } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 6009ffdcae61..d7f61305abdf 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -374,6 +374,8 @@ public final class SystemServer { mSystemServiceManager.startService(UsageStatsService.class); mActivityManagerService.setUsageStatsManager( LocalServices.getService(UsageStatsManagerInternal.class)); + // Update after UsageStatsService is available, needed before performBootDexOpt. + mPackageManagerService.getUsageStatsIfNoPackageUsageInfo(); // Tracks whether the updatable WebView is in a ready state and watches for update installs. mSystemServiceManager.startService(WebViewUpdateService.class); diff --git a/services/print/java/com/android/server/print/RemotePrintSpooler.java b/services/print/java/com/android/server/print/RemotePrintSpooler.java index 9496cae02298..7ab3840128b9 100644 --- a/services/print/java/com/android/server/print/RemotePrintSpooler.java +++ b/services/print/java/com/android/server/print/RemotePrintSpooler.java @@ -21,6 +21,7 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Binder; +import android.os.Build; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; @@ -55,7 +56,8 @@ final class RemotePrintSpooler { private static final boolean DEBUG = false; - private static final long BIND_SPOOLER_SERVICE_TIMEOUT = 10000; + private static final long BIND_SPOOLER_SERVICE_TIMEOUT = + ("eng".equals(Build.TYPE)) ? 120000 : 10000; private final Object mLock = new Object(); diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java index c3d4ed9f1ab5..c115339a9b1d 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java @@ -932,7 +932,6 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expect(mSettings.getPollInterval()).andReturn(HOUR_IN_MILLIS).anyTimes(); expect(mSettings.getTimeCacheMaxAge()).andReturn(DAY_IN_MILLIS).anyTimes(); expect(mSettings.getSampleEnabled()).andReturn(true).anyTimes(); - expect(mSettings.getReportXtOverDev()).andReturn(true).anyTimes(); final Config config = new Config(bucketDuration, deleteAge, deleteAge); expect(mSettings.getDevConfig()).andReturn(config).anyTimes(); diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java index a70ebf481de7..b631331e9546 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java @@ -21,22 +21,15 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; -import com.android.internal.content.PackageHelper; +import android.test.AndroidTestCase; +import android.util.ArraySet; +import android.util.Log; + import com.android.internal.os.AtomicFile; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.util.HashSet; - -import android.os.Debug; -import android.os.Environment; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.storage.IMountService; -import android.test.AndroidTestCase; -import android.util.Log; public class PackageManagerSettingsTests extends AndroidTestCase { @@ -182,11 +175,11 @@ public class PackageManagerSettingsTests extends AndroidTestCase { assertEquals(COMPONENT_ENABLED_STATE_ENABLED, ps.getEnabled(1)); // Enable/Disable a component - HashSet<String> components = new HashSet<String>(); + ArraySet<String> components = new ArraySet<String>(); String component1 = PACKAGE_NAME_1 + "/.Component1"; components.add(component1); ps.setDisabledComponents(components, 0); - HashSet<String> componentsDisabled = ps.getDisabledComponents(0); + ArraySet<String> componentsDisabled = ps.getDisabledComponents(0); assertEquals(1, componentsDisabled.size()); assertEquals(component1, componentsDisabled.toArray()[0]); boolean hasEnabled = diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java index cfa44363551e..11da380766f8 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java +++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java @@ -39,6 +39,7 @@ class UsageStatsDatabase { private static final String TAG = "UsageStatsDatabase"; private static final boolean DEBUG = UsageStatsService.DEBUG; + private static final String BAK_SUFFIX = ".bak"; private final Object mLock = new Object(); private final File[] mIntervalDirs; @@ -95,11 +96,71 @@ class UsageStatsDatabase { } } + public interface CheckinAction { + boolean checkin(IntervalStats stats); + } + + /** + * Calls {@link CheckinAction#checkin(IntervalStats)} on the given {@link CheckinAction} + * for all {@link IntervalStats} that haven't been checked-in. + * If any of the calls to {@link CheckinAction#checkin(IntervalStats)} returns false or throws + * an exception, the check-in will be aborted. + * + * @param checkinAction The callback to run when checking-in {@link IntervalStats}. + * @return true if the check-in succeeded. + */ + public boolean checkinDailyFiles(CheckinAction checkinAction) { + synchronized (mLock) { + final TimeSparseArray<AtomicFile> files = + mSortedStatFiles[UsageStatsManager.INTERVAL_DAILY]; + final int fileCount = files.size(); + int start = 0; + while (start < fileCount - 1) { + if (!files.valueAt(start).getBaseFile().getName().endsWith("-c")) { + break; + } + } + + if (start == fileCount - 1) { + return true; + } + + try { + IntervalStats stats = new IntervalStats(); + for (int i = start; i < fileCount - 1; i++) { + UsageStatsXml.read(files.valueAt(i), stats); + if (!checkinAction.checkin(stats)) { + return false; + } + } + } catch (IOException e) { + Slog.e(TAG, "Failed to check-in", e); + return false; + } + + // We have successfully checked-in the stats, so rename the files so that they + // are marked as checked-in. + for (int i = start; i < fileCount - 1; i++) { + final AtomicFile file = files.valueAt(i); + final File checkedInFile = new File(file.getBaseFile().getParent(), + file.getBaseFile().getName() + "-c"); + if (!file.getBaseFile().renameTo(checkedInFile)) { + // We must return success, as we've already marked some files as checked-in. + // It's better to repeat ourselves than to lose data. + Slog.e(TAG, "Failed to mark file " + file.getBaseFile().getPath() + + " as checked-in"); + return true; + } + } + } + return true; + } + private void indexFilesLocked() { final FilenameFilter backupFileFilter = new FilenameFilter() { @Override public boolean accept(File dir, String name) { - return !name.endsWith(".bak"); + return !name.endsWith(BAK_SUFFIX); } }; @@ -383,10 +444,10 @@ class UsageStatsDatabase { if (files != null) { for (File f : files) { String path = f.getPath(); - if (path.endsWith(".bak")) { - f = new File(path.substring(0, path.length() - 4)); + if (path.endsWith(BAK_SUFFIX)) { + f = new File(path.substring(0, path.length() - BAK_SUFFIX.length())); } - long beginTime = Long.parseLong(f.getName()); + long beginTime = UsageStatsXml.parseBeginTime(f); if (beginTime < expiryTime) { new AtomicFile(f).delete(); } diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 2ed974505de3..485b2a208911 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -33,11 +33,11 @@ import android.content.pm.ParceledListSlice; import android.content.pm.UserInfo; import android.content.res.Configuration; import android.os.Binder; -import android.os.Debug; import android.os.Environment; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; @@ -47,9 +47,12 @@ import android.util.Slog; import android.util.SparseArray; import com.android.internal.os.BackgroundThread; +import com.android.internal.util.IndentingPrintWriter; import com.android.server.SystemService; import java.io.File; +import java.io.FileDescriptor; +import java.io.PrintWriter; import java.util.Arrays; import java.util.List; @@ -176,7 +179,7 @@ public class UsageStatsService extends SystemService implements long currentTimeMillis) { UserUsageStatsService service = mUserState.get(userId); if (service == null) { - service = new UserUsageStatsService(userId, + service = new UserUsageStatsService(getContext(), userId, new File(mUsageStatsDir, Integer.toString(userId)), this); service.init(currentTimeMillis); mUserState.put(userId, service); @@ -319,6 +322,30 @@ public class UsageStatsService extends SystemService implements mHandler.removeMessages(MSG_FLUSH_TO_DISK); } + /** + * Called by the Binder stub. + */ + void dump(String[] args, PrintWriter pw) { + synchronized (mLock) { + IndentingPrintWriter idpw = new IndentingPrintWriter(pw, " "); + ArraySet<String> argSet = new ArraySet<>(); + argSet.addAll(Arrays.asList(args)); + + final int userCount = mUserState.size(); + for (int i = 0; i < userCount; i++) { + idpw.printPair("user", mUserState.keyAt(i)); + idpw.println(); + idpw.increaseIndent(); + if (argSet.contains("--checkin")) { + mUserState.valueAt(i).checkin(idpw); + } else { + mUserState.valueAt(i).dump(idpw); + } + idpw.decreaseIndent(); + } + } + } + class H extends Handler { public H(Looper looper) { super(looper); @@ -349,8 +376,12 @@ public class UsageStatsService extends SystemService implements private class BinderService extends IUsageStatsManager.Stub { private boolean hasPermission(String callingPackage) { + final int callingUid = Binder.getCallingUid(); + if (callingUid == Process.SYSTEM_UID) { + return true; + } final int mode = mAppOps.checkOp(AppOpsManager.OP_GET_USAGE_STATS, - Binder.getCallingUid(), callingPackage); + callingUid, callingPackage); if (mode == AppOpsManager.MODE_DEFAULT) { // The default behavior here is to check if PackageManager has given the app // permission. @@ -417,6 +448,18 @@ public class UsageStatsService extends SystemService implements Binder.restoreCallingIdentity(token); } } + + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump UsageStats from pid=" + + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + + " without permission " + android.Manifest.permission.DUMP); + return; + } + UsageStatsService.this.dump(args, pw); + } } /** diff --git a/services/usage/java/com/android/server/usage/UsageStatsXml.java b/services/usage/java/com/android/server/usage/UsageStatsXml.java index 9ce6d63341fc..26148cef5e63 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsXml.java +++ b/services/usage/java/com/android/server/usage/UsageStatsXml.java @@ -24,21 +24,26 @@ import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import java.io.*; public class UsageStatsXml { private static final String TAG = "UsageStatsXml"; private static final int CURRENT_VERSION = 1; private static final String USAGESTATS_TAG = "usagestats"; private static final String VERSION_ATTR = "version"; + private static final String CHECKED_IN_SUFFIX = "-c"; public static long parseBeginTime(AtomicFile file) { - return Long.parseLong(file.getBaseFile().getName()); + return parseBeginTime(file.getBaseFile()); + } + + public static long parseBeginTime(File file) { + final String name = file.getName(); + if (name.endsWith(CHECKED_IN_SUFFIX)) { + return Long.parseLong( + name.substring(0, name.length() - CHECKED_IN_SUFFIX.length())); + } + return Long.parseLong(name); } public static void read(AtomicFile file, IntervalStats statsOut) throws IOException { diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java index 4916ec2c8612..6596781c0964 100644 --- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java @@ -23,9 +23,13 @@ import android.app.usage.UsageStats; import android.app.usage.UsageStatsManager; import android.content.res.Configuration; import android.os.SystemClock; +import android.content.Context; +import android.text.format.DateUtils; +import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; +import com.android.internal.util.IndentingPrintWriter; import com.android.server.usage.UsageStatsDatabase.StatCombiner; import java.io.File; @@ -43,7 +47,13 @@ class UserUsageStatsService { private static final String TAG = "UsageStatsService"; private static final boolean DEBUG = UsageStatsService.DEBUG; private static final SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + private static final int sDateFormatFlags = + DateUtils.FORMAT_SHOW_DATE + | DateUtils.FORMAT_SHOW_TIME + | DateUtils.FORMAT_SHOW_YEAR + | DateUtils.FORMAT_NUMERIC_DATE; + private final Context mContext; private final UsageStatsDatabase mDatabase; private final IntervalStats[] mCurrentStats; private boolean mStatsChanged = false; @@ -55,7 +65,8 @@ class UserUsageStatsService { void onStatsUpdated(); } - UserUsageStatsService(int userId, File usageStatsDir, StatsUpdatedListener listener) { + UserUsageStatsService(Context context, int userId, File usageStatsDir, StatsUpdatedListener listener) { + mContext = context; mDailyExpiryDate = new UnixCalendar(0); mDatabase = new UsageStatsDatabase(usageStatsDir); mCurrentStats = new IntervalStats[UsageStatsManager.INTERVAL_COUNT]; @@ -433,6 +444,117 @@ class UserUsageStatsService { tempCal.getTimeInMillis() + ")"); } + // + // -- DUMP related methods -- + // + + void checkin(final IndentingPrintWriter pw) { + mDatabase.checkinDailyFiles(new UsageStatsDatabase.CheckinAction() { + @Override + public boolean checkin(IntervalStats stats) { + printIntervalStats(pw, stats, false); + return true; + } + }); + } + + void dump(IndentingPrintWriter pw) { + // This is not a check-in, only dump in-memory stats. + for (int interval = 0; interval < mCurrentStats.length; interval++) { + pw.print("In-memory "); + pw.print(intervalToString(interval)); + pw.println(" stats"); + printIntervalStats(pw, mCurrentStats[interval], true); + } + } + + private String formatDateTime(long dateTime, boolean pretty) { + if (pretty) { + return "\"" + DateUtils.formatDateTime(mContext, dateTime, sDateFormatFlags) + "\""; + } + return Long.toString(dateTime); + } + + private String formatElapsedTime(long elapsedTime, boolean pretty) { + if (pretty) { + return "\"" + DateUtils.formatElapsedTime(elapsedTime / 1000) + "\""; + } + return Long.toString(elapsedTime); + } + + void printIntervalStats(IndentingPrintWriter pw, IntervalStats stats, boolean prettyDates) { + if (prettyDates) { + pw.printPair("timeRange", "\"" + DateUtils.formatDateRange(mContext, + stats.beginTime, stats.endTime, sDateFormatFlags) + "\""); + } else { + pw.printPair("beginTime", stats.beginTime); + pw.printPair("endTime", stats.endTime); + } + pw.println(); + pw.increaseIndent(); + pw.println("packages"); + pw.increaseIndent(); + final ArrayMap<String, UsageStats> pkgStats = stats.packageStats; + final int pkgCount = pkgStats.size(); + for (int i = 0; i < pkgCount; i++) { + final UsageStats usageStats = pkgStats.valueAt(i); + pw.printPair("package", usageStats.mPackageName); + pw.printPair("totalTime", formatElapsedTime(usageStats.mTotalTimeInForeground, prettyDates)); + pw.printPair("lastTime", formatDateTime(usageStats.mLastTimeUsed, prettyDates)); + pw.println(); + } + pw.decreaseIndent(); + + pw.println("configurations"); + pw.increaseIndent(); + final ArrayMap<Configuration, ConfigurationStats> configStats = + stats.configurations; + final int configCount = configStats.size(); + for (int i = 0; i < configCount; i++) { + final ConfigurationStats config = configStats.valueAt(i); + pw.printPair("config", Configuration.resourceQualifierString(config.mConfiguration)); + pw.printPair("totalTime", formatElapsedTime(config.mTotalTimeActive, prettyDates)); + pw.printPair("lastTime", formatDateTime(config.mLastTimeActive, prettyDates)); + pw.printPair("count", config.mActivationCount); + pw.println(); + } + pw.decreaseIndent(); + + pw.println("events"); + pw.increaseIndent(); + final TimeSparseArray<UsageEvents.Event> events = stats.events; + final int eventCount = events != null ? events.size() : 0; + for (int i = 0; i < eventCount; i++) { + final UsageEvents.Event event = events.valueAt(i); + pw.printPair("time", formatDateTime(event.mTimeStamp, prettyDates)); + pw.printPair("type", eventToString(event.mEventType)); + pw.printPair("package", event.mPackage); + if (event.mClass != null) { + pw.printPair("class", event.mClass); + } + if (event.mConfiguration != null) { + pw.printPair("config", Configuration.resourceQualifierString(event.mConfiguration)); + } + pw.println(); + } + pw.decreaseIndent(); + pw.decreaseIndent(); + } + + private static String intervalToString(int interval) { + switch (interval) { + case UsageStatsManager.INTERVAL_DAILY: + return "daily"; + case UsageStatsManager.INTERVAL_WEEKLY: + return "weekly"; + case UsageStatsManager.INTERVAL_MONTHLY: + return "monthly"; + case UsageStatsManager.INTERVAL_YEARLY: + return "yearly"; + default: + return "?"; + } + } private static String eventToString(int eventType) { switch (eventType) { diff --git a/telecomm/java/android/telecom/AudioState.java b/telecomm/java/android/telecom/AudioState.java index fc2fff4ace2e..43da38f3648c 100644 --- a/telecomm/java/android/telecom/AudioState.java +++ b/telecomm/java/android/telecom/AudioState.java @@ -16,17 +16,15 @@ package android.telecom; -import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import java.util.Locale; /** - * Encapsulates all audio states during a call. - * @hide + * Encapsulates the telecom audio state, including the current audio routing, supported audio + * routing and mute. */ -@SystemApi public final class AudioState implements Parcelable { /** Direct the audio stream through the device's earpiece. */ public static final int ROUTE_EARPIECE = 0x00000001; @@ -56,10 +54,10 @@ public final class AudioState implements Parcelable { /** True if the call is muted, false otherwise. */ public final boolean isMuted; - /** The route to use for the audio stream. */ + /** The current audio route being used. */ public final int route; - /** Bit vector of all routes supported by this call. */ + /** Bit mask of all routes supported by this call. */ public final int supportedRouteMask; public AudioState(boolean isMuted, int route, int supportedRouteMask) { diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java index b7b98bf329f0..003d5cd4876c 100644 --- a/telecomm/java/android/telecom/Conference.java +++ b/telecomm/java/android/telecom/Conference.java @@ -16,8 +16,6 @@ package android.telecom; -import android.annotation.SystemApi; - import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -27,9 +25,7 @@ import java.util.concurrent.CopyOnWriteArraySet; /** * Represents a conference call which can contain any number of {@link Connection} objects. - * @hide */ -@SystemApi public abstract class Conference { /** @hide */ @@ -338,6 +334,19 @@ public abstract class Conference { } /** + * Retrieves the primary connection associated with the conference. The primary connection is + * the connection from which the conference will retrieve its current state. + * + * @return The primary connection. + */ + public Connection getPrimaryConnection() { + if (mUnmodifiableChildConnections == null || mUnmodifiableChildConnections.isEmpty()) { + return null; + } + return mUnmodifiableChildConnections.get(0); + } + + /** * Inform this Conference that the state of its audio output has been changed externally. * * @param state The new audio state. diff --git a/telecomm/java/android/telecom/ConferenceParticipant.aidl b/telecomm/java/android/telecom/ConferenceParticipant.aidl new file mode 100644 index 000000000000..020c92320fa3 --- /dev/null +++ b/telecomm/java/android/telecom/ConferenceParticipant.aidl @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2014 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.telecom; + +/** + * {@hide} + */ +parcelable ConferenceParticipant; diff --git a/telecomm/java/android/telecom/ConferenceParticipant.java b/telecomm/java/android/telecom/ConferenceParticipant.java new file mode 100644 index 000000000000..db0f151e2016 --- /dev/null +++ b/telecomm/java/android/telecom/ConferenceParticipant.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2014 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.telecom; + +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Parcelable representation of a participant's state in a conference call. + * @hide + */ +public class ConferenceParticipant implements Parcelable { + + /** + * The conference participant's handle (e.g., phone number). + */ + private final Uri mHandle; + + /** + * The display name for the participant. + */ + private final String mDisplayName; + + /** + * The endpoint Uri which uniquely identifies this conference participant. E.g. for an IMS + * conference call, this is the endpoint URI for the participant on the IMS conference server. + */ + private final Uri mEndpoint; + + /** + * The state of the participant in the conference. + * + * @see android.telecom.Connection + */ + private final int mState; + + /** + * Creates an instance of {@code ConferenceParticipant}. + * + * @param handle The conference participant's handle (e.g., phone number). + * @param displayName The display name for the participant. + * @param endpoint The enpoint Uri which uniquely identifies this conference participant. + * @param state The state of the participant in the conference. + */ + public ConferenceParticipant(Uri handle, String displayName, Uri endpoint, int state) { + mHandle = handle; + mDisplayName = displayName; + mEndpoint = endpoint; + mState = state; + } + + /** + * Responsible for creating {@code ConferenceParticipant} objects for deserialized Parcels. + */ + public static final Parcelable.Creator<ConferenceParticipant> CREATOR = + new Parcelable.Creator<ConferenceParticipant>() { + + @Override + public ConferenceParticipant createFromParcel(Parcel source) { + ClassLoader classLoader = ParcelableCall.class.getClassLoader(); + Uri handle = source.readParcelable(classLoader); + String displayName = source.readString(); + Uri endpoint = source.readParcelable(classLoader); + int state = source.readInt(); + return new ConferenceParticipant(handle, displayName, endpoint, state); + } + + @Override + public ConferenceParticipant[] newArray(int size) { + return new ConferenceParticipant[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + /** + * Writes the {@code ConferenceParticipant} to a parcel. + * + * @param dest The Parcel in which the object should be written. + * @param flags Additional flags about how the object should be written. + */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(mHandle, 0); + dest.writeString(mDisplayName); + dest.writeParcelable(mEndpoint, 0); + dest.writeInt(mState); + } + + /** + * Builds a string representation of this instance. + * + * @return String representing the conference participant. + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("[ConferenceParticipant Handle: "); + sb.append(mHandle); + sb.append(" DisplayName: "); + sb.append(mDisplayName); + sb.append(" Endpoint: "); + sb.append(mEndpoint); + sb.append(" State: "); + sb.append(mState); + sb.append("]"); + return sb.toString(); + } + + /** + * The conference participant's handle (e.g., phone number). + */ + public Uri getHandle() { + return mHandle; + } + + /** + * The display name for the participant. + */ + public String getDisplayName() { + return mDisplayName; + } + + /** + * The enpoint Uri which uniquely identifies this conference participant. E.g. for an IMS + * conference call, this is the endpoint URI for the participant on the IMS conference server. + */ + public Uri getEndpoint() { + return mEndpoint; + } + + /** + * The state of the participant in the conference. + * + * @see android.telecom.Connection + */ + public int getState() { + return mState; + } +} diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index 4c1f75f15fd1..9bdbba8ea085 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -19,7 +19,6 @@ package android.telecom; import com.android.internal.telecom.IVideoCallback; import com.android.internal.telecom.IVideoProvider; -import android.annotation.SystemApi; import android.net.Uri; import android.os.Handler; import android.os.IBinder; @@ -44,9 +43,7 @@ import java.util.concurrent.ConcurrentHashMap; * Implementations are then responsible for updating the state of the {@code Connection}, and * must call {@link #destroy()} to signal to the framework that the {@code Connection} is no * longer used and associated resources may be recovered. - * @hide */ -@SystemApi public abstract class Connection { public static final int STATE_INITIALIZING = 0; @@ -85,6 +82,9 @@ public abstract class Connection { public void onConferenceableConnectionsChanged( Connection c, List<Connection> conferenceableConnections) {} public void onConferenceChanged(Connection c, Conference conference) {} + /** @hide */ + public void onConferenceParticipantChanged(Connection c, ConferenceParticipant participant) + {} } /** @hide */ @@ -876,7 +876,7 @@ public abstract class Connection { return mUnmodifiableConferenceableConnections; } - /** + /* * @hide */ public final void setConnectionService(ConnectionService connectionService) { @@ -921,6 +921,7 @@ public abstract class Connection { mConference = conference; if (mConnectionService != null && mConnectionService.containsConference(conference)) { fireConferenceChanged(); + onConferenceChanged(); } return true; } @@ -936,6 +937,7 @@ public abstract class Connection { Log.d(this, "Conference reset"); mConference = null; fireConferenceChanged(); + onConferenceChanged(); } } @@ -1020,14 +1022,9 @@ public abstract class Connection { public void onPostDialContinue(boolean proceed) {} /** - * Merge this connection and the specified connection into a conference call. Once the - * connections are merged, the calls should be added to the an existing or new - * {@code Conference} instance. For new {@code Conference} instances, use - * {@code ConnectionService#addConference}. - * - * @param otherConnection The connection with which this connection should be conferenced. + * Notifies this Connection that the conference which is set on it has changed. */ - public void onConferenceWith(Connection otherConnection) {} + public void onConferenceChanged() {} static String toLogSafePhoneNumber(String number) { // For unknown number, log empty string. @@ -1123,4 +1120,16 @@ public abstract class Connection { } mConferenceableConnections.clear(); } + + /** + * Notifies listeners of a change to a conference participant. + * + * @param conferenceParticipant The participant. + * @hide + */ + protected final void updateConferenceParticipant(ConferenceParticipant conferenceParticipant) { + for (Listener l : mListeners) { + l.onConferenceParticipantChanged(this, conferenceParticipant); + } + } } diff --git a/telecomm/java/android/telecom/ConnectionRequest.java b/telecomm/java/android/telecom/ConnectionRequest.java index f691c179af53..71b481b89c77 100644 --- a/telecomm/java/android/telecom/ConnectionRequest.java +++ b/telecomm/java/android/telecom/ConnectionRequest.java @@ -16,7 +16,6 @@ package android.telecom; -import android.annotation.SystemApi; import android.net.Uri; import android.os.Bundle; import android.os.Parcel; @@ -25,9 +24,7 @@ import android.os.Parcelable; /** * Simple data container encapsulating a request to some entity to * create a new {@link Connection}. - * @hide */ -@SystemApi public final class ConnectionRequest implements Parcelable { // TODO: Token to limit recursive invocations diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 6eee99d0cebf..6e41c33b7b6f 100644 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -16,7 +16,6 @@ package android.telecom; -import android.annotation.SystemApi; import android.annotation.SdkConstant; import android.app.Service; import android.content.ComponentName; @@ -43,9 +42,7 @@ import java.util.concurrent.ConcurrentHashMap; /** * A {@link android.app.Service} that provides telephone connections to processes running on an * Android device. - * @hide */ -@SystemApi public abstract class ConnectionService extends Service { /** * The {@link Intent} that must be declared as handled by the service. @@ -825,6 +822,40 @@ public abstract class ConnectionService extends Service { } /** + * Adds a connection created by the {@link ConnectionService} and informs telecom of the new + * connection. + * + * @param phoneAccountHandle The phone account handle for the connection. + * @param connection The connection to add. + */ + public final void addExistingConnection(PhoneAccountHandle phoneAccountHandle, + Connection connection) { + + String id = addExistingConnectionInternal(connection); + if (id != null) { + List<String> emptyList = new ArrayList<>(0); + + ParcelableConnection parcelableConnection = new ParcelableConnection( + phoneAccountHandle, + connection.getState(), + connection.getCallCapabilities(), + connection.getAddress(), + connection.getAddressPresentation(), + connection.getCallerDisplayName(), + connection.getCallerDisplayNamePresentation(), + connection.getVideoProvider() == null ? + null : connection.getVideoProvider().getInterface(), + connection.getVideoState(), + connection.isRingbackRequested(), + connection.getAudioModeIsVoip(), + connection.getStatusHints(), + connection.getDisconnectCause(), + emptyList); + mAdapter.addExistingConnection(id, parcelableConnection); + } + } + + /** * Returns all the active {@code Connection}s for which this {@code ConnectionService} * has taken responsibility. * @@ -909,6 +940,12 @@ public abstract class ConnectionService extends Service { public void onRemoteConferenceAdded(RemoteConference conference) {} /** + * Called when an existing connection is added remotely. + * @param connection The existing connection which was added. + */ + public void onRemoteExistingConnectionAdded(RemoteConnection connection) {} + + /** * @hide */ public boolean containsConference(Conference conference) { @@ -920,6 +957,11 @@ public abstract class ConnectionService extends Service { onRemoteConferenceAdded(remoteConference); } + /** {@hide} */ + void addRemoteExistingConnection(RemoteConnection remoteConnection) { + onRemoteExistingConnectionAdded(remoteConnection); + } + private void onAccountsInitialized() { mAreAccountsInitialized = true; for (Runnable r : mPreInitializationConnectionRequests) { @@ -928,6 +970,18 @@ public abstract class ConnectionService extends Service { mPreInitializationConnectionRequests.clear(); } + /** + * Adds an existing connection to the list of connections, identified by a new UUID. + * + * @param connection The connection. + * @return The UUID of the connection (e.g. the call-id). + */ + private String addExistingConnectionInternal(Connection connection) { + String id = UUID.randomUUID().toString(); + addConnection(id, connection); + return id; + } + private void addConnection(String callId, Connection connection) { mConnectionById.put(callId, connection); mIdByConnection.put(connection, callId); diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java index c67617241f50..e67af8cf906d 100644 --- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java +++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java @@ -344,4 +344,20 @@ final class ConnectionServiceAdapter implements DeathRecipient { } } } + + /** + * Informs telecom of an existing connection which was added by the {@link ConnectionService}. + * + * @param callId The unique ID of the call being added. + * @param connection The connection. + */ + void addExistingConnection(String callId, ParcelableConnection connection) { + Log.v(this, "addExistingConnection: %s", callId); + for (IConnectionServiceAdapter adapter : mAdapters) { + try { + adapter.addExistingConnection(callId, connection); + } catch (RemoteException ignored) { + } + } + } } diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java index 217dbc3ac6f4..519a400f6447 100644 --- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java +++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java @@ -57,6 +57,7 @@ final class ConnectionServiceAdapterServant { private static final int MSG_SET_ADDRESS = 18; private static final int MSG_SET_CALLER_DISPLAY_NAME = 19; private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 20; + private static final int MSG_ADD_EXISTING_CONNECTION = 21; private final IConnectionServiceAdapter mDelegate; @@ -199,6 +200,16 @@ final class ConnectionServiceAdapterServant { } break; } + case MSG_ADD_EXISTING_CONNECTION: { + SomeArgs args = (SomeArgs) msg.obj; + try { + mDelegate.addExistingConnection( + (String) args.arg1, (ParcelableConnection) args.arg2); + } finally { + args.recycle(); + } + break; + } } } }; @@ -345,6 +356,15 @@ final class ConnectionServiceAdapterServant { args.arg2 = conferenceableConnectionIds; mHandler.obtainMessage(MSG_SET_CONFERENCEABLE_CONNECTIONS, args).sendToTarget(); } + + @Override + public final void addExistingConnection( + String connectionId, ParcelableConnection connection) { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = connectionId; + args.arg2 = connection; + mHandler.obtainMessage(MSG_ADD_EXISTING_CONNECTION, args).sendToTarget(); + } }; public ConnectionServiceAdapterServant(IConnectionServiceAdapter delegate) { diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java index 52c12844a5d5..206046d6db0b 100644 --- a/telecomm/java/android/telecom/DisconnectCause.java +++ b/telecomm/java/android/telecom/DisconnectCause.java @@ -16,7 +16,6 @@ package android.telecom; -import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import android.media.ToneGenerator; @@ -26,12 +25,11 @@ import java.util.Objects; /** * Describes the cause of a disconnected call. This always includes a code describing the generic - * cause of the disconnect. Optionally, it may include a localized label and/or localized description - * to display to the user which is provided by the {@link ConnectionService}. It also may contain a - * reason for the the disconnect, which is intended for logging and not for display to the user. - * @hide + * cause of the disconnect. Optionally, it may include a label and/or description to display to the + * user. It is the responsibility of the {@link ConnectionService} to provide localized versions of + * the label and description. It also may contain a reason for the disconnect, which is intended for + * logging and not for display to the user. */ -@SystemApi public final class DisconnectCause implements Parcelable { /** Disconnected because of an unknown or unspecified reason. */ @@ -88,6 +86,7 @@ public final class DisconnectCause implements Parcelable { /** * Creates a new DisconnectCause. + * * @param label The localized label to show to the user to explain the disconnect. * @param code The code for the disconnect cause. * @param description The localized description to show to the user to explain the disconnect. diff --git a/telecomm/java/android/telecom/GatewayInfo.java b/telecomm/java/android/telecom/GatewayInfo.java index 3efab0f1e7ca..7105602a0bba 100644 --- a/telecomm/java/android/telecom/GatewayInfo.java +++ b/telecomm/java/android/telecom/GatewayInfo.java @@ -23,16 +23,18 @@ import android.os.Parcelable; import android.text.TextUtils; /** - * When calls are made, they may contain gateway information for services which route phone calls - * through their own service/numbers. The data consists of a number to call and the package name of - * the service. This data is used in two ways: + * Encapsulated gateway address information for outgoing call. When calls are made, the system + * provides a facility to specify two addresses for the call: one to display as the address being + * dialed and a separate (gateway) address to actually dial. Telecom provides this information to + * {@link ConnectionService}s when placing the call as an instance of {@code GatewayInfo}. + * <p> + * The data consists of an address to call, an address to display and the package name of the + * service. This data is used in two ways: * <ol> - * <li> Call the appropriate routing number - * <li> Display information about how the call is being routed to the user + * <li> Call the appropriate gateway address. + * <li> Display information about how the call is being routed to the user. * </ol> - * @hide */ -@SystemApi public class GatewayInfo implements Parcelable { private final String mGatewayProviderPackageName; @@ -48,31 +50,39 @@ public class GatewayInfo implements Parcelable { } /** - * Package name of the gateway provider service. used to place the call with. + * Package name of the gateway provider service that provided the gateway information. + * This can be used to identify the gateway address source and to load an appropriate icon when + * displaying gateway information in the in-call UI. */ public String getGatewayProviderPackageName() { return mGatewayProviderPackageName; } /** - * Gateway provider address to use when actually placing the call. + * Returns the gateway address to dial when placing the call. */ public Uri getGatewayAddress() { return mGatewayAddress; } /** - * The actual call address that the user is trying to connect to via the gateway. + * Returns the address that the user is trying to connect to via the gateway. */ public Uri getOriginalAddress() { return mOriginalAddress; } + /** + * Indicates whether this {@code GatewayInfo} instance contains any data. A returned value of + * false indicates that no gateway number is being used for the call. + */ public boolean isEmpty() { return TextUtils.isEmpty(mGatewayProviderPackageName) || mGatewayAddress == null; } - /** Implement the Parcelable interface */ + /** + * The Parcelable interface. + * */ public static final Parcelable.Creator<GatewayInfo> CREATOR = new Parcelable.Creator<GatewayInfo> () { diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java index 67b63288b461..3fc1d3d08e23 100644 --- a/telecomm/java/android/telecom/PhoneAccount.java +++ b/telecomm/java/android/telecom/PhoneAccount.java @@ -16,10 +16,14 @@ package android.telecom; -import android.annotation.SystemApi; +import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources.NotFoundException; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Parcel; @@ -33,11 +37,15 @@ import java.util.List; import java.util.MissingResourceException; /** - * Describes a distinct account, line of service or call placement method that the system - * can use to place phone calls. - * @hide + * Represents a distinct method to place or receive a phone call. Apps which can place calls and + * want those calls to be integrated into the dialer and in-call UI should build an instance of + * this class and register it with the system using {@link TelecomManager#registerPhoneAccount}. + * <p> + * {@link TelecomManager} uses registered {@link PhoneAccount}s to present the user with + * alternative options when placing a phone call. When building a {@link PhoneAccount}, the app + * should supply a valid {@link PhoneAccountHandle} that references the {@link ConnectionService} + * implementation Telecom will use to interact with the app. */ -@SystemApi public class PhoneAccount implements Parcelable { /** @@ -59,7 +67,7 @@ public class PhoneAccount implements Parcelable { * traditional SIM-based telephony calls. This account will be treated as a distinct method * for placing calls alongside the traditional SIM-based telephony stack. This flag is * distinct from {@link #CAPABILITY_CONNECTION_MANAGER} in that it is not allowed to manage - * calls from or use the built-in telephony stack to place its calls. + * or place calls from the built-in telephony stack. * <p> * See {@link #getCapabilities} * <p> @@ -118,22 +126,32 @@ public class PhoneAccount implements Parcelable { private final Uri mSubscriptionAddress; private final int mCapabilities; private final int mIconResId; + private final String mIconPackageName; + private final Bitmap mIconBitmap; private final int mColor; private final CharSequence mLabel; private final CharSequence mShortDescription; private final List<String> mSupportedUriSchemes; + /** + * Helper class for creating a {@link PhoneAccount}. + */ public static class Builder { private PhoneAccountHandle mAccountHandle; private Uri mAddress; private Uri mSubscriptionAddress; private int mCapabilities; private int mIconResId; + private String mIconPackageName; + private Bitmap mIconBitmap; private int mColor = NO_COLOR; private CharSequence mLabel; private CharSequence mShortDescription; private List<String> mSupportedUriSchemes = new ArrayList<String>(); + /** + * Creates a builder with the specified {@link PhoneAccountHandle} and label. + */ public Builder(PhoneAccountHandle accountHandle, CharSequence label) { this.mAccountHandle = accountHandle; this.mLabel = label; @@ -151,37 +169,97 @@ public class PhoneAccount implements Parcelable { mSubscriptionAddress = phoneAccount.getSubscriptionAddress(); mCapabilities = phoneAccount.getCapabilities(); mIconResId = phoneAccount.getIconResId(); + mIconPackageName = phoneAccount.getIconPackageName(); + mIconBitmap = phoneAccount.getIconBitmap(); mColor = phoneAccount.getColor(); mLabel = phoneAccount.getLabel(); mShortDescription = phoneAccount.getShortDescription(); mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes()); } + /** + * Sets the address. See {@link PhoneAccount#getAddress}. + * + * @param value The address of the phone account. + * @return The builder. + */ public Builder setAddress(Uri value) { this.mAddress = value; return this; } + /** + * Sets the subscription address. See {@link PhoneAccount#getSubscriptionAddress}. + * + * @param value The subscription address. + * @return The builder. + */ public Builder setSubscriptionAddress(Uri value) { this.mSubscriptionAddress = value; return this; } + /** + * Sets the capabilities. See {@link PhoneAccount#getCapabilities}. + * + * @param value The capabilities to set. + * @return The builder. + */ public Builder setCapabilities(int value) { this.mCapabilities = value; return this; } + /** + * Sets the icon resource ID. See {@link PhoneAccount#getIconResId}. + * + * @param value The resource ID of the icon. + * @return The builder. + */ public Builder setIconResId(int value) { this.mIconResId = value; return this; } + /** + * Sets the icon package name. See {@link PhoneAccount#getIconPackageName}. + * + * @param value The name of the package from which to load the icon. + * @return The builder. + */ + public Builder setIconPackageName(String value) { + this.mIconPackageName = value; + return this; + } + + /** + * Sets the icon bitmap. See {@link PhoneAccount#getIconBitmap}. + * + * @param value The icon bitmap. + * @return The builder. + */ + public Builder setIconBitmap(Bitmap value) { + this.mIconBitmap = value; + return this; + } + + /** + * Sets the color. See {@link PhoneAccount#getColor}. + * + * @param value The resource ID of the icon. + * @return The builder. + */ public Builder setColor(int value) { this.mColor = value; return this; } + /** + * Sets the short description. See {@link PhoneAccount#getShortDescription}. + * + * @param value The short description. + * @return The builder. + */ public Builder setShortDescription(CharSequence value) { this.mShortDescription = value; return this; @@ -191,7 +269,7 @@ public class PhoneAccount implements Parcelable { * Specifies an additional URI scheme supported by the {@link PhoneAccount}. * * @param uriScheme The URI scheme. - * @return The Builder. + * @return The builder. * @hide */ public Builder addSupportedUriScheme(String uriScheme) { @@ -205,7 +283,7 @@ public class PhoneAccount implements Parcelable { * Specifies the URI schemes supported by the {@link PhoneAccount}. * * @param uriSchemes The URI schemes. - * @return The Builder. + * @return The builder. */ public Builder setSupportedUriSchemes(List<String> uriSchemes) { mSupportedUriSchemes.clear(); @@ -235,6 +313,8 @@ public class PhoneAccount implements Parcelable { mSubscriptionAddress, mCapabilities, mIconResId, + mIconPackageName, + mIconBitmap, mColor, mLabel, mShortDescription, @@ -248,6 +328,8 @@ public class PhoneAccount implements Parcelable { Uri subscriptionAddress, int capabilities, int iconResId, + String iconPackageName, + Bitmap iconBitmap, int color, CharSequence label, CharSequence shortDescription, @@ -257,6 +339,8 @@ public class PhoneAccount implements Parcelable { mSubscriptionAddress = subscriptionAddress; mCapabilities = capabilities; mIconResId = iconResId; + mIconPackageName = iconPackageName; + mIconBitmap = iconBitmap; mColor = color; mLabel = label; mShortDescription = shortDescription; @@ -302,6 +386,9 @@ public class PhoneAccount implements Parcelable { * The raw callback number used for this {@code PhoneAccount}, as distinct from * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered * as {@code null}. It is used by the system for SIM-based {@code PhoneAccount} registration + * where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)} + * has been used to alter the callback number. + * <p> * * @return The subscription number, suitable for display to the user. */ @@ -379,6 +466,12 @@ public class PhoneAccount implements Parcelable { /** * The icon resource ID for the icon of this {@code PhoneAccount}. + * <p> + * Creators of a {@code PhoneAccount} who possess the icon in static resources should prefer + * this method of indicating the icon rather than using {@link #getIconBitmap()}, since it + * leads to less resource usage. + * <p> + * Clients wishing to display a {@code PhoneAccount} should use {@link #getIcon(Context)}. * * @return A resource ID. */ @@ -387,6 +480,20 @@ public class PhoneAccount implements Parcelable { } /** + * The package name from which to load the icon of this {@code PhoneAccount}. + * <p> + * If this property is {@code null}, the resource {@link #getIconResId()} will be loaded from + * the package in the {@link ComponentName} of the {@link #getAccountHandle()}. + * <p> + * Clients wishing to display a {@code PhoneAccount} should use {@link #getIcon(Context)}. + * + * @return A package name. + */ + public String getIconPackageName() { + return mIconPackageName; + } + + /** * A highlight color to use in displaying information about this {@code PhoneAccount}. * * @return A hexadecimal color value. @@ -396,30 +503,51 @@ public class PhoneAccount implements Parcelable { } /** - * An icon to represent this {@code PhoneAccount} in a user interface. + * A literal icon bitmap to represent this {@code PhoneAccount} in a user interface. + * <p> + * If this property is specified, it is to be considered the preferred icon. Otherwise, the + * resource specified by {@link #getIconResId()} should be used. + * <p> + * Clients wishing to display a {@code PhoneAccount} should use {@link #getIcon(Context)}. * - * @return An icon for this {@code PhoneAccount}. + * @return A bitmap. */ - public Drawable getIcon(Context context) { - return getIcon(context, mIconResId); + public Bitmap getIconBitmap() { + return mIconBitmap; } - private Drawable getIcon(Context context, int resId) { - Context packageContext; - try { - packageContext = context.createPackageContext( - mAccountHandle.getComponentName().getPackageName(), 0); - } catch (PackageManager.NameNotFoundException e) { - Log.w(this, "Cannot find package %s", mAccountHandle.getComponentName().getPackageName()); - return null; + /** + * Builds and returns an icon {@code Drawable} to represent this {@code PhoneAccount} in a user + * interface. Uses the properties {@link #getIconResId()}, {@link #getIconPackageName()}, and + * {@link #getIconBitmap()} as necessary. + * + * @param context A {@code Context} to use for loading {@code Drawable}s. + * + * @return An icon for this {@code PhoneAccount}. + */ + public Drawable getIcon(Context context) { + if (mIconBitmap != null) { + return new BitmapDrawable(context.getResources(), mIconBitmap); } - try { - return packageContext.getDrawable(resId); - } catch (NotFoundException|MissingResourceException e) { - Log.e(this, e, "Cannot find icon %d in package %s", - resId, mAccountHandle.getComponentName().getPackageName()); - return null; + + if (mIconResId != 0) { + String packageName = mIconPackageName == null + ? mAccountHandle.getComponentName().getPackageName() + : mIconPackageName; + + try { + Context packageContext = context.createPackageContext(packageName, 0); + try { + return packageContext.getDrawable(mIconResId); + } catch (NotFoundException | MissingResourceException e) { + Log.e(this, e, "Cannot find icon %d in package %s", mIconResId, packageName); + } + } catch (PackageManager.NameNotFoundException e) { + Log.w(this, "Cannot find package %s", packageName); + } } + + return new ColorDrawable(Color.TRANSPARENT); } // @@ -438,6 +566,8 @@ public class PhoneAccount implements Parcelable { out.writeParcelable(mSubscriptionAddress, 0); out.writeInt(mCapabilities); out.writeInt(mIconResId); + out.writeString(mIconPackageName); + out.writeParcelable(mIconBitmap, 0); out.writeInt(mColor); out.writeCharSequence(mLabel); out.writeCharSequence(mShortDescription); @@ -465,6 +595,8 @@ public class PhoneAccount implements Parcelable { mSubscriptionAddress = in.readParcelable(getClass().getClassLoader()); mCapabilities = in.readInt(); mIconResId = in.readInt(); + mIconPackageName = in.readString(); + mIconBitmap = in.readParcelable(getClass().getClassLoader()); mColor = in.readInt(); mLabel = in.readCharSequence(); mShortDescription = in.readCharSequence(); @@ -473,4 +605,19 @@ public class PhoneAccount implements Parcelable { in.readList(supportedUriSchemes, classLoader); mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes); } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder().append("[PhoneAccount: ") + .append(mAccountHandle) + .append(" Capabilities: ") + .append(mCapabilities) + .append(" Schemes: "); + for (String scheme : mSupportedUriSchemes) { + sb.append(scheme) + .append(" "); + } + sb.append("]"); + return sb.toString(); + } } diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java index 652befe5d0b1..bc4cc8ce4e83 100644 --- a/telecomm/java/android/telecom/PhoneAccountHandle.java +++ b/telecomm/java/android/telecom/PhoneAccountHandle.java @@ -16,7 +16,6 @@ package android.telecom; -import android.annotation.SystemApi; import android.content.ComponentName; import android.os.Parcel; import android.os.Parcelable; @@ -24,10 +23,17 @@ import android.os.Parcelable; import java.util.Objects; /** - * The unique identifier for a {@link PhoneAccount}. - * @hide + * The unique identifier for a {@link PhoneAccount}. A {@code PhoneAccountHandle} is made of two + * parts: + * <ul> + * <li>The component name of the associated {@link ConnectionService}.</li> + * <li>A string identifier that is unique across {@code PhoneAccountHandle}s with the same + * component name.</li> + * </ul> + * + * See {@link PhoneAccount}, + * {@link TelecomManager#registerPhoneAccount TelecomManager.registerPhoneAccount}. */ -@SystemApi public class PhoneAccountHandle implements Parcelable { private ComponentName mComponentName; private String mId; @@ -74,9 +80,11 @@ public class PhoneAccountHandle implements Parcelable { @Override public String toString() { + // Note: Log.pii called for mId as it can contain personally identifying phone account + // information such as SIP account IDs. return new StringBuilder().append(mComponentName) .append(", ") - .append(mId) + .append(Log.pii(mId)) .toString(); } diff --git a/telecomm/java/android/telecom/PhoneCapabilities.java b/telecomm/java/android/telecom/PhoneCapabilities.java index de2abcbb9558..3d3c6bd17324 100644 --- a/telecomm/java/android/telecom/PhoneCapabilities.java +++ b/telecomm/java/android/telecom/PhoneCapabilities.java @@ -16,14 +16,10 @@ package android.telecom; -import android.annotation.SystemApi; - /** - * Defines capabilities a phone call can support, such as conference calling and video telephony. - * Also defines properties of a phone call, such as whether it is using VoLTE technology. - * @hide + * Defines capabilities for {@link Connection}s and {@link Conference}s such as hold, swap, and + * merge. */ -@SystemApi public final class PhoneCapabilities { /** Call can currently be put on hold or unheld. */ public static final int HOLD = 0x00000001; @@ -32,15 +28,22 @@ public final class PhoneCapabilities { public static final int SUPPORT_HOLD = 0x00000002; /** - * Calls within a conference can be merged. Some connection services create a conference call - * only after two calls have been merged. However, a conference call can also be added the - * moment there are more than one call. CDMA calls are implemented in this way because the call - * actions are more limited when more than one call exists. This flag allows merge to be exposed - * as a capability on the conference call instead of individual calls. + * Calls within a conference can be merged. A {@link ConnectionService} has the option to + * add a {@link Conference} call before the child {@link Connection}s are merged. This is how + * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this + * capability allows a merge button to be shown while the conference call is in the foreground + * of the in-call UI. + * <p> + * This is only intended for use by a {@link Conference}. */ public static final int MERGE_CONFERENCE = 0x00000004; - /** Calls withing a conference can be swapped between foreground and background. */ + /** + * Calls within a conference can be swapped between foreground and background. + * See {@link #MERGE_CONFERENCE} for additional information. + * <p> + * This is only intended for use by a {@link Conference}. + */ public static final int SWAP_CONFERENCE = 0x00000008; /** Call currently supports adding another call to this one. */ @@ -53,8 +56,8 @@ public final class PhoneCapabilities { public static final int MUTE = 0x00000040; /** - * Call supports conference call management. This capability only applies to conference calls - * which can have other calls as children. + * Call supports conference call management. This capability only applies to {@link Conference} + * calls which can have {@link Connection}s as children. */ public static final int MANAGE_CONFERENCE = 0x00000080; @@ -96,43 +99,65 @@ public final class PhoneCapabilities { | ADD_CALL | RESPOND_VIA_TEXT | MUTE | MANAGE_CONFERENCE | SEPARATE_FROM_CONFERENCE | DISCONNECT_FROM_CONFERENCE; + /** + * Whether this set of capabilities supports the specified capability. + * @param capabilities The set of capabilities. + * @param capability The capability to check capabilities for. + * @return Whether the specified capability is supported. + * @hide + */ + public static boolean can(int capabilities, int capability) { + return (capabilities & capability) != 0; + } + + /** + * Removes the specified capability from the set of capabilities and returns the new set. + * @param capabilities The set of capabilities. + * @param capability The capability to remove from the set. + * @return The set of capabilities, with the capability removed. + * @hide + */ + public static int remove(int capabilities, int capability) { + return capabilities & ~capability; + } + public static String toString(int capabilities) { StringBuilder builder = new StringBuilder(); builder.append("[Capabilities:"); - if ((capabilities & HOLD) != 0) { + if (can(capabilities, HOLD)) { builder.append(" HOLD"); } - if ((capabilities & SUPPORT_HOLD) != 0) { + if (can(capabilities, SUPPORT_HOLD)) { builder.append(" SUPPORT_HOLD"); } - if ((capabilities & MERGE_CONFERENCE) != 0) { + if (can(capabilities, MERGE_CONFERENCE)) { builder.append(" MERGE_CONFERENCE"); } - if ((capabilities & SWAP_CONFERENCE) != 0) { + if (can(capabilities, SWAP_CONFERENCE)) { builder.append(" SWAP_CONFERENCE"); } - if ((capabilities & ADD_CALL) != 0) { + if (can(capabilities, ADD_CALL)) { builder.append(" ADD_CALL"); } - if ((capabilities & RESPOND_VIA_TEXT) != 0) { + if (can(capabilities, RESPOND_VIA_TEXT)) { builder.append(" RESPOND_VIA_TEXT"); } - if ((capabilities & MUTE) != 0) { + if (can(capabilities, MUTE)) { builder.append(" MUTE"); } - if ((capabilities & MANAGE_CONFERENCE) != 0) { + if (can(capabilities, MANAGE_CONFERENCE)) { builder.append(" MANAGE_CONFERENCE"); } - if ((capabilities & SUPPORTS_VT_LOCAL) != 0) { + if (can(capabilities, SUPPORTS_VT_LOCAL)) { builder.append(" SUPPORTS_VT_LOCAL"); } - if ((capabilities & SUPPORTS_VT_REMOTE) != 0) { + if (can(capabilities, SUPPORTS_VT_REMOTE)) { builder.append(" SUPPORTS_VT_REMOTE"); } - if ((capabilities & VoLTE) != 0) { + if (can(capabilities, VoLTE)) { builder.append(" VoLTE"); } - if ((capabilities & VoWIFI) != 0) { + if (can(capabilities, VoWIFI)) { builder.append(" VoWIFI"); } builder.append("]"); diff --git a/telecomm/java/android/telecom/RemoteConference.java b/telecomm/java/android/telecom/RemoteConference.java index b548274de2fc..eba75808164f 100644 --- a/telecomm/java/android/telecom/RemoteConference.java +++ b/telecomm/java/android/telecom/RemoteConference.java @@ -18,7 +18,6 @@ package android.telecom; import com.android.internal.telecom.IConnectionService; -import android.annotation.SystemApi; import android.os.RemoteException; import java.util.ArrayList; @@ -30,9 +29,7 @@ import java.util.concurrent.CopyOnWriteArraySet; /** * Represents a conference call which can contain any number of {@link Connection} objects. - * @hide */ -@SystemApi public final class RemoteConference { public abstract static class Callback { diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java index 4a896928c4e1..816e2bf6b418 100644 --- a/telecomm/java/android/telecom/RemoteConnection.java +++ b/telecomm/java/android/telecom/RemoteConnection.java @@ -20,7 +20,6 @@ import com.android.internal.telecom.IConnectionService; import com.android.internal.telecom.IVideoCallback; import com.android.internal.telecom.IVideoProvider; -import android.annotation.SystemApi; import android.net.Uri; import android.os.IBinder; import android.os.RemoteException; @@ -38,9 +37,7 @@ import java.util.concurrent.ConcurrentHashMap; * * @see ConnectionService#createRemoteOutgoingConnection(PhoneAccountHandle, ConnectionRequest) * @see ConnectionService#createRemoteIncomingConnection(PhoneAccountHandle, ConnectionRequest) - * @hide */ -@SystemApi public final class RemoteConnection { public static abstract class Callback { @@ -410,6 +407,29 @@ public final class RemoteConnection { } /** + * @hide + */ + RemoteConnection(String callId, IConnectionService connectionService, + ParcelableConnection connection) { + mConnectionId = callId; + mConnectionService = connectionService; + mConnected = true; + mState = connection.getState(); + mDisconnectCause = connection.getDisconnectCause(); + mRingbackRequested = connection.isRingbackRequested(); + mCallCapabilities = connection.getCapabilities(); + mVideoState = connection.getVideoState(); + mVideoProvider = new RemoteConnection.VideoProvider(connection.getVideoProvider()); + mIsVoipAudioMode = connection.getIsVoipAudioMode(); + mStatusHints = connection.getStatusHints(); + mAddress = connection.getHandle(); + mAddressPresentation = connection.getHandlePresentation(); + mCallerDisplayName = connection.getCallerDisplayName(); + mCallerDisplayNamePresentation = connection.getCallerDisplayNamePresentation(); + mConference = null; + } + + /** * Create a RemoteConnection which is used for failed connections. Note that using it for any * "real" purpose will almost certainly fail. Callers should note the failure and act * accordingly (moving on to another RemoteConnection, for example) @@ -418,7 +438,7 @@ public final class RemoteConnection { * @hide */ RemoteConnection(DisconnectCause disconnectCause) { - this("NULL", null, null); + mConnectionId = "NULL"; mConnected = false; mState = Connection.STATE_DISCONNECTED; mDisconnectCause = disconnectCause; diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java index af4ee22ef2af..4bb78c010303 100644 --- a/telecomm/java/android/telecom/RemoteConnectionService.java +++ b/telecomm/java/android/telecom/RemoteConnectionService.java @@ -41,8 +41,9 @@ import java.util.UUID; */ final class RemoteConnectionService { + // Note: Casting null to avoid ambiguous constructor reference. private static final RemoteConnection NULL_CONNECTION = - new RemoteConnection("NULL", null, null); + new RemoteConnection("NULL", null, (ConnectionRequest) null); private static final RemoteConference NULL_CONFERENCE = new RemoteConference("NULL", null); @@ -286,6 +287,15 @@ final class RemoteConnectionService { .setConferenceableConnections(conferenceable); } } + + @Override + public void addExistingConnection(String callId, ParcelableConnection connection) { + // TODO: add contents of this method + RemoteConnection remoteConnction = new RemoteConnection(callId, + mOutgoingConnectionServiceRpc, connection); + + mOurConnectionServiceImpl.addRemoteExistingConnection(remoteConnction); + } }; private final ConnectionServiceAdapterServant mServant = diff --git a/telecomm/java/android/telecom/StatusHints.java b/telecomm/java/android/telecom/StatusHints.java index dd3a639e6bf3..a32eae76dcea 100644 --- a/telecomm/java/android/telecom/StatusHints.java +++ b/telecomm/java/android/telecom/StatusHints.java @@ -16,7 +16,6 @@ package android.telecom; -import android.annotation.SystemApi; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; @@ -30,9 +29,7 @@ import java.util.Objects; /** * Contains status label and icon displayed in the in-call UI. - * @hide */ -@SystemApi public final class StatusHints implements Parcelable { private final ComponentName mPackageName; diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index e87615ef4502..4eac5ac4a570 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -21,6 +21,7 @@ import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.util.Log; import com.android.internal.telecom.ITelecomService; @@ -30,8 +31,17 @@ import java.util.Collections; import java.util.List; /** - * Provides access to Telecom-related functionality. - * TODO: Move this all into PhoneManager. + * Provides access to information about active calls and registration/call-management functionality. + * Apps can use methods in this class to determine the current call state. Apps can also register new + * {@link PhoneAccount}s and get a listing of existing {@link PhoneAccount}s. + * <p> + * Apps do not instantiate this class directly; instead, they retrieve a reference to an instance + * through {@link Context#getSystemService Context.getSystemService(Context.TELECOM_SERVICE)}. + * <p> + * Note that access to some telecom information is permission-protected. Your app cannot access the + * protected information or gain access to protected functionality unless it has the appropriate + * permissions declared in its manifest file. Where permissions apply, they are noted in the method + * descriptions. */ public class TelecomManager { @@ -60,7 +70,6 @@ public class TelecomManager { /** * The {@link android.content.Intent} action used to configure a * {@link android.telecom.ConnectionService}. - * @hide */ public static final String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.telecom.action.CONNECTION_SERVICE_CONFIGURE"; @@ -74,7 +83,6 @@ public class TelecomManager { /** * The {@link android.content.Intent} action used to show the settings page used to configure * {@link PhoneAccount} preferences. - * @hide */ public static final String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecom.action.CHANGE_PHONE_ACCOUNTS"; @@ -105,7 +113,6 @@ public class TelecomManager { * {@link PhoneAccountHandle} to use when making the call. * <p class="note"> * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}. - * @hide */ public static final String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecom.extra.PHONE_ACCOUNT_HANDLE"; @@ -154,7 +161,6 @@ public class TelecomManager { /** * Optional extra for {@link android.telephony.TelephonyManager#ACTION_PHONE_STATE_CHANGED} * containing the component name of the associated connection service. - * @hide */ public static final String EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE"; @@ -190,7 +196,6 @@ public class TelecomManager { * {@link ConnectionService}s which interact with {@link RemoteConnection}s should only populate * this if the {@link android.telephony.TelephonyManager#getLine1Number()} value, as that is the * user's expected caller ID. - * @hide */ public static final String EXTRA_CALL_BACK_NUMBER = "android.telecom.extra.CALL_BACK_NUMBER"; @@ -437,7 +442,6 @@ public class TelecomManager { * {@code PhoneAccount}. * * @return The phone account handle of the current connection manager. - * @hide */ public PhoneAccountHandle getConnectionManager() { return getSimCallManager(); @@ -495,7 +499,6 @@ public class TelecomManager { * * @return {@code true} if the device has more than one account registered and {@code false} * otherwise. - * @hide */ public boolean hasMultipleCallCapableAccounts() { return getCallCapablePhoneAccounts().size() > 1; @@ -505,7 +508,6 @@ public class TelecomManager { * Returns a list of all {@link PhoneAccount}s registered for the calling package. * * @return A list of {@code PhoneAccountHandle} objects. - * @hide */ public List<PhoneAccountHandle> getPhoneAccountsForPackage() { try { @@ -524,7 +526,6 @@ public class TelecomManager { * * @param account The {@link PhoneAccountHandle}. * @return The {@link PhoneAccount} object. - * @hide */ public PhoneAccount getPhoneAccount(PhoneAccountHandle account) { try { @@ -592,12 +593,19 @@ public class TelecomManager { } /** - * Register a {@link PhoneAccount} for use by the system. + * Register a {@link PhoneAccount} for use by the system. When registering + * {@link PhoneAccount}s, existing registrations will be overwritten if the + * {@link PhoneAccountHandle} matches that of a {@link PhoneAccount} which is already + * registered. Once registered, the {@link PhoneAccount} is listed to the user as an option + * when placing calls. The user may still need to enable the {@link PhoneAccount} within + * the phone app settings before the account is usable. + * <p> + * A {@link SecurityException} will be thrown if an app tries to register a + * {@link PhoneAccountHandle} where the package name specified within + * {@link PhoneAccountHandle#getComponentName()} does not match the package name of the app. * * @param account The complete {@link PhoneAccount}. - * @hide */ - @SystemApi public void registerPhoneAccount(PhoneAccount account) { try { if (isServiceConnected()) { @@ -612,9 +620,7 @@ public class TelecomManager { * Remove a {@link PhoneAccount} registration from the system. * * @param accountHandle A {@link PhoneAccountHandle} for the {@link PhoneAccount} to unregister. - * @hide */ - @SystemApi public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) { try { if (isServiceConnected()) { @@ -627,9 +633,7 @@ public class TelecomManager { /** * Remove all Accounts that belong to the calling package from the system. - * @hide */ - @SystemApi public void clearAccounts() { try { if (isServiceConnected()) { @@ -641,6 +645,20 @@ public class TelecomManager { } /** + * Remove all Accounts that belong to the specified package from the system. + * @hide + */ + public void clearAccountsForPackage(String packageName) { + try { + if (isServiceConnected() && !TextUtils.isEmpty(packageName)) { + getTelecomService().clearAccounts(packageName); + } + } catch (RemoteException e) { + Log.e(TAG, "Error calling ITelecomService#clearAccountsForPackage()", e); + } + } + + /** * @hide */ @SystemApi @@ -683,7 +701,6 @@ public class TelecomManager { * Requires permission: {@link android.Manifest.permission#READ_PHONE_STATE} * </p> */ - @SystemApi public boolean isInCall() { try { if (isServiceConnected()) { @@ -701,6 +718,11 @@ public class TelecomManager { * {@link TelephonyManager#CALL_STATE_RINGING} * {@link TelephonyManager#CALL_STATE_OFFHOOK} * {@link TelephonyManager#CALL_STATE_IDLE} + * + * Note that this API does not require the + * {@link android.Manifest.permission#READ_PHONE_STATE} permission. This is intentional, to + * preserve the behavior of {@link TelephonyManager#getCallState()}, which also did not require + * the permission. * @hide */ @SystemApi @@ -834,9 +856,7 @@ public class TelecomManager { * {@link #registerPhoneAccount}. * @param extras A bundle that will be passed through to * {@link ConnectionService#onCreateIncomingConnection}. - * @hide */ - @SystemApi public void addNewIncomingCall(PhoneAccountHandle phoneAccount, Bundle extras) { try { if (isServiceConnected()) { @@ -875,6 +895,7 @@ public class TelecomManager { * Processes the specified dial string as an MMI code. * MMI codes are any sequence of characters entered into the dialpad that contain a "*" or "#". * Some of these sequences launch special behavior through handled by Telephony. + * This method uses the default subscription. * <p> * Requires that the method-caller be set as the system dialer app. * </p> @@ -895,6 +916,31 @@ public class TelecomManager { } /** + * Processes the specified dial string as an MMI code. + * MMI codes are any sequence of characters entered into the dialpad that contain a "*" or "#". + * Some of these sequences launch special behavior through handled by Telephony. + * <p> + * Requires that the method-caller be set as the system dialer app. + * </p> + * + * @param accountHandle The handle for the account the MMI code should apply to. + * @param dialString The digits to dial. + * @return True if the digits were processed as an MMI code, false otherwise. + * + */ + public boolean handleMmi(PhoneAccountHandle accountHandle, String dialString) { + ITelecomService service = getTelecomService(); + if (service != null) { + try { + return service.handlePinMmiForPhoneAccount(accountHandle, dialString); + } catch (RemoteException e) { + Log.e(TAG, "Error calling ITelecomService#handlePinMmi", e); + } + } + return false; + } + + /** * Removes the missed-call notification if one is present. * <p> * Requires that the method-caller be set as the system dialer app. diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl index 5daa568bffc5..0d6b3d9bbb12 100644 --- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl +++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl @@ -77,4 +77,6 @@ oneway interface IConnectionServiceAdapter { void setCallerDisplayName(String callId, String callerDisplayName, int presentation); void setConferenceableConnections(String callId, in List<String> conferenceableCallIds); + + void addExistingConnection(String callId, in ParcelableConnection connection); } diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl index 91f44b9a055b..fd472130deb4 100644 --- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl +++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl @@ -169,6 +169,11 @@ interface ITelecomService { boolean handlePinMmi(String dialString); /** + * @see TelecomServiceImpl#handleMmi + */ + boolean handlePinMmiForPhoneAccount(in PhoneAccountHandle accountHandle, String dialString); + + /** * @see TelecomServiceImpl#isTtySupported */ boolean isTtySupported(); diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index 27e9baf1bbec..897702dc093d 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -1570,7 +1570,7 @@ public class PhoneNumberUtils * listed in the RIL / SIM, otherwise return false. * @hide */ - public static boolean isEmergencyNumber(long subId, String number) { + public static boolean isEmergencyNumber(int subId, String number) { // Return true only if the specified number *exactly* matches // one of the emergency numbers listed by the RIL / SIM. return isEmergencyNumberInternal(subId, number, true /* useExactMatch */); @@ -1620,7 +1620,7 @@ public class PhoneNumberUtils * same digits as any of those emergency numbers. * @hide */ - public static boolean isPotentialEmergencyNumber(long subId, String number) { + public static boolean isPotentialEmergencyNumber(int subId, String number) { // Check against the emergency numbers listed by the RIL / SIM, // and *don't* require an exact match. return isEmergencyNumberInternal(subId, number, false /* useExactMatch */); @@ -1669,7 +1669,7 @@ public class PhoneNumberUtils * @return true if the number is in the list of emergency numbers * listed in the RIL / sim, otherwise return false. */ - private static boolean isEmergencyNumberInternal(long subId, String number, + private static boolean isEmergencyNumberInternal(int subId, String number, boolean useExactMatch) { return isEmergencyNumberInternal(subId, number, null, useExactMatch); } @@ -1698,7 +1698,7 @@ public class PhoneNumberUtils * otherwise false * @hide */ - public static boolean isEmergencyNumber(long subId, String number, String defaultCountryIso) { + public static boolean isEmergencyNumber(int subId, String number, String defaultCountryIso) { return isEmergencyNumberInternal(subId, number, defaultCountryIso, true /* useExactMatch */); @@ -1750,7 +1750,7 @@ public class PhoneNumberUtils * any of those emergency numbers. * @hide */ - public static boolean isPotentialEmergencyNumber(long subId, String number, + public static boolean isPotentialEmergencyNumber(int subId, String number, String defaultCountryIso) { return isEmergencyNumberInternal(subId, number, defaultCountryIso, @@ -1794,7 +1794,7 @@ public class PhoneNumberUtils * @return true if the number is an emergency number for the specified country. * @hide */ - private static boolean isEmergencyNumberInternal(long subId, String number, + private static boolean isEmergencyNumberInternal(int subId, String number, String defaultCountryIso, boolean useExactMatch) { // If the number passed in is null, just return false: @@ -1911,7 +1911,7 @@ public class PhoneNumberUtils * is currently in. * @hide */ - public static boolean isLocalEmergencyNumber(Context context, long subId, String number) { + public static boolean isLocalEmergencyNumber(Context context, int subId, String number) { return isLocalEmergencyNumberInternal(subId, number, context, true /* useExactMatch */); @@ -1965,7 +1965,7 @@ public class PhoneNumberUtils * * @hide */ - public static boolean isPotentialLocalEmergencyNumber(Context context, long subId, + public static boolean isPotentialLocalEmergencyNumber(Context context, int subId, String number) { return isLocalEmergencyNumberInternal(subId, number, context, @@ -2014,7 +2014,7 @@ public class PhoneNumberUtils * local country, based on the CountryDetector. * @hide */ - private static boolean isLocalEmergencyNumberInternal(long subId, String number, + private static boolean isLocalEmergencyNumberInternal(int subId, String number, Context context, boolean useExactMatch) { String countryIso; @@ -2057,7 +2057,7 @@ public class PhoneNumberUtils * to read the VM number. * @hide */ - public static boolean isVoiceMailNumber(long subId, String number) { + public static boolean isVoiceMailNumber(int subId, String number) { String vmNumber; try { @@ -2796,7 +2796,7 @@ public class PhoneNumberUtils /** * Returns Default voice subscription Id. */ - private static long getDefaultVoiceSubId() { + private static int getDefaultVoiceSubId() { return SubscriptionManager.getDefaultVoiceSubId(); } //==== End of utility methods used only in compareStrictly() ===== diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java index ec34ce8218ca..2f1a8da24d54 100644 --- a/telephony/java/android/telephony/PhoneStateListener.java +++ b/telephony/java/android/telephony/PhoneStateListener.java @@ -227,7 +227,7 @@ public class PhoneStateListener { * @hide */ /** @hide */ - protected long mSubId = SubscriptionManager.INVALID_SUB_ID; + protected int mSubId = SubscriptionManager.INVALID_SUB_ID; private final Handler mHandler; @@ -252,10 +252,10 @@ public class PhoneStateListener { /** * Create a PhoneStateListener for the Phone using the specified subscription. * This class requires Looper.myLooper() not return null. To supply your - * own non-null Looper use PhoneStateListener(long subId, Looper looper) below. + * own non-null Looper use PhoneStateListener(int subId, Looper looper) below. * @hide */ - public PhoneStateListener(long subId) { + public PhoneStateListener(int subId) { this(subId, Looper.myLooper()); } @@ -264,7 +264,7 @@ public class PhoneStateListener { * and non-null Looper. * @hide */ - public PhoneStateListener(long subId, Looper looper) { + public PhoneStateListener(int subId, Looper looper) { if (DBG) log("ctor: subId=" + subId + " looper=" + looper); mSubId = subId; mHandler = new Handler(looper) { diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index 52d05165c416..8c2a4ebb5e45 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -864,4 +864,23 @@ public class ServiceState implements Parcelable { || radioTechnology == RIL_RADIO_TECHNOLOGY_EVDO_B || radioTechnology == RIL_RADIO_TECHNOLOGY_EHRPD; } + + /** + * Returns a merged ServiceState consisting of the base SS with voice settings from the + * voice SS. The voice SS is only used if it is IN_SERVICE (otherwise the base SS is returned). + * @hide + * */ + public static ServiceState mergeServiceStates(ServiceState baseSs, ServiceState voiceSs) { + if (voiceSs.mVoiceRegState != STATE_IN_SERVICE) { + return baseSs; + } + + ServiceState newSs = new ServiceState(baseSs); + + // voice overrides + newSs.mVoiceRegState = voiceSs.mVoiceRegState; + newSs.mIsEmergencyOnly = false; // only get here if voice is IN_SERVICE + + return newSs; + } } diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java index 3363ca678c6a..17db3fb97d7b 100644 --- a/telephony/java/android/telephony/SignalStrength.java +++ b/telephony/java/android/telephony/SignalStrength.java @@ -20,6 +20,7 @@ import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.telephony.Rlog; +import android.content.res.Resources; /** * Contains phone signal strength related information. @@ -50,6 +51,11 @@ public class SignalStrength implements Parcelable { //Use int max, as -1 is a valid value in signal strength public static final int INVALID = 0x7FFFFFFF; + private static final int RSRP_THRESH_TYPE_STRICT = 0; + private static final int[] RSRP_THRESH_STRICT = new int[] {-140, -115, -105, -95, -85, -44}; + private static final int[] RSRP_THRESH_LENIENT = new int[] {-140, -128, -118, -108, -98, -44}; + + private int mGsmSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5 private int mGsmBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5 private int mCdmaDbm; // This value is the RSSI value @@ -745,12 +751,21 @@ public class SignalStrength implements Parcelable { */ int rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, rsrpIconLevel = -1, snrIconLevel = -1; - if (mLteRsrp > -44) rsrpIconLevel = -1; - else if (mLteRsrp >= -85) rsrpIconLevel = SIGNAL_STRENGTH_GREAT; - else if (mLteRsrp >= -95) rsrpIconLevel = SIGNAL_STRENGTH_GOOD; - else if (mLteRsrp >= -105) rsrpIconLevel = SIGNAL_STRENGTH_MODERATE; - else if (mLteRsrp >= -115) rsrpIconLevel = SIGNAL_STRENGTH_POOR; - else if (mLteRsrp >= -140) rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; + int rsrpThreshType = Resources.getSystem().getInteger(com.android.internal.R.integer. + config_LTE_RSRP_threshold_type); + int[] threshRsrp; + if (rsrpThreshType == RSRP_THRESH_TYPE_STRICT) { + threshRsrp = RSRP_THRESH_STRICT; + } else { + threshRsrp = RSRP_THRESH_LENIENT; + } + + if (mLteRsrp > threshRsrp[5]) rsrpIconLevel = -1; + else if (mLteRsrp >= threshRsrp[4]) rsrpIconLevel = SIGNAL_STRENGTH_GREAT; + else if (mLteRsrp >= threshRsrp[3]) rsrpIconLevel = SIGNAL_STRENGTH_GOOD; + else if (mLteRsrp >= threshRsrp[2]) rsrpIconLevel = SIGNAL_STRENGTH_MODERATE; + else if (mLteRsrp >= threshRsrp[1]) rsrpIconLevel = SIGNAL_STRENGTH_POOR; + else if (mLteRsrp >= threshRsrp[0]) rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; /* * Values are -200 dB to +300 (SNR*10dB) RS_SNR >= 13.0 dB =>4 bars 4.5 @@ -789,6 +804,7 @@ public class SignalStrength implements Parcelable { else if (mLteSignalStrength >= 8) rssiIconLevel = SIGNAL_STRENGTH_GOOD; else if (mLteSignalStrength >= 5) rssiIconLevel = SIGNAL_STRENGTH_MODERATE; else if (mLteSignalStrength >= 0) rssiIconLevel = SIGNAL_STRENGTH_POOR; + if (DBG) log("getLTELevel - rssi:" + mLteSignalStrength + " rssiIconLevel:" + rssiIconLevel); return rssiIconLevel; diff --git a/telephony/java/android/telephony/SubInfoRecord.java b/telephony/java/android/telephony/SubInfoRecord.java index 10058e285765..4a3d67ef25a5 100644 --- a/telephony/java/android/telephony/SubInfoRecord.java +++ b/telephony/java/android/telephony/SubInfoRecord.java @@ -22,7 +22,6 @@ import android.os.Parcelable; /** * A Parcelable class for Subscription Information. - * @hide */ public class SubInfoRecord implements Parcelable { @@ -30,7 +29,7 @@ public class SubInfoRecord implements Parcelable { * Subscription Identifier, this is a device unique number * and not an index into an array */ - public long subId; + public int subId; /** The GID for a SIM that maybe associated with this subscription, empty if unknown */ public String iccId; /** @@ -92,7 +91,7 @@ public class SubInfoRecord implements Parcelable { this.mnc = 0; } - public SubInfoRecord(long subId, String iccId, int slotId, String displayName, int nameSource, + public SubInfoRecord(int subId, String iccId, int slotId, String displayName, int nameSource, int color, String number, int displayFormat, int roaming, int[] iconRes, int mcc, int mnc) { this.subId = subId; @@ -137,7 +136,7 @@ public class SubInfoRecord implements Parcelable { public static final Parcelable.Creator<SubInfoRecord> CREATOR = new Parcelable.Creator<SubInfoRecord>() { @Override public SubInfoRecord createFromParcel(Parcel source) { - long subId = source.readLong(); + int subId = source.readInt(); String iccId = source.readString(); int slotId = source.readInt(); String displayName = source.readString(); @@ -163,7 +162,7 @@ public class SubInfoRecord implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(subId); + dest.writeInt(subId); dest.writeString(iccId); dest.writeInt(slotId); dest.writeString(displayName); diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index b37a75206908..edfddc7d5e8b 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -18,7 +18,6 @@ package android.telephony; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; -import android.annotation.SystemApi; import android.content.Intent; import android.net.Uri; import android.provider.BaseColumns; @@ -38,8 +37,6 @@ import java.util.List; * * The android.Manifest.permission.READ_PHONE_STATE to retrieve the information, except * getActiveSubIdList and getActiveSubIdCount for which no permission is needed. - * - * @hide */ public class SubscriptionManager implements BaseColumns { private static final String LOG_TAG = "SUB"; @@ -47,40 +44,34 @@ public class SubscriptionManager implements BaseColumns { private static final boolean VDBG = false; /** An invalid phone identifier */ - @SystemApi public static final int INVALID_PHONE_ID = -1000; /** Indicates the caller wants the default phone id. */ - @SystemApi public static final int DEFAULT_PHONE_ID = Integer.MAX_VALUE; /** An invalid slot identifier */ - @SystemApi public static final int INVALID_SLOT_ID = -1000; /** Indicates the caller wants the default slot id. */ - @SystemApi + /** @hide */ public static final int DEFAULT_SLOT_ID = Integer.MAX_VALUE; /** Indicates the user should be asked which subscription to use. */ - @SystemApi - public static final long ASK_USER_SUB_ID = -1001; + public static final int ASK_USER_SUB_ID = -1001; /** An invalid subscription identifier */ - @SystemApi - public static final long INVALID_SUB_ID = -1000; + public static final int INVALID_SUB_ID = -1000; /** Indicates the caller wants the default sub id. */ - @SystemApi - public static final long DEFAULT_SUB_ID = Long.MAX_VALUE; + public static final int DEFAULT_SUB_ID = Integer.MAX_VALUE; /** Minimum possible subid that represents a subscription */ /** @hide */ - public static final long MIN_SUB_ID_VALUE = 0; + public static final int MIN_SUB_ID_VALUE = 0; /** Maximum possible subid that represents a subscription */ /** @hide */ - public static final long MAX_SUB_ID_VALUE = DEFAULT_SUB_ID - 1; + public static final int MAX_SUB_ID_VALUE = DEFAULT_SUB_ID - 1; /** @hide */ @@ -125,7 +116,6 @@ public class SubscriptionManager implements BaseColumns { public static final String SIM_ID = "sim_id"; /** SIM is not inserted */ - @SystemApi public static final int SIM_NOT_INSERTED = -1; /** @@ -275,7 +265,7 @@ public class SubscriptionManager implements BaseColumns { * @param subId The unique SubInfoRecord index in database * @return SubInfoRecord, maybe null */ - public static SubInfoRecord getSubInfoForSubscriber(long subId) { + public static SubInfoRecord getSubInfoForSubscriber(int subId) { if (!isValidSubId(subId)) { logd("[getSubInfoForSubscriberx]- invalid subId"); return null; @@ -332,7 +322,6 @@ public class SubscriptionManager implements BaseColumns { * @param slotId the slot which the SIM is inserted * @return SubInfoRecord list, maybe empty but not null */ - @SystemApi public static List<SubInfoRecord> getSubInfoUsingSlotId(int slotId) { // FIXME: Consider never returning null if (!isValidSlotId(slotId)) { @@ -388,7 +377,6 @@ public class SubscriptionManager implements BaseColumns { * Get the SubInfoRecord(s) of the currently inserted SIM(s) * @return Array list of currently inserted SubInfoRecord(s) maybe empty but not null */ - @SystemApi public static List<SubInfoRecord> getActiveSubInfoList() { List<SubInfoRecord> result = null; @@ -482,15 +470,15 @@ public class SubscriptionManager implements BaseColumns { /** * Set SIM color by simInfo index - * @param color the color of the SIM + * @param color the rgb value of color of the SIM * @param subId the unique SubInfoRecord index in database * @return the number of records updated * @hide */ - public static int setColor(int color, long subId) { + public static int setColor(int color, int subId) { if (VDBG) logd("[setColor]+ color:" + color + " subId:" + subId); int size = sSimBackgroundDarkRes.length; - if (!isValidSubId(subId) || color < 0 || color >= size) { + if (!isValidSubId(subId)) { logd("[setColor]- fail"); return -1; } @@ -517,7 +505,7 @@ public class SubscriptionManager implements BaseColumns { * @return the number of records updated * @hide */ - public static int setDisplayName(String displayName, long subId) { + public static int setDisplayName(String displayName, int subId) { return setDisplayName(displayName, subId, NAME_SOURCE_UNDEFINDED); } @@ -530,7 +518,7 @@ public class SubscriptionManager implements BaseColumns { * @return the number of records updated or -1 if invalid subId * @hide */ - public static int setDisplayName(String displayName, long subId, long nameSource) { + public static int setDisplayName(String displayName, int subId, long nameSource) { if (VDBG) { logd("[setDisplayName]+ displayName:" + displayName + " subId:" + subId + " nameSource:" + nameSource); @@ -562,7 +550,7 @@ public class SubscriptionManager implements BaseColumns { * @return the number of records updated * @hide */ - public static int setDisplayNumber(String number, long subId) { + public static int setDisplayNumber(String number, int subId) { if (number == null || !isValidSubId(subId)) { logd("[setDisplayNumber]- fail"); return -1; @@ -590,7 +578,7 @@ public class SubscriptionManager implements BaseColumns { * @return the number of records updated * @hide */ - public static int setDisplayNumberFormat(int format, long subId) { + public static int setDisplayNumberFormat(int format, int subId) { if (VDBG) logd("[setDisplayNumberFormat]+ format:" + format + " subId:" + subId); if (format < 0 || !isValidSubId(subId)) { logd("[setDisplayNumberFormat]- fail, return -1"); @@ -619,7 +607,7 @@ public class SubscriptionManager implements BaseColumns { * @return the number of records updated * @hide */ - public static int setDataRoaming(int roaming, long subId) { + public static int setDataRoaming(int roaming, int subId) { if (VDBG) logd("[setDataRoaming]+ roaming:" + roaming + " subId:" + subId); if (roaming < 0 || !isValidSubId(subId)) { logd("[setDataRoaming]- fail"); @@ -645,8 +633,7 @@ public class SubscriptionManager implements BaseColumns { * @return slotId as a positive integer or a negative value if an error either * SIM_NOT_INSERTED or INVALID_SLOT_ID. */ - @SystemApi - public static int getSlotId(long subId) { + public static int getSlotId(int subId) { if (!isValidSubId(subId)) { logd("[getSlotId]- fail"); } @@ -667,13 +654,13 @@ public class SubscriptionManager implements BaseColumns { } /** @hide */ - public static long[] getSubId(int slotId) { + public static int[] getSubId(int slotId) { if (!isValidSlotId(slotId)) { logd("[getSubId]- fail"); return null; } - long[] subId = null; + int[] subId = null; try { ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); @@ -688,7 +675,7 @@ public class SubscriptionManager implements BaseColumns { } /** @hide */ - public static int getPhoneId(long subId) { + public static int getPhoneId(int subId) { if (!isValidSubId(subId)) { logd("[getPhoneId]- fail"); return INVALID_PHONE_ID; @@ -745,8 +732,8 @@ public class SubscriptionManager implements BaseColumns { * getDefaultDataSubId(). * @hide */ - public static long getDefaultSubId() { - long subId = INVALID_SUB_ID; + public static int getDefaultSubId() { + int subId = INVALID_SUB_ID; try { ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); @@ -762,8 +749,8 @@ public class SubscriptionManager implements BaseColumns { } /** @hide */ - public static long getDefaultVoiceSubId() { - long subId = INVALID_SUB_ID; + public static int getDefaultVoiceSubId() { + int subId = INVALID_SUB_ID; try { ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); @@ -779,7 +766,7 @@ public class SubscriptionManager implements BaseColumns { } /** @hide */ - public static void setDefaultVoiceSubId(long subId) { + public static void setDefaultVoiceSubId(int subId) { if (VDBG) logd("setDefaultVoiceSubId sub id = " + subId); try { ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); @@ -804,9 +791,8 @@ public class SubscriptionManager implements BaseColumns { /** * @return subId of the DefaultSms subscription or the value INVALID_SUB_ID if an error. */ - @SystemApi - public static long getDefaultSmsSubId() { - long subId = INVALID_SUB_ID; + public static int getDefaultSmsSubId() { + int subId = INVALID_SUB_ID; try { ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); @@ -822,7 +808,7 @@ public class SubscriptionManager implements BaseColumns { } /** @hide */ - public static void setDefaultSmsSubId(long subId) { + public static void setDefaultSmsSubId(int subId) { if (VDBG) logd("setDefaultSmsSubId sub id = " + subId); try { ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); @@ -845,8 +831,8 @@ public class SubscriptionManager implements BaseColumns { } /** @hide */ - public static long getDefaultDataSubId() { - long subId = INVALID_SUB_ID; + public static int getDefaultDataSubId() { + int subId = INVALID_SUB_ID; try { ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); @@ -862,7 +848,7 @@ public class SubscriptionManager implements BaseColumns { } /** @hide */ - public static void setDefaultDataSubId(long subId) { + public static void setDefaultDataSubId(int subId) { if (VDBG) logd("setDataSubscription sub id = " + subId); try { ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); @@ -933,8 +919,7 @@ public class SubscriptionManager implements BaseColumns { /** * @return true if a valid subId else false */ - @SystemApi - public static boolean isValidSubId(long subId) { + public static boolean isValidSubId(int subId) { return subId > INVALID_SUB_ID ; } @@ -943,7 +928,7 @@ public class SubscriptionManager implements BaseColumns { * usable subId means its neither a INVALID_SUB_ID nor a DEFAUL_SUB_ID. * @hide */ - public static boolean isUsableSubIdValue(long subId) { + public static boolean isUsableSubIdValue(int subId) { return subId >= MIN_SUB_ID_VALUE && subId <= MAX_SUB_ID_VALUE; } @@ -967,7 +952,7 @@ public class SubscriptionManager implements BaseColumns { /** @hide */ public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId) { - long[] subIds = SubscriptionManager.getSubId(phoneId); + int[] subIds = SubscriptionManager.getSubId(phoneId); if (subIds != null && subIds.length > 0) { putPhoneIdAndSubIdExtra(intent, phoneId, subIds[0]); } else { @@ -976,7 +961,7 @@ public class SubscriptionManager implements BaseColumns { } /** @hide */ - public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId, long subId) { + public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId, int subId) { if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId); intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId); intent.putExtra(PhoneConstants.PHONE_KEY, phoneId); @@ -990,8 +975,8 @@ public class SubscriptionManager implements BaseColumns { * is never null but the length maybe 0. * @hide */ - public static long[] getActiveSubIdList() { - long[] subId = null; + public static int[] getActiveSubIdList() { + int[] subId = null; try { ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); @@ -1003,7 +988,7 @@ public class SubscriptionManager implements BaseColumns { } if (subId == null) { - subId = new long[0]; + subId = new int[0]; } return subId; diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index b72a920bed29..0246a2da1359 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -588,7 +588,7 @@ public class TelephonyManager { /** {@hide} */ public String getDeviceSoftwareVersion(int slotId) { // FIXME methods taking slot id should not use subscription, instead us Uicc directly - long[] subId = SubscriptionManager.getSubId(slotId); + int[] subId = SubscriptionManager.getSubId(slotId); if (subId == null || subId.length == 0) { return null; } @@ -624,7 +624,7 @@ public class TelephonyManager { /** {@hide} */ public String getDeviceId(int slotId) { // FIXME methods taking slot id should not use subscription, instead us Uicc directly - long[] subId = SubscriptionManager.getSubId(slotId); + int[] subId = SubscriptionManager.getSubId(slotId); if (subId == null || subId.length == 0) { return null; } @@ -658,7 +658,7 @@ public class TelephonyManager { */ /** {@hide} */ public String getImei(int slotId) { - long[] subId = SubscriptionManager.getSubId(slotId); + int[] subId = SubscriptionManager.getSubId(slotId); try { return getSubscriberInfo().getImeiForSubscriber(subId[0]); } catch (RemoteException ex) { @@ -669,6 +669,32 @@ public class TelephonyManager { } /** + * Returns the NAI. Return null if NAI is not available. + * + */ + /** {@hide}*/ + public String getNai() { + return getNai(getDefaultSim()); + } + + /** + * Returns the NAI. Return null if NAI is not available. + * + * @param slotId of which Nai is returned + */ + /** {@hide}*/ + public String getNai(int slotId) { + int[] subId = SubscriptionManager.getSubId(slotId); + try { + return getSubscriberInfo().getNaiForSubscriber(subId[0]); + } catch (RemoteException ex) { + return null; + } catch (NullPointerException ex) { + return null; + } + } + + /** * Returns the current location of the device. *<p> * If there is only one radio in the device and that radio has an LTE connection, @@ -722,7 +748,7 @@ public class TelephonyManager { * @param subId for which the location updates are enabled */ /** @hide */ - public void enableLocationUpdates(long subId) { + public void enableLocationUpdates(int subId) { try { getITelephony().enableLocationUpdatesForSubscriber(subId); } catch (RemoteException ex) { @@ -744,7 +770,7 @@ public class TelephonyManager { } /** @hide */ - public void disableLocationUpdates(long subId) { + public void disableLocationUpdates(int subId) { try { getITelephony().disableLocationUpdatesForSubscriber(subId); } catch (RemoteException ex) { @@ -809,7 +835,7 @@ public class TelephonyManager { */ /** {@hide} */ @SystemApi - public int getCurrentPhoneType(long subId) { + public int getCurrentPhoneType(int subId) { int phoneId = SubscriptionManager.getPhoneId(subId); try{ ITelephony telephony = getITelephony(); @@ -1021,7 +1047,7 @@ public class TelephonyManager { * @param subId */ /** {@hide} */ - public String getNetworkOperatorName(long subId) { + public String getNetworkOperatorName(int subId) { int phoneId = SubscriptionManager.getPhoneId(subId); return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ALPHA, ""); } @@ -1048,7 +1074,7 @@ public class TelephonyManager { * @param subId */ /** {@hide} */ - public String getNetworkOperator(long subId) { + public String getNetworkOperator(int subId) { int phoneId = SubscriptionManager.getPhoneId(subId); return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, ""); } @@ -1072,7 +1098,7 @@ public class TelephonyManager { * @param subId */ /** {@hide} */ - public boolean isNetworkRoaming(long subId) { + public boolean isNetworkRoaming(int subId) { int phoneId = SubscriptionManager.getPhoneId(subId); return Boolean.parseBoolean(getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ISROAMING, null)); @@ -1101,7 +1127,7 @@ public class TelephonyManager { * @param subId for which Network CountryIso is returned */ /** {@hide} */ - public String getNetworkCountryIso(long subId) { + public String getNetworkCountryIso(int subId) { int phoneId = SubscriptionManager.getPhoneId(subId); return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, ""); } @@ -1173,7 +1199,7 @@ public class TelephonyManager { * @see #NETWORK_TYPE_HSPAP */ /** {@hide} */ - public int getNetworkType(long subId) { + public int getNetworkType(int subId) { try { ITelephony telephony = getITelephony(); if (telephony != null) { @@ -1227,7 +1253,7 @@ public class TelephonyManager { * @param subId for which network type is returned */ /** {@hide} */ - public int getDataNetworkType(long subId) { + public int getDataNetworkType(int subId) { try{ ITelephony telephony = getITelephony(); if (telephony != null) { @@ -1259,7 +1285,7 @@ public class TelephonyManager { * */ /** {@hide} */ - public int getVoiceNetworkType(long subId) { + public int getVoiceNetworkType(int subId) { try{ ITelephony telephony = getITelephony(); if (telephony != null) { @@ -1416,7 +1442,7 @@ public class TelephonyManager { */ /** {@hide} */ // FIXME Input argument slotId should be of type int - public boolean hasIccCard(long slotId) { + public boolean hasIccCard(int slotId) { try { return getITelephony().hasIccCardUsingSlotId(slotId); @@ -1461,7 +1487,7 @@ public class TelephonyManager { /** {@hide} */ // FIXME the argument to pass is subId ?? public int getSimState(int slotId) { - long[] subId = SubscriptionManager.getSubId(slotId); + int[] subId = SubscriptionManager.getSubId(slotId); if (subId == null || subId.length == 0) { return SIM_STATE_ABSENT; } @@ -1501,7 +1527,7 @@ public class TelephonyManager { * @see #getSimState */ public String getSimOperator() { - long subId = SubscriptionManager.getDefaultDataSubId(); + int subId = SubscriptionManager.getDefaultDataSubId(); if (!SubscriptionManager.isUsableSubIdValue(subId)) { subId = SubscriptionManager.getDefaultSmsSubId(); if (!SubscriptionManager.isUsableSubIdValue(subId)) { @@ -1526,7 +1552,7 @@ public class TelephonyManager { * @param subId for which SimOperator is returned */ /** {@hide} */ - public String getSimOperator(long subId) { + public String getSimOperator(int subId) { int phoneId = SubscriptionManager.getPhoneId(subId); String operator = getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, ""); @@ -1555,7 +1581,7 @@ public class TelephonyManager { * @param subId for which SimOperatorName is returned */ /** {@hide} */ - public String getSimOperatorName(long subId) { + public String getSimOperatorName(int subId) { int phoneId = SubscriptionManager.getPhoneId(subId); return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA, ""); } @@ -1573,7 +1599,7 @@ public class TelephonyManager { * @param subId for which SimCountryIso is returned */ /** {@hide} */ - public String getSimCountryIso(long subId) { + public String getSimCountryIso(int subId) { int phoneId = SubscriptionManager.getPhoneId(subId); return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY, ""); @@ -1599,7 +1625,7 @@ public class TelephonyManager { * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} */ /** {@hide} */ - public String getSimSerialNumber(long subId) { + public String getSimSerialNumber(int subId) { try { return getSubscriberInfo().getIccSerialNumberForSubscriber(subId); } catch (RemoteException ex) { @@ -1635,7 +1661,7 @@ public class TelephonyManager { * */ /** {@hide} */ - public int getLteOnCdmaMode(long subId) { + public int getLteOnCdmaMode(int subId) { try { return getITelephony().getLteOnCdmaModeForSubscriber(subId); } catch (RemoteException ex) { @@ -1675,7 +1701,7 @@ public class TelephonyManager { * @param subId whose subscriber id is returned */ /** {@hide} */ - public String getSubscriberId(long subId) { + public String getSubscriberId(int subId) { try { return getSubscriberInfo().getSubscriberIdForSubscriber(subId); } catch (RemoteException ex) { @@ -1714,7 +1740,7 @@ public class TelephonyManager { * @param subscription whose subscriber id is returned */ /** {@hide} */ - public String getGroupIdLevel1(long subId) { + public String getGroupIdLevel1(int subId) { try { return getSubscriberInfo().getGroupIdLevel1ForSubscriber(subId); } catch (RemoteException ex) { @@ -1746,7 +1772,7 @@ public class TelephonyManager { * @param subId whose phone number for line 1 is returned */ /** {@hide} */ - public String getLine1NumberForSubscriber(long subId) { + public String getLine1NumberForSubscriber(int subId) { String number = null; try { number = getITelephony().getLine1NumberForDisplay(subId); @@ -1778,7 +1804,6 @@ public class TelephonyManager { * * @param alphaTag alpha-tagging of the dailing nubmer * @param number The dialing number - * @hide */ public void setLine1NumberForDisplay(String alphaTag, String number) { setLine1NumberForDisplayForSubscriber(getDefaultSubscription(), alphaTag, number); @@ -1799,7 +1824,7 @@ public class TelephonyManager { * @param number The dialing number * @hide */ - public void setLine1NumberForDisplayForSubscriber(long subId, String alphaTag, String number) { + public void setLine1NumberForDisplayForSubscriber(int subId, String alphaTag, String number) { try { getITelephony().setLine1NumberForDisplayForSubscriber(subId, alphaTag, number); } catch (RemoteException ex) { @@ -1831,7 +1856,7 @@ public class TelephonyManager { * nobody seems to call this. */ /** {@hide} */ - public String getLine1AlphaTagForSubscriber(long subId) { + public String getLine1AlphaTagForSubscriber(int subId) { String alphaTag = null; try { alphaTag = getITelephony().getLine1AlphaTagForDisplay(subId); @@ -1874,7 +1899,7 @@ public class TelephonyManager { * @param subId for which msisdn is returned */ /** {@hide} */ - public String getMsisdn(long subId) { + public String getMsisdn(int subId) { try { return getSubscriberInfo().getMsisdnForSubscriber(subId); } catch (RemoteException ex) { @@ -1904,7 +1929,7 @@ public class TelephonyManager { * @param subId whose voice mail number is returned */ /** {@hide} */ - public String getVoiceMailNumber(long subId) { + public String getVoiceMailNumber(int subId) { try { return getSubscriberInfo().getVoiceMailNumberForSubscriber(subId); } catch (RemoteException ex) { @@ -1936,7 +1961,7 @@ public class TelephonyManager { * @param subId */ /** {@hide} */ - public String getCompleteVoiceMailNumber(long subId) { + public String getCompleteVoiceMailNumber(int subId) { try { return getSubscriberInfo().getCompleteVoiceMailNumberForSubscriber(subId); } catch (RemoteException ex) { @@ -1966,7 +1991,7 @@ public class TelephonyManager { * @param subId whose voice message count is returned */ /** {@hide} */ - public int getVoiceMessageCount(long subId) { + public int getVoiceMessageCount(int subId) { try { return getITelephony().getVoiceMessageCountForSubscriber(subId); } catch (RemoteException ex) { @@ -1998,7 +2023,7 @@ public class TelephonyManager { * voice mail number is returned */ /** {@hide} */ - public String getVoiceMailAlphaTag(long subId) { + public String getVoiceMailAlphaTag(int subId) { try { return getSubscriberInfo().getVoiceMailAlphaTagForSubscriber(subId); } catch (RemoteException ex) { @@ -2095,7 +2120,7 @@ public class TelephonyManager { * @param subId whose call state is returned */ /** {@hide} */ - public int getCallState(long subId) { + public int getCallState(int subId) { try { return getITelephony().getCallStateForSubscriber(subId); } catch (RemoteException ex) { @@ -2246,7 +2271,7 @@ public class TelephonyManager { * Returns the CDMA ERI icon index to display for a subscription */ /** {@hide} */ - public int getCdmaEriIconIndex(long subId) { + public int getCdmaEriIconIndex(int subId) { try { return getITelephony().getCdmaEriIconIndexForSubscriber(subId); } catch (RemoteException ex) { @@ -2274,7 +2299,7 @@ public class TelephonyManager { * 1 - FLASHING */ /** {@hide} */ - public int getCdmaEriIconMode(long subId) { + public int getCdmaEriIconMode(int subId) { try { return getITelephony().getCdmaEriIconModeForSubscriber(subId); } catch (RemoteException ex) { @@ -2299,7 +2324,7 @@ public class TelephonyManager { * */ /** {@hide} */ - public String getCdmaEriText(long subId) { + public String getCdmaEriText(int subId) { try { return getITelephony().getCdmaEriTextForSubscriber(subId); } catch (RemoteException ex) { @@ -2423,6 +2448,7 @@ public class TelephonyManager { * * <p>Requires Permission: * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} + * Or the calling app has carrier privileges. @see #hasCarrierPrivileges * * @param AID Application id. See ETSI 102.221 and 101.220. * @return an IccOpenLogicalChannelResponse object. @@ -2443,6 +2469,7 @@ public class TelephonyManager { * * <p>Requires Permission: * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} + * Or the calling app has carrier privileges. @see #hasCarrierPrivileges * * @param channel is the channel id to be closed as retruned by a successful * iccOpenLogicalChannel. @@ -2464,6 +2491,7 @@ public class TelephonyManager { * * <p>Requires Permission: * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} + * Or the calling app has carrier privileges. @see #hasCarrierPrivileges * * @param channel is the channel id to be closed as returned by a successful * iccOpenLogicalChannel. @@ -2495,6 +2523,7 @@ public class TelephonyManager { * * <p>Requires Permission: * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} + * Or the calling app has carrier privileges. @see #hasCarrierPrivileges * * @param cla Class of the APDU command. * @param instruction Instruction of the APDU command. @@ -2522,6 +2551,7 @@ public class TelephonyManager { * * <p>Requires Permission: * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} + * Or the calling app has carrier privileges. @see #hasCarrierPrivileges * * @param fileID * @param command @@ -2547,6 +2577,7 @@ public class TelephonyManager { * * <p>Requires Permission: * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} + * Or the calling app has carrier privileges. @see #hasCarrierPrivileges * * @param content String containing SAT/USAT response in hexadecimal * format starting with command tag. See TS 102 223 for @@ -2665,7 +2696,7 @@ public class TelephonyManager { /** * Returns Default subscription. */ - private static long getDefaultSubscription() { + private static int getDefaultSubscription() { return SubscriptionManager.getDefaultSubId(); } @@ -2907,7 +2938,7 @@ public class TelephonyManager { * @return the response of SIM Authentication, or null if not available * @hide */ - public String getIccSimChallengeResponse(long subId, int appType, String data) { + public String getIccSimChallengeResponse(int subId, int appType, String data) { try { return getSubscriberInfo().getIccSimChallengeResponse(subId, appType, data); } catch (RemoteException ex) { @@ -3011,7 +3042,6 @@ public class TelephonyManager { * Or the calling app has carrier privileges. @see #hasCarrierPrivileges * * @return true on success; false on any failure. - * @hide */ public boolean setGlobalPreferredNetworkType() { return setPreferredNetworkType(RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA); @@ -3019,23 +3049,10 @@ public class TelephonyManager { /** * Values used to return status for hasCarrierPrivileges call. - * @hide */ public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; - /** - * Values used to return status for hasCarrierPrivileges call. - * @hide - */ public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; - /** - * Values used to return status for hasCarrierPrivileges call. - * @hide - */ public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; - /** - * Values used to return status for hasCarrierPrivileges call. - * @hide - */ public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; /** @@ -3052,7 +3069,6 @@ public class TelephonyManager { * CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED if the carrier rules are not loaded. * CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES if there was an error loading carrier * rules (or if there are no rules). - * @hide */ public int hasCarrierPrivileges() { try { @@ -3079,7 +3095,6 @@ public class TelephonyManager { * * @param brand The brand name to display/set. * @return true if the operation was executed correctly. - * @hide */ public boolean setOperatorBrandOverride(String brand) { try { @@ -3104,7 +3119,7 @@ public class TelephonyManager { /** @hide */ @SystemApi - public String getCdmaMdn(long subId) { + public String getCdmaMdn(int subId) { try { return getITelephony().getCdmaMdn(subId); } catch (RemoteException ex) { @@ -3122,7 +3137,7 @@ public class TelephonyManager { /** @hide */ @SystemApi - public String getCdmaMin(long subId) { + public String getCdmaMin(int subId) { try { return getITelephony().getCdmaMin(subId); } catch (RemoteException ex) { @@ -3321,6 +3336,17 @@ public class TelephonyManager { /** @hide */ @SystemApi + public boolean handlePinMmiForSubscriber(int subId, String dialString) { + try { + return getITelephony().handlePinMmiForSubscriber(subId, dialString); + } catch (RemoteException e) { + Log.e(TAG, "Error calling ITelephony#handlePinMmi", e); + } + return false; + } + + /** @hide */ + @SystemApi public void toggleRadioOnOff() { try { getITelephony().toggleRadioOnOff(); @@ -3453,7 +3479,7 @@ public class TelephonyManager { * @param enable true means enabling the simplified UI. * @hide */ - public void enableSimplifiedNetworkSettingsForSubscriber(long subId, boolean enable) { + public void enableSimplifiedNetworkSettingsForSubscriber(int subId, boolean enable) { try { getITelephony().enableSimplifiedNetworkSettingsForSubscriber(subId, enable); } catch (RemoteException ex) { @@ -3486,7 +3512,7 @@ public class TelephonyManager { * @return true if the simplified UI is enabled. * @hide */ - public boolean getSimplifiedNetworkSettingsEnabledForSubscriber(long subId) { + public boolean getSimplifiedNetworkSettingsEnabledForSubscriber(int subId) { try { return getITelephony().getSimplifiedNetworkSettingsEnabledForSubscriber(subId); } catch (RemoteException ex) { @@ -3513,4 +3539,25 @@ public class TelephonyManager { } return -1; } + + /** @hide */ + @SystemApi + public void enableVideoCalling(boolean enable) { + try { + getITelephony().enableVideoCalling(enable); + } catch (RemoteException e) { + Log.e(TAG, "Error calling ITelephony#enableVideoCalling", e); + } + } + + /** @hide */ + @SystemApi + public boolean isVideoCallingEnabled() { + try { + return getITelephony().isVideoCallingEnabled(); + } catch (RemoteException e) { + Log.e(TAG, "Error calling ITelephony#isVideoCallingEnabled", e); + } + return false; + } } diff --git a/telephony/java/com/android/ims/ImsConferenceState.java b/telephony/java/com/android/ims/ImsConferenceState.java index f708d5bc0530..c57ef98abb4d 100644 --- a/telephony/java/com/android/ims/ImsConferenceState.java +++ b/telephony/java/com/android/ims/ImsConferenceState.java @@ -24,6 +24,8 @@ import java.util.Set; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import android.telecom.Call; +import android.telecom.Connection; /** * Provides the conference information (defined in RFC 4575) for IMS conference call. @@ -139,4 +141,30 @@ public class ImsConferenceState implements Parcelable { return new ImsConferenceState[size]; } }; + + /** + * Translates an {@code ImsConferenceState} status type to a telecom connection state. + * + * @param status The status type. + * @return The corresponding {@link android.telecom.Connection} state. + */ + public static int getConnectionStateForStatus(String status) { + if (status.equals(STATUS_PENDING)) { + return Connection.STATE_INITIALIZING; + } else if (status.equals(STATUS_DIALING_IN)) { + return Connection.STATE_RINGING; + } else if (status.equals(STATUS_ALERTING) || + status.equals(STATUS_DIALING_OUT)) { + return Connection.STATE_DIALING; + } else if (status.equals(STATUS_ON_HOLD)) { + return Connection.STATE_HOLDING; + } else if (status.equals(STATUS_CONNECTED) || + status.equals(STATUS_MUTED_VIA_FOCUS) || + status.equals(STATUS_DISCONNECTING)) { + return Connection.STATE_ACTIVE; + } else if (status.equals(STATUS_DISCONNECTED)) { + return Connection.STATE_DISCONNECTED; + } + return Call.STATE_ACTIVE; + } } diff --git a/telephony/java/com/android/ims/internal/IImsCallSession.aidl b/telephony/java/com/android/ims/internal/IImsCallSession.aidl index 98b2d8a9d0bb..16b0cd5e1c95 100644 --- a/telephony/java/com/android/ims/internal/IImsCallSession.aidl +++ b/telephony/java/com/android/ims/internal/IImsCallSession.aidl @@ -160,10 +160,13 @@ interface IImsCallSession { void resume(in ImsStreamMediaProfile profile); /** - * Merges the active & hold call. When it succeeds, {@link Listener#callSessionMerged} - * is called. + * Merges the active & hold call. When the merge starts, + * {@link Listener#callSessionMergeStarted} is called. + * {@link Listener#callSessionMergeComplete} is called if the merge is successful, and + * {@link Listener#callSessionMergeFailed} is called if the merge fails. * - * @see Listener#callSessionMerged, Listener#callSessionMergeFailed + * @see Listener#callSessionMergeStarted, Listener#callSessionMergeComplete, + * Listener#callSessionMergeFailed */ void merge(); @@ -225,4 +228,10 @@ interface IImsCallSession { * intermediates between the propriety implementation and Telecomm/InCall. */ IImsVideoCallProvider getVideoCallProvider(); + + /** + * Determines if the current session is multiparty. + * @return {@code True} if the session is multiparty. + */ + boolean isMultiparty(); } diff --git a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl index acd1eb9d592e..84d1c54575f8 100644 --- a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl +++ b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl @@ -48,10 +48,11 @@ interface IImsCallSessionListener { void callSessionResumeReceived(in IImsCallSession session, in ImsCallProfile profile); /** - * Notifiies the result of call merge operation. + * Notifies the result of call merge operation. */ - void callSessionMerged(in IImsCallSession session, + void callSessionMergeStarted(in IImsCallSession session, in IImsCallSession newSession, in ImsCallProfile profile); + void callSessionMergeComplete(in IImsCallSession session); void callSessionMergeFailed(in IImsCallSession session, in ImsReasonInfo reasonInfo); @@ -104,4 +105,14 @@ interface IImsCallSessionListener { in int srcAccessTech, in int targetAccessTech, in ImsReasonInfo reasonInfo); void callSessionHandoverFailed(in IImsCallSession session, in int srcAccessTech, in int targetAccessTech, in ImsReasonInfo reasonInfo); + + /** + * Notifies the TTY mode change by remote party. + * @param mode one of the following: + * - {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} + * - {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} + * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} + * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO} + */ + void callSessionTtyModeReceived(in IImsCallSession session, in int mode); } diff --git a/telephony/java/com/android/ims/internal/IImsConfig.aidl b/telephony/java/com/android/ims/internal/IImsConfig.aidl index e8d921e7153e..c5ccf5f0e5d0 100644 --- a/telephony/java/com/android/ims/internal/IImsConfig.aidl +++ b/telephony/java/com/android/ims/internal/IImsConfig.aidl @@ -73,9 +73,9 @@ interface IImsConfig { * * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. * @param value in Integer format. - * @return void. + * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants. */ - void setProvisionedValue(int item, int value); + int setProvisionedValue(int item, int value); /** * Sets the value for IMS service/capabilities parameters by the operator device @@ -84,9 +84,9 @@ interface IImsConfig { * * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. * @param value in String format. - * @return void. + * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants. */ - void setProvisionedStringValue(int item, String value); + int setProvisionedStringValue(int item, String value); /** * Gets the value of the specified IMS feature item for specified network type. diff --git a/telephony/java/com/android/ims/internal/IImsService.aidl b/telephony/java/com/android/ims/internal/IImsService.aidl index 5138305f5d8f..b9cee42927a2 100644 --- a/telephony/java/com/android/ims/internal/IImsService.aidl +++ b/telephony/java/com/android/ims/internal/IImsService.aidl @@ -26,6 +26,8 @@ import com.android.ims.internal.IImsEcbm; import com.android.ims.internal.IImsUt; import com.android.ims.internal.IImsConfig; +import android.os.Message; + /** * {@hide} */ @@ -64,10 +66,13 @@ interface IImsService { */ void turnOffIms(); - /** * ECBM interface for Emergency Callback mode mechanism. */ IImsEcbm getEcbmInterface(int serviceId); + /** + * Used to set current TTY Mode. + */ + void setUiTTYMode(int serviceId, int uiTtyMode, in Message onComplete); } diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java index 88e5bd60b32c..5cd5d4e8f97d 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfo.java +++ b/telephony/java/com/android/internal/telephony/CallerInfo.java @@ -301,7 +301,7 @@ public class CallerInfo { public static CallerInfo getCallerInfo(Context context, String number) { if (VDBG) Rlog.v(TAG, "getCallerInfo() based on number..."); - long subId = SubscriptionManager.getDefaultSubId(); + int subId = SubscriptionManager.getDefaultSubId(); return getCallerInfo(context, number, subId); } @@ -316,7 +316,7 @@ public class CallerInfo { * a matching number is not found, then a generic caller info is returned, * with all relevant fields empty or null. */ - public static CallerInfo getCallerInfo(Context context, String number, long subId) { + public static CallerInfo getCallerInfo(Context context, String number, int subId) { if (TextUtils.isEmpty(number)) { return null; @@ -418,12 +418,12 @@ public class CallerInfo { // string in the phone number field. /* package */ CallerInfo markAsVoiceMail() { - long subId = SubscriptionManager.getDefaultSubId(); + int subId = SubscriptionManager.getDefaultSubId(); return markAsVoiceMail(subId); } - /* package */ CallerInfo markAsVoiceMail(long subId) { + /* package */ CallerInfo markAsVoiceMail(int subId) { mIsVoiceMail = true; try { diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java index 0d183896b5bf..aae7617eabe9 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java +++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java @@ -81,7 +81,7 @@ public class CallerInfoAsyncQuery { public int event; public String number; - public long subId; + public int subId; } @@ -388,7 +388,7 @@ public class CallerInfoAsyncQuery { public static CallerInfoAsyncQuery startQuery(int token, Context context, String number, OnQueryCompleteListener listener, Object cookie) { - long subId = SubscriptionManager.getDefaultSubId(); + int subId = SubscriptionManager.getDefaultSubId(); return startQuery(token, context, number, listener, cookie, subId); } @@ -404,7 +404,7 @@ public class CallerInfoAsyncQuery { * the phone type of the incoming connection. */ public static CallerInfoAsyncQuery startQuery(int token, Context context, String number, - OnQueryCompleteListener listener, Object cookie, long subId) { + OnQueryCompleteListener listener, Object cookie, int subId) { if (DBG) { Rlog.d(LOG_TAG, "##### CallerInfoAsyncQuery startQuery()... #####"); diff --git a/telephony/java/com/android/internal/telephony/DcParamObject.java b/telephony/java/com/android/internal/telephony/DcParamObject.java index c92988f906e4..139939cbd0c1 100644 --- a/telephony/java/com/android/internal/telephony/DcParamObject.java +++ b/telephony/java/com/android/internal/telephony/DcParamObject.java @@ -21,9 +21,9 @@ import android.os.Parcel; public class DcParamObject implements Parcelable { - private long mSubId; + private int mSubId; - public DcParamObject(long subId) { + public DcParamObject(int subId) { mSubId = subId; } @@ -40,7 +40,7 @@ public class DcParamObject implements Parcelable { } private void readFromParcel(Parcel in) { - mSubId = in.readLong(); + mSubId = in.readInt(); } public static final Parcelable.Creator<DcParamObject> CREATOR = new Parcelable.Creator<DcParamObject>() { @@ -52,7 +52,7 @@ public class DcParamObject implements Parcelable { } }; - public long getSubId() { + public int getSubId() { return mSubId; } } diff --git a/telephony/java/com/android/internal/telephony/IMms.aidl b/telephony/java/com/android/internal/telephony/IMms.aidl index ebfefd199497..032249957527 100644 --- a/telephony/java/com/android/internal/telephony/IMms.aidl +++ b/telephony/java/com/android/internal/telephony/IMms.aidl @@ -39,7 +39,7 @@ interface IMms { * @param sentIntent if not NULL this <code>PendingIntent</code> is * broadcast when the message is successfully sent, or failed */ - void sendMessage(long subId, String callingPkg, in Uri contentUri, + void sendMessage(int subId, String callingPkg, in Uri contentUri, String locationUrl, in Bundle configOverrides, in PendingIntent sentIntent); /** @@ -56,7 +56,7 @@ interface IMms { * @param downloadedIntent if not NULL this <code>PendingIntent</code> is * broadcast when the message is downloaded, or the download is failed */ - void downloadMessage(long subId, String callingPkg, String locationUrl, + void downloadMessage(int subId, String callingPkg, String locationUrl, in Uri contentUri, in Bundle configOverrides, in PendingIntent downloadedIntent); @@ -99,7 +99,7 @@ interface IMms { * * @param subId the SIM id */ - Bundle getCarrierConfigValues(long subId); + Bundle getCarrierConfigValues(int subId); /** * Import a text message into system's SMS store @@ -204,7 +204,7 @@ interface IMms { * @param sentIntent if not NULL this <code>PendingIntent</code> is * broadcast when the message is successfully sent, or failed */ - void sendStoredMessage(long subId, String callingPkg, in Uri messageUri, + void sendStoredMessage(int subId, String callingPkg, in Uri messageUri, in Bundle configOverrides, in PendingIntent sentIntent); /** diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl index d7062034c6c6..eec533383107 100644 --- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl +++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl @@ -27,16 +27,21 @@ interface IPhoneSubInfo { */ String getDeviceId(); + /** + * Retrieves the unique Network Access ID + */ + String getNaiForSubscriber(int subId); + /** * Retrieves the unique device ID of a subId for the device, e.g., IMEI * for GSM phones. */ - String getDeviceIdForSubscriber(long subId); + String getDeviceIdForSubscriber(int subId); /** * Retrieves the IMEI. */ - String getImeiForSubscriber(long subId); + String getImeiForSubscriber(int subId); /** * Retrieves the software version number for the device, e.g., IMEI/SV @@ -48,7 +53,7 @@ interface IPhoneSubInfo { * Retrieves the software version number of a subId for the device, e.g., IMEI/SV * for GSM phones. */ - String getDeviceSvnUsingSubId(long subId); + String getDeviceSvnUsingSubId(int subId); /** * Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones. @@ -58,7 +63,7 @@ interface IPhoneSubInfo { /** * Retrieves the unique subscriber ID of a given subId, e.g., IMSI for GSM phones. */ - String getSubscriberIdForSubscriber(long subId); + String getSubscriberIdForSubscriber(int subId); /** * Retrieves the Group Identifier Level1 for GSM phones. @@ -68,7 +73,7 @@ interface IPhoneSubInfo { /** * Retrieves the Group Identifier Level1 for GSM phones of a subId. */ - String getGroupIdLevel1ForSubscriber(long subId); + String getGroupIdLevel1ForSubscriber(int subId); /** * Retrieves the serial number of the ICC, if applicable. @@ -78,7 +83,7 @@ interface IPhoneSubInfo { /** * Retrieves the serial number of a given subId. */ - String getIccSerialNumberForSubscriber(long subId); + String getIccSerialNumberForSubscriber(int subId); /** * Retrieves the phone number string for line 1. @@ -88,7 +93,7 @@ interface IPhoneSubInfo { /** * Retrieves the phone number string for line 1 of a subcription. */ - String getLine1NumberForSubscriber(long subId); + String getLine1NumberForSubscriber(int subId); /** @@ -99,7 +104,7 @@ interface IPhoneSubInfo { /** * Retrieves the alpha identifier for line 1 of a subId. */ - String getLine1AlphaTagForSubscriber(long subId); + String getLine1AlphaTagForSubscriber(int subId); /** @@ -110,7 +115,7 @@ interface IPhoneSubInfo { /** * Retrieves the Msisdn of a subId. */ - String getMsisdnForSubscriber(long subId); + String getMsisdnForSubscriber(int subId); /** * Retrieves the voice mail number. @@ -120,7 +125,7 @@ interface IPhoneSubInfo { /** * Retrieves the voice mail number of a given subId. */ - String getVoiceMailNumberForSubscriber(long subId); + String getVoiceMailNumberForSubscriber(int subId); /** * Retrieves the complete voice mail number. @@ -130,7 +135,7 @@ interface IPhoneSubInfo { /** * Retrieves the complete voice mail number for particular subId */ - String getCompleteVoiceMailNumberForSubscriber(long subId); + String getCompleteVoiceMailNumberForSubscriber(int subId); /** * Retrieves the alpha identifier associated with the voice mail number. @@ -141,7 +146,7 @@ interface IPhoneSubInfo { * Retrieves the alpha identifier associated with the voice mail number * of a subId. */ - String getVoiceMailAlphaTagForSubscriber(long subId); + String getVoiceMailAlphaTagForSubscriber(int subId); /** * Returns the IMS private user identity (IMPI) that was loaded from the ISIM. @@ -194,5 +199,5 @@ interface IPhoneSubInfo { * @param data authentication challenge data * @return challenge response */ - String getIccSimChallengeResponse(long subId, int appType, String data); + String getIccSimChallengeResponse(int subId, int appType, String data); } diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl index 32bb8b491849..560af450d326 100644 --- a/telephony/java/com/android/internal/telephony/ISms.aidl +++ b/telephony/java/com/android/internal/telephony/ISms.aidl @@ -47,7 +47,7 @@ interface ISms { * @param subId the subId id. * @return list of SmsRawData of all sms on ICC */ - List<SmsRawData> getAllMessagesFromIccEfForSubscriber(in long subId, String callingPkg); + List<SmsRawData> getAllMessagesFromIccEfForSubscriber(in int subId, String callingPkg); /** * Update the specified message on the ICC. @@ -75,7 +75,7 @@ interface ISms { * @return success or not * */ - boolean updateMessageOnIccEfForSubscriber(in long subId, String callingPkg, + boolean updateMessageOnIccEfForSubscriber(in int subId, String callingPkg, int messageIndex, int newStatus, in byte[] pdu); /** @@ -99,7 +99,7 @@ interface ISms { * @return success or not * */ - boolean copyMessageToIccEfForSubscriber(in long subId, String callingPkg, int status, + boolean copyMessageToIccEfForSubscriber(in int subId, String callingPkg, int status, in byte[] pdu, in byte[] smsc); /** @@ -152,7 +152,7 @@ interface ISms { * raw pdu of the status report is in the extended data ("pdu"). * @param subId the subId id. */ - void sendDataForSubscriber(long subId, String callingPkg, in String destAddr, + void sendDataForSubscriber(int subId, String callingPkg, in String destAddr, in String scAddr, in int destPort, in byte[] data, in PendingIntent sentIntent, in PendingIntent deliveryIntent); @@ -206,7 +206,7 @@ interface ISms { * raw pdu of the status report is in the extended data ("pdu"). * @param subId the subId on which the SMS has to be sent. */ - void sendTextForSubscriber(in long subId, String callingPkg, in String destAddr, + void sendTextForSubscriber(in int subId, String callingPkg, in String destAddr, in String scAddr, in String text, in PendingIntent sentIntent, in PendingIntent deliveryIntent); @@ -283,7 +283,7 @@ interface ISms { * extended data ("pdu"). * @param subId the subId on which the SMS has to be sent. */ - void sendMultipartTextForSubscriber(in long subId, String callingPkg, + void sendMultipartTextForSubscriber(in int subId, String callingPkg, in String destinationAddress, in String scAddress, in List<String> parts, in List<PendingIntent> sentIntents, in List<PendingIntent> deliveryIntents); @@ -315,7 +315,7 @@ interface ISms { * * @see #disableCellBroadcast(int) */ - boolean enableCellBroadcastForSubscriber(in long subId, int messageIdentifier); + boolean enableCellBroadcastForSubscriber(in int subId, int messageIdentifier); /** * Disable reception of cell broadcast (SMS-CB) messages with the given @@ -344,7 +344,7 @@ interface ISms { * * @see #enableCellBroadcast(int) */ - boolean disableCellBroadcastForSubscriber(in long subId, int messageIdentifier); + boolean disableCellBroadcastForSubscriber(in int subId, int messageIdentifier); /* * Enable reception of cell broadcast (SMS-CB) messages with the given @@ -377,7 +377,7 @@ interface ISms { * * @see #disableCellBroadcastRange(int, int) */ - boolean enableCellBroadcastRangeForSubscriber(long subId, int startMessageId, int endMessageId); + boolean enableCellBroadcastRangeForSubscriber(int subId, int startMessageId, int endMessageId); /** * Disable reception of cell broadcast (SMS-CB) messages with the given @@ -410,7 +410,7 @@ interface ISms { * * @see #enableCellBroadcastRange(int, int, int) */ - boolean disableCellBroadcastRangeForSubscriber(long subId, int startMessageId, + boolean disableCellBroadcastRangeForSubscriber(int subId, int startMessageId, int endMessageId); /** @@ -423,7 +423,7 @@ interface ISms { * Returns the premium SMS send permission for the specified package. * Requires system permission. */ - int getPremiumSmsPermissionForSubscriber(long subId, String packageName); + int getPremiumSmsPermissionForSubscriber(int subId, String packageName); /** * Set the SMS send permission for the specified package. @@ -439,7 +439,7 @@ interface ISms { * Set the SMS send permission for the specified package. * Requires system permission. */ - void setPremiumSmsPermissionForSubscriber(long subId, String packageName, int permission); + void setPremiumSmsPermissionForSubscriber(int subId, String packageName, int permission); /** * SMS over IMS is supported if IMS is registered and SMS is supported @@ -459,13 +459,13 @@ interface ISms { * * @see #getImsSmsFormat() */ - boolean isImsSmsSupportedForSubscriber(long subId); + boolean isImsSmsSupportedForSubscriber(int subId); /* * get user prefered SMS subId * @return subId id */ - long getPreferredSmsSubscription(); + int getPreferredSmsSubscription(); /** * Gets SMS format supported on IMS. SMS over IMS format is @@ -489,7 +489,7 @@ interface ISms { * * @see #isImsSmsSupported() */ - String getImsSmsFormatForSubscriber(long subId); + String getImsSmsFormatForSubscriber(int subId); /* * Get SMS prompt property, enabled or not @@ -524,7 +524,7 @@ interface ISms { * broadcast when the message is delivered to the recipient. The * raw pdu of the status report is in the extended data ("pdu"). */ - void sendStoredText(long subId, String callingPkg, in Uri messageUri, String scAddress, + void sendStoredText(int subId, String callingPkg, in Uri messageUri, String scAddress, in PendingIntent sentIntent, in PendingIntent deliveryIntent); /** @@ -560,7 +560,7 @@ interface ISms { * to the recipient. The raw pdu of the status report is in the * extended data ("pdu"). */ - void sendStoredMultipartText(long subId, String callingPkg, in Uri messageUri, + void sendStoredMultipartText(int subId, String callingPkg, in Uri messageUri, String scAddress, in List<PendingIntent> sentIntents, in List<PendingIntent> deliveryIntents); } diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl index b87365e2bd64..daf850ecc9c1 100755 --- a/telephony/java/com/android/internal/telephony/ISub.aidl +++ b/telephony/java/com/android/internal/telephony/ISub.aidl @@ -25,7 +25,7 @@ interface ISub { * @param subId The unique SubInfoRecord index in database * @return SubInfoRecord, maybe null */ - SubInfoRecord getSubInfoForSubscriber(long subId); + SubInfoRecord getSubInfoForSubscriber(int subId); /** * Get the SubInfoRecord according to an IccId @@ -79,7 +79,7 @@ interface ISub { * @param subId the unique SubInfoRecord index in database * @return the number of records updated */ - int setColor(int color, long subId); + int setColor(int color, int subId); /** * Set display name by simInfo index @@ -87,7 +87,7 @@ interface ISub { * @param subId the unique SubInfoRecord index in database * @return the number of records updated */ - int setDisplayName(String displayName, long subId); + int setDisplayName(String displayName, int subId); /** * Set display name by simInfo index with name source @@ -96,7 +96,7 @@ interface ISub { * @param nameSource, 0: DEFAULT_SOURCE, 1: SIM_SOURCE, 2: USER_INPUT * @return the number of records updated */ - int setDisplayNameUsingSrc(String displayName, long subId, long nameSource); + int setDisplayNameUsingSrc(String displayName, int subId, long nameSource); /** * Set phone number by subId @@ -104,7 +104,7 @@ interface ISub { * @param subId the unique SubInfoRecord index in database * @return the number of records updated */ - int setDisplayNumber(String number, long subId); + int setDisplayNumber(String number, int subId); /** * Set number display format. 0: none, 1: the first four digits, 2: the last four digits @@ -112,7 +112,7 @@ interface ISub { * @param subId the unique SubInfoRecord index in database * @return the number of records updated */ - int setDisplayNumberFormat(int format, long subId); + int setDisplayNumberFormat(int format, int subId); /** * Set data roaming by simInfo index @@ -120,35 +120,35 @@ interface ISub { * @param subId the unique SubInfoRecord index in database * @return the number of records updated */ - int setDataRoaming(int roaming, long subId); + int setDataRoaming(int roaming, int subId); - int getSlotId(long subId); + int getSlotId(int subId); - long[] getSubId(int slotId); + int[] getSubId(int slotId); - long getDefaultSubId(); + int getDefaultSubId(); int clearSubInfo(); - int getPhoneId(long subId); + int getPhoneId(int subId); /** * Get the default data subscription * @return Id of the data subscription */ - long getDefaultDataSubId(); + int getDefaultDataSubId(); - void setDefaultDataSubId(long subId); + void setDefaultDataSubId(int subId); - long getDefaultVoiceSubId(); + int getDefaultVoiceSubId(); - void setDefaultVoiceSubId(long subId); + void setDefaultVoiceSubId(int subId); - long getDefaultSmsSubId(); + int getDefaultSmsSubId(); - void setDefaultSmsSubId(long subId); + void setDefaultSmsSubId(int subId); void clearDefaultsForInactiveSubIds(); - long[] getActiveSubIdList(); + int[] getActiveSubIdList(); } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 58807b26652f..13f0e3f32b23 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -28,7 +28,7 @@ import java.util.List; /** * Interface used to interact with the phone. Mostly this is used by the * TelephonyManager class. A few places are still using this directly. - * Please clean them up if possible and use TelephonyManager insteadl. + * Please clean them up if possible and use TelephonyManager instead. * * {@hide} */ @@ -60,7 +60,7 @@ interface ITelephony { * @param subId user preferred subId. * @return whether it hung up */ - boolean endCallForSubscriber(long subId); + boolean endCallForSubscriber(int subId); /** * Answer the currently-ringing call. @@ -94,7 +94,7 @@ interface ITelephony { * TODO: this should be a oneway call (especially since it's called * directly from the key queue thread). */ - void answerRingingCallForSubscriber(long subId); + void answerRingingCallForSubscriber(int subId); /** * Silence the ringer if an incoming call is currently ringing. @@ -121,7 +121,7 @@ interface ITelephony { * @param subId user preferred subId. * @return true if the phone state is OFFHOOK. */ - boolean isOffhookForSubscriber(long subId); + boolean isOffhookForSubscriber(int subId); /** * Check if an incoming phone call is ringing or call waiting @@ -130,7 +130,7 @@ interface ITelephony { * @param subId user preferred subId. * @return true if the phone state is RINGING. */ - boolean isRingingForSubscriber(long subId); + boolean isRingingForSubscriber(int subId); /** * Check if an incoming phone call is ringing or call waiting. @@ -150,7 +150,7 @@ interface ITelephony { * @param subId user preferred subId. * @return true if the phone state is IDLE. */ - boolean isIdleForSubscriber(long subId); + boolean isIdleForSubscriber(int subId); /** * Check to see if the radio is on or not. @@ -163,7 +163,7 @@ interface ITelephony { * @param subId user preferred subId. * @return returns true if the radio is on. */ - boolean isRadioOnForSubscriber(long subId); + boolean isRadioOnForSubscriber(int subId); /** * Check if the SIM pin lock is enabled. @@ -185,7 +185,7 @@ interface ITelephony { * @param subId user preferred subId. * @return whether the operation was a success. */ - boolean supplyPinForSubscriber(long subId, String pin); + boolean supplyPinForSubscriber(int subId, String pin); /** * Supply puk to unlock the SIM and set SIM pin to new pin. @@ -204,7 +204,7 @@ interface ITelephony { * @param subId user preferred subId. * @return whether the operation was a success. */ - boolean supplyPukForSubscriber(long subId, String puk, String pin); + boolean supplyPukForSubscriber(int subId, String puk, String pin); /** * Supply a pin to unlock the SIM. Blocks until a result is determined. @@ -222,7 +222,7 @@ interface ITelephony { * @return retValue[0] = Phone.PIN_RESULT_SUCCESS on success. Otherwise error code * retValue[1] = number of attempts remaining if known otherwise -1 */ - int[] supplyPinReportResultForSubscriber(long subId, String pin); + int[] supplyPinReportResultForSubscriber(int subId, String pin); /** * Supply puk to unlock the SIM and set SIM pin to new pin. @@ -244,7 +244,7 @@ interface ITelephony { * @return retValue[0] = Phone.PIN_RESULT_SUCCESS on success. Otherwise error code * retValue[1] = number of attempts remaining if known otherwise -1 */ - int[] supplyPukReportResultForSubscriber(long subId, String puk, String pin); + int[] supplyPukReportResultForSubscriber(int subId, String puk, String pin); /** * Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated @@ -263,7 +263,7 @@ interface ITelephony { * @param subId user preferred subId. * @return true if MMI command is executed. */ - boolean handlePinMmiForSubscriber(long subId, String dialString); + boolean handlePinMmiForSubscriber(int subId, String dialString); /** * Toggles the radio on or off. @@ -274,7 +274,7 @@ interface ITelephony { * Toggles the radio on or off on particular subId. * @param subId user preferred subId. */ - void toggleRadioOnOffForSubscriber(long subId); + void toggleRadioOnOffForSubscriber(int subId); /** * Set the radio to on or off @@ -285,7 +285,7 @@ interface ITelephony { * Set the radio to on or off on particular subId. * @param subId user preferred subId. */ - boolean setRadioForSubscriber(long subId, boolean turnOn); + boolean setRadioForSubscriber(int subId, boolean turnOn); /** * Set the radio to on or off unconditionally @@ -301,7 +301,7 @@ interface ITelephony { * Request to update location information for a subscrition in service state * @param subId user preferred subId. */ - void updateServiceLocationForSubscriber(long subId); + void updateServiceLocationForSubscriber(int subId); /** * Enable location update notifications. @@ -312,7 +312,7 @@ interface ITelephony { * Enable location update notifications. * @param subId user preferred subId. */ - void enableLocationUpdatesForSubscriber(long subId); + void enableLocationUpdatesForSubscriber(int subId); /** * Disable location update notifications. @@ -323,7 +323,7 @@ interface ITelephony { * Disable location update notifications. * @param subId user preferred subId. */ - void disableLocationUpdatesForSubscriber(long subId); + void disableLocationUpdatesForSubscriber(int subId); /** * Allow mobile data connections. @@ -352,7 +352,7 @@ interface ITelephony { /** * Returns the call state for a subId. */ - int getCallStateForSubscriber(long subId); + int getCallStateForSubscriber(int subId); int getDataActivity(); int getDataState(); @@ -370,7 +370,7 @@ interface ITelephony { * and TelephonyManager.PHONE_TYPE_GSM if RILConstants.GSM_PHONE * @param subId user preferred subId. */ - int getActivePhoneTypeForSubscriber(long subId); + int getActivePhoneTypeForSubscriber(int subId); /** * Returns the CDMA ERI icon index to display @@ -381,7 +381,7 @@ interface ITelephony { * Returns the CDMA ERI icon index to display on particular subId. * @param subId user preferred subId. */ - int getCdmaEriIconIndexForSubscriber(long subId); + int getCdmaEriIconIndexForSubscriber(int subId); /** * Returns the CDMA ERI icon mode, @@ -396,7 +396,7 @@ interface ITelephony { * 1 - FLASHING * @param subId user preferred subId. */ - int getCdmaEriIconModeForSubscriber(long subId); + int getCdmaEriIconModeForSubscriber(int subId); /** * Returns the CDMA ERI text, @@ -407,7 +407,7 @@ interface ITelephony { * Returns the CDMA ERI text for particular subId, * @param subId user preferred subId. */ - String getCdmaEriTextForSubscriber(long subId); + String getCdmaEriTextForSubscriber(int subId); /** * Returns true if OTA service provisioning needs to run. @@ -426,7 +426,7 @@ interface ITelephony { * @param subId user preferred subId. * Returns the unread count of voicemails */ - int getVoiceMessageCountForSubscriber(long subId); + int getVoiceMessageCountForSubscriber(int subId); /** * Returns the network type for data transmission @@ -438,7 +438,7 @@ interface ITelephony { * @param subId user preferred subId. * Returns the network type */ - int getNetworkTypeForSubscriber(long subId); + int getNetworkTypeForSubscriber(int subId); /** * Returns the network type for data transmission @@ -450,7 +450,7 @@ interface ITelephony { * @param subId user preferred subId. * Returns the network type */ - int getDataNetworkTypeForSubscriber(long subId); + int getDataNetworkTypeForSubscriber(int subId); /** * Returns the network type for voice @@ -462,7 +462,7 @@ interface ITelephony { * @param subId user preferred subId. * Returns the network type */ - int getVoiceNetworkTypeForSubscriber(long subId); + int getVoiceNetworkTypeForSubscriber(int subId); /** * Return true if an ICC card is present @@ -474,7 +474,7 @@ interface ITelephony { * @param slotId user preferred slotId. * Return true if an ICC card is present */ - boolean hasIccCardUsingSlotId(long slotId); + boolean hasIccCardUsingSlotId(int slotId); /** * Return if the current radio is LTE on CDMA. This @@ -494,7 +494,7 @@ interface ITelephony { * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE} * or {@link PHone#LTE_ON_CDMA_TRUE} */ - int getLteOnCdmaModeForSubscriber(long subId); + int getLteOnCdmaModeForSubscriber(int subId); /** * Returns the all observed cell information of the device. @@ -689,13 +689,13 @@ interface ITelephony { * Return MDN string for CDMA phone. * @param subId user preferred subId. */ - String getCdmaMdn(long subId); + String getCdmaMdn(int subId); /** * Return MIN string for CDMA phone. * @param subId user preferred subId. */ - String getCdmaMin(long subId); + String getCdmaMin(int subId); /** * Has the calling application been granted special privileges by the carrier. @@ -733,7 +733,7 @@ interface ITelephony { * @param subId for which the simplified UI should be enabled or disabled. * @param enable true means enabling the simplified UI. */ - void enableSimplifiedNetworkSettingsForSubscriber(long subId, boolean enable); + void enableSimplifiedNetworkSettingsForSubscriber(int subId, boolean enable); /** * Get whether a simplified Mobile Network Settings UI is enabled for the @@ -742,7 +742,7 @@ interface ITelephony { * @param subId for which the simplified UI should be enabled or disabled. * @return true if the simplified UI is enabled. */ - boolean getSimplifiedNetworkSettingsEnabledForSubscriber(long subId); + boolean getSimplifiedNetworkSettingsEnabledForSubscriber(int subId); /** * Set the line 1 phone number string and its alphatag for the current ICCID @@ -754,7 +754,7 @@ interface ITelephony { * @param alphaTag alpha-tagging of the dailing nubmer * @param number The dialing number */ - void setLine1NumberForDisplayForSubscriber(long subId, String alphaTag, String number); + void setLine1NumberForDisplayForSubscriber(int subId, String alphaTag, String number); /** * Returns the displayed dialing number string if it was set previously via @@ -763,7 +763,7 @@ interface ITelephony { * @param subId whose dialing number for line 1 is returned. * @return the displayed dialing number if set, or null if not set. */ - String getLine1NumberForDisplay(long subId); + String getLine1NumberForDisplay(int subId); /** * Returns the displayed alphatag of the dialing number if it was set @@ -773,7 +773,7 @@ interface ITelephony { * @return the displayed alphatag of the dialing number if set, or null if * not set. */ - String getLine1AlphaTagForDisplay(long subId); + String getLine1AlphaTagForDisplay(int subId); /** * Override the operator branding for the current ICCID. @@ -831,4 +831,18 @@ interface ITelephony { * @return phone radio type and access technology */ int getRadioAccessFamily(in int phoneId); + + /** + * Enables or disables video calling. + * + * @param enable Whether to enable video calling. + */ + void enableVideoCalling(boolean enable); + + /** + * Whether video calling has been enabled by the user. + * + * @return {@code True} if the user has enabled video calling, {@code false} otherwise. + */ + boolean isVideoCallingEnabled(); } diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl index 39defcf44e85..ee3f8b0f3f68 100644 --- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -30,28 +30,28 @@ import com.android.internal.telephony.IPhoneStateListener; interface ITelephonyRegistry { void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow); - void listenForSubscriber(in long subId, String pkg, IPhoneStateListener callback, int events, + void listenForSubscriber(in int subId, String pkg, IPhoneStateListener callback, int events, boolean notifyNow); void notifyCallState(int state, String incomingNumber); - void notifyCallStateForSubscriber(in long subId, int state, String incomingNumber); - void notifyServiceStateForPhoneId(in int phoneId, in long subId, in ServiceState state); + void notifyCallStateForSubscriber(in int subId, int state, String incomingNumber); + void notifyServiceStateForPhoneId(in int phoneId, in int subId, in ServiceState state); void notifySignalStrength(in SignalStrength signalStrength); - void notifySignalStrengthForSubscriber(in long subId, in SignalStrength signalStrength); - void notifyMessageWaitingChangedForPhoneId(in int phoneId, in long subId, in boolean mwi); + void notifySignalStrengthForSubscriber(in int subId, in SignalStrength signalStrength); + void notifyMessageWaitingChangedForPhoneId(in int phoneId, in int subId, in boolean mwi); void notifyCallForwardingChanged(boolean cfi); - void notifyCallForwardingChangedForSubscriber(in long subId, boolean cfi); + void notifyCallForwardingChangedForSubscriber(in int subId, boolean cfi); void notifyDataActivity(int state); - void notifyDataActivityForSubscriber(in long subId, int state); + void notifyDataActivityForSubscriber(in int subId, int state); void notifyDataConnection(int state, boolean isDataConnectivityPossible, String reason, String apn, String apnType, in LinkProperties linkProperties, in NetworkCapabilities networkCapabilities, int networkType, boolean roaming); - void notifyDataConnectionForSubscriber(long subId, int state, boolean isDataConnectivityPossible, + void notifyDataConnectionForSubscriber(int subId, int state, boolean isDataConnectivityPossible, String reason, String apn, String apnType, in LinkProperties linkProperties, in NetworkCapabilities networkCapabilities, int networkType, boolean roaming); void notifyDataConnectionFailed(String reason, String apnType); - void notifyDataConnectionFailedForSubscriber(long subId, String reason, String apnType); + void notifyDataConnectionFailedForSubscriber(int subId, String reason, String apnType); void notifyCellLocation(in Bundle cellLocation); - void notifyCellLocationForSubscriber(in long subId, in Bundle cellLocation); + void notifyCellLocationForSubscriber(in int subId, in Bundle cellLocation); void notifyOtaspChanged(in int otaspMode); void notifyCellInfo(in List<CellInfo> cellInfo); void notifyPreciseCallState(int ringingCallState, int foregroundCallState, @@ -59,8 +59,8 @@ interface ITelephonyRegistry { void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause); void notifyPreciseDataConnectionFailed(String reason, String apnType, String apn, String failCause); - void notifyCellInfoForSubscriber(in long subId, in List<CellInfo> cellInfo); + void notifyCellInfoForSubscriber(in int subId, in List<CellInfo> cellInfo); void notifyDataConnectionRealTimeInfo(in DataConnectionRealTimeInfo dcRtInfo); void notifyVoLteServiceStateChanged(in VoLteServiceState lteState); - void notifyOemHookRawEventForSubscriber(in long subId, in byte[] rawData); + void notifyOemHookRawEventForSubscriber(in int subId, in byte[] rawData); } diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index d093a29d1a05..b5e82e399758 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -161,6 +161,7 @@ cat include/telephony/ril.h | \ public static final int DATA_PROFILE_FOTA = 3; public static final int DATA_PROFILE_CBS = 4; public static final int DATA_PROFILE_OEM_BASE = 1000; + public static final int DATA_PROFILE_INVALID = 0xFFFFFFFF; int RIL_REQUEST_GET_SIM_STATUS = 1; int RIL_REQUEST_ENTER_SIM_PIN = 2; diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java index afe1d5dba9e9..7531d7b846ed 100644 --- a/test-runner/src/android/test/mock/MockPackageManager.java +++ b/test-runner/src/android/test/mock/MockPackageManager.java @@ -733,6 +733,14 @@ public class MockPackageManager extends PackageManager { * @hide */ @Override + public boolean isUpgrade() { + throw new UnsupportedOperationException(); + } + + /** + * @hide + */ + @Override public void installPackage(Uri packageURI, PackageInstallObserver observer, int flags, String installerPackageName) { throw new UnsupportedOperationException(); @@ -793,4 +801,11 @@ public class MockPackageManager extends PackageManager { public Drawable loadItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) { throw new UnsupportedOperationException(); } + + /** + * @hide + */ + public Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) { + throw new UnsupportedOperationException(); + } } diff --git a/tests/VectorDrawableTest/AndroidManifest.xml b/tests/VectorDrawableTest/AndroidManifest.xml index 7796953b4b25..991ec5718b32 100644 --- a/tests/VectorDrawableTest/AndroidManifest.xml +++ b/tests/VectorDrawableTest/AndroidManifest.xml @@ -18,7 +18,7 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.test.dynamic" > - <uses-sdk android:minSdkVersion="20" /> + <uses-sdk android:minSdkVersion="21" /> <application android:hardwareAccelerated="true" diff --git a/tests/VectorDrawableTest/res/anim/alpha_animation_progress_bar.xml b/tests/VectorDrawableTest/res/anim/alpha_animation_progress_bar.xml new file mode 100644 index 000000000000..867abc7744a1 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/alpha_animation_progress_bar.xml @@ -0,0 +1,24 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<set xmlns:android="http://schemas.android.com/apk/res/android" > + + <objectAnimator + android:duration="1350" + android:propertyName="alpha" + android:valueFrom="1" + android:valueTo="0.2" /> + +</set>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/anim/ic_bluethooth_v2_animation_dot_left.xml b/tests/VectorDrawableTest/res/anim/ic_bluethooth_v2_animation_dot_left.xml new file mode 100644 index 000000000000..b465ead3fe86 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_bluethooth_v2_animation_dot_left.xml @@ -0,0 +1,61 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="scaleX" + android:valueFrom="1" + android:valueTo="1" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="350" + android:propertyName="scaleX" + android:valueFrom="1" + android:valueTo="0" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="scaleY" + android:valueFrom="1" + android:valueTo="1" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="350" + android:propertyName="scaleY" + android:valueFrom="1" + android:valueTo="0" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="rotation" + android:valueFrom="0" + android:valueTo="0" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="350" + android:propertyName="rotation" + android:valueFrom="0" + android:valueTo="-45" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_bluethooth_v2_animation_dot_right.xml b/tests/VectorDrawableTest/res/anim/ic_bluethooth_v2_animation_dot_right.xml new file mode 100644 index 000000000000..49ac1650af8e --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_bluethooth_v2_animation_dot_right.xml @@ -0,0 +1,61 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="scaleX" + android:valueFrom="1" + android:valueTo="1" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="350" + android:propertyName="scaleX" + android:valueFrom="1" + android:valueTo="0" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="scaleY" + android:valueFrom="1" + android:valueTo="1" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="350" + android:propertyName="scaleY" + android:valueFrom="1" + android:valueTo="0" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="rotation" + android:valueFrom="0" + android:valueTo="0" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="350" + android:propertyName="rotation" + android:valueFrom="0" + android:valueTo="45" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_bluethooth_v2_animation_ic_signal_wifi_4_bar_48px_outlines_.xml b/tests/VectorDrawableTest/res/anim/ic_bluethooth_v2_animation_ic_signal_wifi_4_bar_48px_outlines_.xml new file mode 100644 index 000000000000..1bdfde6b3bb7 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_bluethooth_v2_animation_ic_signal_wifi_4_bar_48px_outlines_.xml @@ -0,0 +1,31 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="alpha" + android:valueFrom="1" + android:valueTo="1" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="350" + android:propertyName="alpha" + android:valueFrom="1" + android:valueTo="0.5" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_bluethooth_v2_animation_mask.xml b/tests/VectorDrawableTest/res/anim/ic_bluethooth_v2_animation_mask.xml new file mode 100644 index 000000000000..47efa183f705 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_bluethooth_v2_animation_mask.xml @@ -0,0 +1,33 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="pathData" + android:valueFrom="M 37.8337860107 -40.4599914551 c 0.0 0.0 -35.8077850342 30.0523681641 -35.8077850342 30.0523681641 c 0.0 0.0 12.925994873 12.9778747559 12.925994873 12.9778747559 c 0.0 0.0 -2.61700439453 2.09387207031 -2.61700439453 2.09387207031 c 0.0 0.0 -13.1259613037 -12.9893035889 -13.1259613037 -12.9893035889 c 0.0 0.0 -34.6200408936 26.9699249268 -34.6200408936 26.9699249268 c 0.0 0.0 55.9664764404 69.742401123 55.9664764404 69.742401123 c 0.0 0.0 73.2448120117 -59.1047973633 73.2448120117 -59.1047973633 c 0.0 0.0 -55.9664916992 -69.7423400879 -55.9664916992 -69.7423400879 Z" + android:valueTo="M 37.8337860107 -40.4599914551 c 0.0 0.0 -35.8077850342 30.0523681641 -35.8077850342 30.0523681641 c 0.0 0.0 12.925994873 12.9778747559 12.925994873 12.9778747559 c 0.0 0.0 -2.61700439453 2.09387207031 -2.61700439453 2.09387207031 c 0.0 0.0 -13.1259613037 -12.9893035889 -13.1259613037 -12.9893035889 c 0.0 0.0 -34.6200408936 26.9699249268 -34.6200408936 26.9699249268 c 0.0 0.0 55.9664764404 69.742401123 55.9664764404 69.742401123 c 0.0 0.0 73.2448120117 -59.1047973633 73.2448120117 -59.1047973633 c 0.0 0.0 -55.9664916992 -69.7423400879 -55.9664916992 -69.7423400879 Z" + android:valueType="pathType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="133" + android:propertyName="pathData" + android:valueFrom="M 37.8337860107 -40.4599914551 c 0.0 0.0 -35.8077850342 30.0523681641 -35.8077850342 30.0523681641 c 0.0 0.0 12.925994873 12.9778747559 12.925994873 12.9778747559 c 0.0 0.0 -2.61700439453 2.09387207031 -2.61700439453 2.09387207031 c 0.0 0.0 -13.1259613037 -12.9893035889 -13.1259613037 -12.9893035889 c 0.0 0.0 -34.6200408936 26.9699249268 -34.6200408936 26.9699249268 c 0.0 0.0 55.9664764404 69.742401123 55.9664764404 69.742401123 c 0.0 0.0 73.2448120117 -59.1047973633 73.2448120117 -59.1047973633 c 0.0 0.0 -55.9664916992 -69.7423400879 -55.9664916992 -69.7423400879 Z" + android:valueTo="M 37.8337860107 -40.4599914551 c 0.0 0.0 -35.8077850342 29.7398681641 -35.8077850342 29.7398681641 c 0.0 0.0 27.2634735107 27.4966583252 27.2634735107 27.4966583252 c 0.0 0.0 -2.61700439453 2.4063873291 -2.61700439453 2.4063873291 c 0.0 0.0 -27.4634399414 -27.508102417 -27.4634399414 -27.508102417 c 0.0 0.0 -34.6200408936 26.9699249268 -34.6200408936 26.9699249268 c 0.0 0.0 55.9664764404 69.742401123 55.9664764404 69.742401123 c 0.0 0.0 73.2448120117 -59.1047973633 73.2448120117 -59.1047973633 c 0.0 0.0 -55.9664916992 -69.7423400879 -55.9664916992 -69.7423400879 Z" + android:valueType="pathType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_bluethooth_v2_animation_path_1.xml b/tests/VectorDrawableTest/res/anim/ic_bluethooth_v2_animation_path_1.xml new file mode 100644 index 000000000000..41fe86634f4e --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_bluethooth_v2_animation_path_1.xml @@ -0,0 +1,33 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="pathData" + android:valueFrom="M 10.6188659668 6.56344604492 c 0.0 0.0 21.7386016846 23.1297454834 21.7386016846 23.1297454834 " + android:valueTo="M 10.6188659668 6.56344604492 c 0.0 0.0 21.7386016846 23.1297454834 21.7386016846 23.1297454834 " + android:valueType="pathType" + android:interpolator="@interpolator/ic_bluethooth_v2_path_1_pathdata_interpolator" /> + <objectAnimator + android:duration="350" + android:propertyName="pathData" + android:valueFrom="M 10.6188659668 6.56344604492 c 0.0 0.0 21.7386016846 23.1297454834 21.7386016846 23.1297454834 " + android:valueTo="M 8.62858581543 4.33430480957 c 0.0 0.0 28.1998138428 30.2359008789 28.1998138428 30.2359008789 " + android:valueType="pathType" + android:interpolator="@interpolator/ic_bluethooth_v2_path_1_pathdata_interpolator" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_frame.xml b/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_frame.xml new file mode 100644 index 000000000000..9cea85da6e27 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_frame.xml @@ -0,0 +1,31 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="367" + android:propertyName="alpha" + android:valueFrom="0.5" + android:valueTo="0.5" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="333" + android:propertyName="alpha" + android:valueFrom="0.5" + android:valueTo="1" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_screen.xml b/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_screen.xml new file mode 100644 index 000000000000..61b018b05869 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_screen.xml @@ -0,0 +1,31 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="367" + android:propertyName="alpha" + android:valueFrom="0" + android:valueTo="0" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="333" + android:propertyName="alpha" + android:valueFrom="0" + android:valueTo="1" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_wave1.xml b/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_wave1.xml new file mode 100644 index 000000000000..002f7b2a1ea8 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_wave1.xml @@ -0,0 +1,33 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="pathData" + android:valueFrom="M 0 -4.0 a 4 4 0 0 1 4 4 a 4 4 0 0 1 -4 4 a 4 4 0 0 1 -4 -4 a 4 4 0 0 1 4 -4 Z" + android:valueTo="M 0 -4.0 a 4 4 0 0 1 4 4 a 4 4 0 0 1 -4 4 a 4 4 0 0 1 -4 -4 a 4 4 0 0 1 4 -4 Z" + android:valueType="pathType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="500" + android:propertyName="pathData" + android:valueFrom="M 0 -4.0 a 4 4 0 0 1 4 4 a 4 4 0 0 1 -4 4 a 4 4 0 0 1 -4 -4 a 4 4 0 0 1 4 -4 Z" + android:valueTo="M 0 -20.0 a 20 20 0 0 1 20 20 a 20 20 0 0 1 -20 20 a 20 20 0 0 1 -20 -20 a 20 20 0 0 1 20 -20 Z" + android:valueType="pathType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_wave2.xml b/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_wave2.xml new file mode 100644 index 000000000000..0c2ee210d055 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_wave2.xml @@ -0,0 +1,33 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="pathData" + android:valueFrom="M 0 -12.0 a 12 12 0 0 1 12 12 a 12 12 0 0 1 -12 12 a 12 12 0 0 1 -12 -12 a 12 12 0 0 1 12 -12 Z" + android:valueTo="M 0 -12.0 a 12 12 0 0 1 12 12 a 12 12 0 0 1 -12 12 a 12 12 0 0 1 -12 -12 a 12 12 0 0 1 12 -12 Z" + android:valueType="pathType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="333" + android:propertyName="pathData" + android:valueFrom="M 0 -12.0 a 12 12 0 0 1 12 12 a 12 12 0 0 1 -12 12 a 12 12 0 0 1 -12 -12 a 12 12 0 0 1 12 -12 Z" + android:valueTo="M 0 -20.0 a 20 20 0 0 1 20 20 a 20 20 0 0 1 -20 20 a 20 20 0 0 1 -20 -20 a 20 20 0 0 1 20 -20 Z" + android:valueType="pathType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_wave3.xml b/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_wave3.xml new file mode 100644 index 000000000000..a75b2eaf35dd --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_wave3.xml @@ -0,0 +1,33 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="pathData" + android:valueFrom="M 0 -20.0 a 20 20 0 0 1 20 20 a 20 20 0 0 1 -20 20 a 20 20 0 0 1 -20 -20 a 20 20 0 0 1 20 -20 Z" + android:valueTo="M 0 -20.0 a 20 20 0 0 1 20 20 a 20 20 0 0 1 -20 20 a 20 20 0 0 1 -20 -20 a 20 20 0 0 1 20 -20 Z" + android:valueType="pathType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="167" + android:propertyName="pathData" + android:valueFrom="M 0 -20.0 a 20 20 0 0 1 20 20 a 20 20 0 0 1 -20 20 a 20 20 0 0 1 -20 -20 a 20 20 0 0 1 20 -20 Z" + android:valueTo="M 0 -20.0 a 20 20 0 0 1 20 20 a 20 20 0 0 1 -20 20 a 20 20 0 0 1 -20 -20 a 20 20 0 0 1 20 -20 Z" + android:valueType="pathType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_wave5.xml b/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_wave5.xml new file mode 100644 index 000000000000..7e79b94cbdd5 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_wave5.xml @@ -0,0 +1,33 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="pathData" + android:valueFrom="M 0 -0.0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 Z" + android:valueTo="M 0 -0.0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 Z" + android:valueType="pathType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="500" + android:propertyName="pathData" + android:valueFrom="M 0 -0.0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 Z" + android:valueTo="M 0 -12.0 a 12 12 0 0 1 12 12 a 12 12 0 0 1 -12 12 a 12 12 0 0 1 -12 -12 a 12 12 0 0 1 12 -12 Z" + android:valueType="pathType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_wave6.xml b/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_wave6.xml new file mode 100644 index 000000000000..0917e0e30ca4 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_wave6.xml @@ -0,0 +1,33 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="pathData" + android:valueFrom="M 0 -0.0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 Z" + android:valueTo="M 0 -0.0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 Z" + android:valueType="pathType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="333" + android:propertyName="pathData" + android:valueFrom="M 0 -0.0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 Z" + android:valueTo="M 0 -4.0 a 4 4 0 0 1 4 4 a 4 4 0 0 1 -4 4 a 4 4 0 0 1 -4 -4 a 4 4 0 0 1 4 -4 Z" + android:valueType="pathType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_waves.xml b/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_waves.xml new file mode 100644 index 000000000000..9cea85da6e27 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_cast_v2_animation_waves.xml @@ -0,0 +1,31 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="367" + android:propertyName="alpha" + android:valueFrom="0.5" + android:valueTo="0.5" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="333" + android:propertyName="alpha" + android:valueFrom="0.5" + android:valueTo="1" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_hourglass_animation_fill_outlines.xml b/tests/VectorDrawableTest/res/anim/ic_hourglass_animation_fill_outlines.xml new file mode 100644 index 000000000000..17499d5a7f74 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_hourglass_animation_fill_outlines.xml @@ -0,0 +1,22 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <objectAnimator + android:duration="333" + android:propertyName="rotation" + android:valueFrom="0" + android:valueTo="180" + android:interpolator="@android:interpolator/fast_out_slow_in" /> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_hourglass_animation_hourglass_frame.xml b/tests/VectorDrawableTest/res/anim/ic_hourglass_animation_hourglass_frame.xml new file mode 100644 index 000000000000..17499d5a7f74 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_hourglass_animation_hourglass_frame.xml @@ -0,0 +1,22 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <objectAnimator + android:duration="333" + android:propertyName="rotation" + android:valueFrom="0" + android:valueTo="180" + android:interpolator="@android:interpolator/fast_out_slow_in" /> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_hourglass_animation_mask_1.xml b/tests/VectorDrawableTest/res/anim/ic_hourglass_animation_mask_1.xml new file mode 100644 index 000000000000..541792e3b41d --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_hourglass_animation_mask_1.xml @@ -0,0 +1,33 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="333" + android:propertyName="pathData" + android:valueFrom="M 24 13.3999938965 c 0 0.0 -24 0.0 -24 0.0 c 0 0.0 0 10.6000061035 0 10.6000061035 c 0 0 24 0 24 0 c 0 0 0 -10.6000061035 0 -10.6000061035 Z" + android:valueTo="M 24 13.3999938965 c 0 0.0 -24 0.0 -24 0.0 c 0 0.0 0 10.6000061035 0 10.6000061035 c 0 0 24 0 24 0 c 0 0 0 -10.6000061035 0 -10.6000061035 Z" + android:valueType="pathType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="1000" + android:propertyName="pathData" + android:valueFrom="M 24 13.3999938965 c 0 0.0 -24 0.0 -24 0.0 c 0 0.0 0 10.6000061035 0 10.6000061035 c 0 0 24 0 24 0 c 0 0 0 -10.6000061035 0 -10.6000061035 Z" + android:valueTo="M 24 0.00173950195312 c 0 0.0 -24 0.0 -24 0.0 c 0 0.0 0 10.6982574463 0 10.6982574463 c 0 0.0 24 0.0 24 0.0 c 0 0.0 0 -10.6982574463 0 -10.6982574463 Z" + android:valueType="pathType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_open_animation_ball_start.xml b/tests/VectorDrawableTest/res/anim/ic_open_animation_ball_start.xml new file mode 100644 index 000000000000..c26c8ede867d --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_open_animation_ball_start.xml @@ -0,0 +1,86 @@ +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="833" + android:propertyName="translateX" + android:valueFrom="144" + android:valueTo="144" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="100" + android:propertyName="translateX" + android:valueFrom="144" + android:valueTo="147.411817411" + android:interpolator="@interpolator/ic_open_ball_start_translatex_interpolator" /> + </set> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="167" + android:propertyName="translateY" + android:valueFrom="144.58457376" + android:valueTo="144.58457376" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="333" + android:propertyName="translateY" + android:valueFrom="144.58457376" + android:valueTo="196.11111456" + android:interpolator="@interpolator/ic_open_ball_start_translatey_interpolator_1" /> + <objectAnimator + android:duration="333" + android:propertyName="translateY" + android:valueFrom="196.11111456" + android:valueTo="196.11111456" + android:interpolator="@interpolator/ic_open_ball_start_translatey_interpolator_2" /> + <objectAnimator + android:duration="100" + android:propertyName="translateY" + android:valueFrom="196.11111456" + android:valueTo="129.468428513" + android:interpolator="@interpolator/ic_open_ball_start_translatey_interpolator_3" /> + </set> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="167" + android:propertyName="scaleX" + android:valueFrom="0" + android:valueTo="0.71187984" + android:interpolator="@interpolator/ic_open_ball_start_scalex_interpolator_1" /> + <objectAnimator + android:duration="667" + android:propertyName="scaleX" + android:valueFrom="0.71187984" + android:valueTo="0.71187984" + android:interpolator="@interpolator/ic_open_ball_start_scalex_interpolator_2" /> + <objectAnimator + android:duration="100" + android:propertyName="scaleX" + android:valueFrom="0.71187984" + android:valueTo="0.586201598553" + android:interpolator="@interpolator/ic_open_ball_start_scalex_interpolator_3" /> + </set> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="167" + android:propertyName="scaleY" + android:valueFrom="0" + android:valueTo="0.71187984" + android:interpolator="@interpolator/ic_open_ball_start_scaley_interpolator_1" /> + <objectAnimator + android:duration="667" + android:propertyName="scaleY" + android:valueFrom="0.71187984" + android:valueTo="0.71187984" + android:interpolator="@interpolator/ic_open_ball_start_scaley_interpolator_2" /> + <objectAnimator + android:duration="100" + android:propertyName="scaleY" + android:valueFrom="0.71187984" + android:valueTo="0.586201598553" + android:interpolator="@interpolator/ic_open_ball_start_scaley_interpolator_3" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_open_animation_ball_swoop.xml b/tests/VectorDrawableTest/res/anim/ic_open_animation_ball_swoop.xml new file mode 100644 index 000000000000..509651409d51 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_open_animation_ball_swoop.xml @@ -0,0 +1,17 @@ +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="933" + android:propertyName="rotation" + android:valueFrom="-90" + android:valueTo="-90" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="1367" + android:propertyName="rotation" + android:valueFrom="-90" + android:valueTo="-87" + android:interpolator="@android:interpolator/linear" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_open_animation_path_1.xml b/tests/VectorDrawableTest/res/anim/ic_open_animation_path_1.xml new file mode 100644 index 000000000000..ef8496e50763 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_open_animation_path_1.xml @@ -0,0 +1,48 @@ +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="500" + android:propertyName="pathData" + android:valueFrom="M 0,-17.3838043213 c -9.625,0.0 -17.0795440674,8.28025817871 -17.0795440674,17.4052734375 c 0.0,9.75645446777 7.51704406738,17.6295623779 17.0795440674,17.353515625 c 11.5579986572,-0.333648681641 17.2784118652,-8.72853088379 17.2784118652,-17.353515625 c 0.0,-8.62501525879 -7.65341186523,-17.4052734375 -17.2784118652,-17.4052734375 Z" + android:valueTo="M 0,-17.3838043213 c -9.625,0.0 -17.0795440674,8.28025817871 -17.0795440674,17.4052734375 c 0.0,9.75645446777 7.51704406738,17.6295623779 17.0795440674,17.353515625 c 11.5579986572,-0.333648681641 17.2784118652,-8.72853088379 17.2784118652,-17.353515625 c 0.0,-8.62501525879 -7.65341186523,-17.4052734375 -17.2784118652,-17.4052734375 Z" + android:valueType="pathType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="267" + android:propertyName="pathData" + android:valueFrom="M 0,-17.3838043213 c -9.625,0.0 -17.0795440674,8.28025817871 -17.0795440674,17.4052734375 c 0.0,9.75645446777 7.51704406738,17.6295623779 17.0795440674,17.353515625 c 11.5579986572,-0.333648681641 17.2784118652,-8.72853088379 17.2784118652,-17.353515625 c 0.0,-8.62501525879 -7.65341186523,-17.4052734375 -17.2784118652,-17.4052734375 Z" + android:valueTo="M 0,-6 c -9.625,0 -23.5648803711,6.97859191895 -23.5648803711,16.1035919189 c 0.0,8.875 6.62738037109,8.39640808105 23.5648803711,8.39640808105 c 17.0625,0.0 23.8825073242,0.375 23.8825073242,-8.25 c 0.0,-8.625 -14.2574920654,-16.25 -23.8825073242,-16.25 Z" + android:valueType="pathType" + android:interpolator="@interpolator/ic_open_path_1_pathdata_interpolator_1" /> + <objectAnimator + android:duration="33" + android:propertyName="pathData" + android:valueFrom="M 0,-6 c -9.625,0 -23.5648803711,6.97859191895 -23.5648803711,16.1035919189 c 0.0,8.875 6.62738037109,8.39640808105 23.5648803711,8.39640808105 c 17.0625,0.0 23.8825073242,0.375 23.8825073242,-8.25 c 0.0,-8.625 -14.2574920654,-16.25 -23.8825073242,-16.25 Z" + android:valueTo="M 0,-6 c -9.625,0 -23.5648803711,6.97859191895 -23.5648803711,16.1035919189 c 0.0,8.875 6.62738037109,8.39640808105 23.5648803711,8.39640808105 c 17.0625,0.0 23.8825073242,0.375 23.8825073242,-8.25 c 0.0,-8.625 -14.2574920654,-16.25 -23.8825073242,-16.25 Z" + android:valueType="pathType" + android:interpolator="@interpolator/ic_open_path_1_pathdata_interpolator_2" /> + <objectAnimator + android:duration="67" + android:propertyName="pathData" + android:valueFrom="M 0,-6 c -9.625,0 -23.5648803711,6.97859191895 -23.5648803711,16.1035919189 c 0.0,8.875 6.62738037109,8.39640808105 23.5648803711,8.39640808105 c 17.0625,0.0 23.8825073242,0.375 23.8825073242,-8.25 c 0.0,-8.625 -14.2574920654,-16.25 -23.8825073242,-16.25 Z" + android:valueTo="M 0,-17.3838043213 c -9.625,0.0 -17.0795440674,8.28025817871 -17.0795440674,17.4052734375 c 0.0,9.75645446777 7.51704406738,17.6295623779 17.0795440674,17.353515625 c 11.5579986572,-0.333648681641 17.2784118652,-8.72853088379 17.2784118652,-17.353515625 c 0.0,-8.62501525879 -7.65341186523,-17.4052734375 -17.2784118652,-17.4052734375 Z" + android:valueType="pathType" + android:interpolator="@interpolator/ic_open_path_1_pathdata_interpolator_3" /> + </set> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="933" + android:propertyName="fillAlpha" + android:valueFrom="1" + android:valueTo="1" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="17" + android:propertyName="fillAlpha" + android:valueFrom="1" + android:valueTo="0" + android:interpolator="@android:interpolator/linear" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_open_animation_path_1_1.xml b/tests/VectorDrawableTest/res/anim/ic_open_animation_path_1_1.xml new file mode 100644 index 000000000000..496120435a90 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_open_animation_path_1_1.xml @@ -0,0 +1,74 @@ +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="917" + android:propertyName="strokeAlpha" + android:valueFrom="0" + android:valueTo="0" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="17" + android:propertyName="strokeAlpha" + android:valueFrom="0" + android:valueTo="1" + android:interpolator="@android:interpolator/linear" /> + </set> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="917" + android:propertyName="strokeWidth" + android:valueFrom="0" + android:valueTo="0" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="17" + android:propertyName="strokeWidth" + android:valueFrom="0" + android:valueTo="20" + android:interpolator="@android:interpolator/linear" /> + </set> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="933" + android:propertyName="trimPathStart" + android:valueFrom="0.06" + android:valueTo="0.06" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="383" + android:propertyName="trimPathStart" + android:valueFrom="0.06" + android:valueTo="0.19231" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="983" + android:propertyName="trimPathStart" + android:valueFrom="0.19231" + android:valueTo="0.999" + android:interpolator="@interpolator/ic_open_path_1_1_trimpathstart_interpolator_2" /> + </set> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="933" + android:propertyName="trimPathEnd" + android:valueFrom="0.061" + android:valueTo="0.061" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="300" + android:propertyName="trimPathEnd" + android:valueFrom="0.061" + android:valueTo="0.19231" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="1067" + android:propertyName="trimPathEnd" + android:valueFrom="0.19231" + android:valueTo="1" + android:interpolator="@interpolator/ic_open_path_1_1_trimpathend_interpolator_2" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_arrows_1.xml b/tests/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_arrows_1.xml new file mode 100644 index 000000000000..496e3ed819b2 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_arrows_1.xml @@ -0,0 +1,37 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <objectAnimator + android:duration="333" + android:startOffset="317" + android:propertyXName="scaleX" + android:propertyYName="scaleY" + android:pathData="M 1 1 l -0.1 -0.1 " + android:valueType="pathType" + android:interpolator="@interpolator/ic_rotate_2_portrait_v2_arrows_1_scalex_interpolator" /> + <objectAnimator + android:duration="617" + android:startOffset="200" + android:propertyName="rotation" + android:valueFrom="0" + android:valueTo="-221" + android:interpolator="@interpolator/ic_rotate_2_portrait_v2_arrows_1_rotation_interpolator" /> + <objectAnimator + android:duration="83" + android:startOffset="600" + android:propertyName="alpha" + android:valueFrom="1" + android:valueTo="0" /> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_device_1.xml b/tests/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_device_1.xml new file mode 100644 index 000000000000..47e1e7145b7d --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_device_1.xml @@ -0,0 +1,23 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <objectAnimator + android:duration="400" + android:startOffset="200" + android:propertyName="rotation" + android:valueFrom="0" + android:valueTo="-135" + android:interpolator="@interpolator/ic_rotate_2_portrait_v2_device_1_rotation_interpolator" /> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_device_2.xml b/tests/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_device_2.xml new file mode 100644 index 000000000000..f1126cfd618c --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_device_2.xml @@ -0,0 +1,24 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <objectAnimator + android:duration="217" + android:startOffset="267" + android:propertyName="pathData" + android:valueFrom="M -3.5 -20.5 c -1.19999694824 -1.19999694824 -3.10000610352 -1.19999694824 -4.19999694824 0.0 c 0.0 0.0 -12.8000030518 12.6999969482 -12.8000030518 12.6999969482 c -1.19999694824 1.19999694824 -1.19999694824 3.10000610352 0.0 4.19999694824 c 0.0 0.0 24.0 24.0000152588 24.0 24.0000152588 c 1.19999694824 1.19999694824 3.10000610352 1.19999694824 4.19999694824 0.0 c 0.0 0.0 12.6999969482 -12.700012207 12.6999969482 -12.700012207 c 1.20001220703 -1.19999694824 1.20001220703 -3.09999084473 0.0 -4.19999694824 c 0.0 0.0 -23.8999938965 -24.0 -23.8999938965 -24.0 Z M 2.84999084473 15.5500183105 c 0.0 0.0 -18.6000061035 -18.5000457764 -18.6000061035 -18.5000457764 c 0.0 0.0 12.5999908447 -12.8000030518 12.5999908447 -12.8000030518 c 0.0 0.0 18.6000213623 18.5000457764 18.6000213623 18.5000457764 c 0.0 0.0 -12.6000061035 12.8000030518 -12.6000061035 12.8000030518 Z" + android:valueTo="M -3.34053039551 -22.9980926514 c -1.3207244873 -1.3207244873 -3.46876525879 -1.26383972168 -4.74829101563 0.125762939453 c 0.0 0.0 -14.8512420654 14.7411804199 -14.8512420654 14.7411804199 c -1.39259338379 1.392578125 -1.44947814941 3.54061889648 -0.125762939453 4.74827575684 c 0.0 0.0 26.4143981934 26.4144134521 26.4143981934 26.4144134521 c 1.3207244873 1.3207244873 3.46876525879 1.26382446289 4.74829101562 -0.125762939453 c 0.0 0.0 14.7381896973 -14.7381896973 14.7381896973 -14.7381896973 c 1.392578125 -1.39259338379 1.44947814941 -3.54061889648 0.125762939453 -4.74829101562 c 0.0 0.0 -26.3013458252 -26.417388916 -26.3013458252 -26.417388916 Z M 2.87156677246 16.9857940674 c 0.0 0.0 -19.7573547363 -19.7573699951 -19.7573547363 -19.7573699951 c 0.0 0.0 14.0142059326 -14.2142181396 14.0142059326 -14.2142181396 c 0.0 0.0 19.7573699951 19.7573699951 19.7573699951 19.7573699951 c 0.0 0.0 -14.0142211914 14.2142181396 -14.0142211914 14.2142181396 Z" + android:valueType="pathType" + android:interpolator="@interpolator/ic_rotate_2_portrait_v2_device_2_pathdata_interpolator" /> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_cross_1.xml b/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_cross_1.xml new file mode 100644 index 000000000000..993493b007fe --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_cross_1.xml @@ -0,0 +1,31 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="alpha" + android:valueFrom="0" + android:valueTo="0" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="17" + android:propertyName="alpha" + android:valueFrom="0" + android:valueTo="1" + android:interpolator="@android:interpolator/linear" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_ic_signal_airplane.xml b/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_ic_signal_airplane.xml new file mode 100644 index 000000000000..1bdfde6b3bb7 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_ic_signal_airplane.xml @@ -0,0 +1,31 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="alpha" + android:valueFrom="1" + android:valueTo="1" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="350" + android:propertyName="alpha" + android:valueFrom="1" + android:valueTo="0.5" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_mask_2.xml b/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_mask_2.xml new file mode 100644 index 000000000000..94b0a3241d4f --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_mask_2.xml @@ -0,0 +1,33 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="pathData" + android:valueFrom="M 37.8337860107 -40.4599914551 c 0.0 0.0 -35.8077850342 31.5523681641 -35.8077850342 31.5523681641 c 0.0 0.0 9.55097961426 9.55285644531 9.55097961426 9.55285644531 c 0.0 0.0 -2.61698913574 2.09387207031 -2.61698913574 2.09387207031 c 0.0 0.0 -9.75096130371 -9.56428527832 -9.75096130371 -9.56428527832 c 0.0 0.0 -34.6200408936 25.4699249268 -34.6200408936 25.4699249268 c 0.0 0.0 55.9664764404 69.742401123 55.9664764404 69.742401123 c 0.0 0.0 73.2448120117 -59.1047973633 73.2448120117 -59.1047973633 c 0.0 0.0 -55.9664916992 -69.7423400879 -55.9664916992 -69.7423400879 Z" + android:valueTo="M 37.8337860107 -40.4599914551 c 0.0 0.0 -35.8077850342 31.5523681641 -35.8077850342 31.5523681641 c 0.0 0.0 9.55097961426 9.55285644531 9.55097961426 9.55285644531 c 0.0 0.0 -2.61698913574 2.09387207031 -2.61698913574 2.09387207031 c 0.0 0.0 -9.75096130371 -9.56428527832 -9.75096130371 -9.56428527832 c 0.0 0.0 -34.6200408936 25.4699249268 -34.6200408936 25.4699249268 c 0.0 0.0 55.9664764404 69.742401123 55.9664764404 69.742401123 c 0.0 0.0 73.2448120117 -59.1047973633 73.2448120117 -59.1047973633 c 0.0 0.0 -55.9664916992 -69.7423400879 -55.9664916992 -69.7423400879 Z" + android:valueType="pathType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="350" + android:propertyName="pathData" + android:valueFrom="M 37.8337860107 -40.4599914551 c 0.0 0.0 -35.8077850342 31.5523681641 -35.8077850342 31.5523681641 c 0.0 0.0 9.55097961426 9.55285644531 9.55097961426 9.55285644531 c 0.0 0.0 -2.61698913574 2.09387207031 -2.61698913574 2.09387207031 c 0.0 0.0 -9.75096130371 -9.56428527832 -9.75096130371 -9.56428527832 c 0.0 0.0 -34.6200408936 25.4699249268 -34.6200408936 25.4699249268 c 0.0 0.0 55.9664764404 69.742401123 55.9664764404 69.742401123 c 0.0 0.0 73.2448120117 -59.1047973633 73.2448120117 -59.1047973633 c 0.0 0.0 -55.9664916992 -69.7423400879 -55.9664916992 -69.7423400879 Z" + android:valueTo="M 37.8337860107 -40.3974914551 c 0.0 0.0 -35.8077850342 31.5523681641 -35.8077850342 31.5523681641 c 0.0 0.0 40.9884796143 40.9278411865 40.9884796143 40.9278411865 c 0.0 0.0 -2.61700439453 2.0938873291 -2.61700439453 2.0938873291 c 0.0 0.0 -41.1884460449 -40.9392852783 -41.1884460449 -40.9392852783 c 0.0 0.0 -34.6200408936 25.4699249268 -34.6200408936 25.4699249268 c 0.0 0.0 55.9664764404 69.742401123 55.9664764404 69.742401123 c 0.0 0.0 73.2448120117 -59.1047973633 73.2448120117 -59.1047973633 c 0.0 0.0 -55.9664916992 -69.7423400879 -55.9664916992 -69.7423400879 Z" + android:valueType="pathType" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_path_1_1.xml b/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_path_1_1.xml new file mode 100644 index 000000000000..0a4a7c476c09 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_path_1_1.xml @@ -0,0 +1,33 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="pathData" + android:valueFrom="M 7.54049682617 3.9430847168 c 0.0 0.0 0.324981689453 0.399978637695 0.324981689453 0.399978637695 " + android:valueTo="M 7.54049682617 3.9430847168 c 0.0 0.0 0.324981689453 0.399978637695 0.324981689453 0.399978637695 " + android:valueType="pathType" + android:interpolator="@interpolator/ic_signal_airplane_v2_path_1_1_pathdata_interpolator" /> + <objectAnimator + android:duration="350" + android:propertyName="pathData" + android:valueFrom="M 7.54049682617 3.9430847168 c 0.0 0.0 0.324981689453 0.399978637695 0.324981689453 0.399978637695 " + android:valueTo="M 7.54049682617 3.9430847168 c 0.0 0.0 31.5749816895 31.4499664307 31.5749816895 31.4499664307 " + android:valueType="pathType" + android:interpolator="@interpolator/ic_signal_airplane_v2_path_1_1_pathdata_interpolator" /> + </set> +</set> diff --git a/tests/VectorDrawableTest/res/drawable/animation_vector_progress_bar.xml b/tests/VectorDrawableTest/res/drawable/animation_vector_progress_bar.xml index 6621e41adfd5..4d46ee8f27d8 100644 --- a/tests/VectorDrawableTest/res/drawable/animation_vector_progress_bar.xml +++ b/tests/VectorDrawableTest/res/drawable/animation_vector_progress_bar.xml @@ -19,5 +19,7 @@ <target android:name="pie1" android:animation="@anim/trim_path_animation_progress_bar" /> - + <target + android:name="root_bar" + android:animation="@anim/alpha_animation_progress_bar" /> </animated-vector>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/drawable/ic_bluethooth_v2.xml b/tests/VectorDrawableTest/res/drawable/ic_bluethooth_v2.xml new file mode 100644 index 000000000000..5f068fc7ba79 --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/ic_bluethooth_v2.xml @@ -0,0 +1,81 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:height="48dp" + android:width="48dp" + android:viewportHeight="48" + android:viewportWidth="48" + android:name="root_bt"> + <group + android:name="ic_signal_wifi_4_bar_48px_outlines_" + android:translateX="21.9995" + android:translateY="25.73401" > + <group + android:name="ic_signal_wifi_4_bar_48px_outlines__pivot" + android:translateX="-23.21545" + android:translateY="-18.86649" > + <clip-path + android:name="mask" + android:pathData="M 37.8337860107 -40.4599914551 c 0.0 0.0 -35.8077850342 30.0523681641 -35.8077850342 30.0523681641 c 0.0 0.0 12.925994873 12.9778747559 12.925994873 12.9778747559 c 0.0 0.0 -2.61700439453 2.09387207031 -2.61700439453 2.09387207031 c 0.0 0.0 -13.1259613037 -12.9893035889 -13.1259613037 -12.9893035889 c 0.0 0.0 -34.6200408936 26.9699249268 -34.6200408936 26.9699249268 c 0.0 0.0 55.9664764404 69.742401123 55.9664764404 69.742401123 c 0.0 0.0 73.2448120117 -59.1047973633 73.2448120117 -59.1047973633 c 0.0 0.0 -55.9664916992 -69.7423400879 -55.9664916992 -69.7423400879 Z" /> + <group + android:name="cross" + android:rotation="-1.88453332239" > + <path + android:name="path_1" + android:pathData="M 10.6188659668 6.56344604492 c 0.0 0.0 21.7386016846 23.1297454834 21.7386016846 23.1297454834 " + android:strokeColor="#FF777777" + android:strokeWidth="4" + android:fillColor="#00000000" /> + </group> + <group + android:name="bluetooth" + android:translateX="23.38789" + android:translateY="18.72031" > + <path + android:name="path_4" + android:pathData="M 11.3999938965 -8.60000610352 c 0.0 0.0 -11.3999938965 -11.3999938965 -11.3999938965 -11.3999938965 c 0 0 -2 0 -2 0 c 0 0 0 15.1999969482 0 15.1999969482 c 0 0.0 -9.19999694824 -9.19999694824 -9.19999694824 -9.19999694824 c 0.0 0 -2.80000305176 2.80000305176 -2.80000305176 2.80000305176 c 0 0.0 11.1999969482 11.1999969482 11.1999969482 11.1999969482 c 0.0 0 -11.1999969482 11.1999969482 -11.1999969482 11.1999969482 c 0 0.0 2.80000305176 2.80000305176 2.80000305176 2.80000305176 c 0.0 0 9.19999694824 -9.19999694824 9.19999694824 -9.19999694824 c 0 0.0 0 15.1999969482 0 15.1999969482 c 0 0 2 0 2 0 c 0 0 11.3999938965 -11.3999938965 11.3999938965 -11.3999938965 c 0.0 0.0 -8.59999084473 -8.60000610352 -8.59999084473 -8.60000610352 c 0.0 0 8.59999084473 -8.60000610352 8.59999084473 -8.60000610352 Z M 2 -12.3000030518 c 0 0.0 3.80000305176 3.80000305176 3.80000305176 3.80000305176 c 0.0 0.0 -3.80000305176 3.69999694824 -3.80000305176 3.69999694824 c 0 0.0 0 -7.5 0 -7.5 Z M 5.80000305176 8.60000610352 c 0.0 0.0 -3.80000305176 3.69999694824 -3.80000305176 3.69999694824 c 0 0.0 0 -7.5 0 -7.5 c 0 0.0 3.80000305176 3.80000305176 3.80000305176 3.80000305176 Z" + android:fillColor="#FF777777" /> + </group> + <group + android:name="dot_left" + android:translateX="20.16992" + android:translateY="18.64258" > + <group + android:name="dot_left_pivot" + android:translateX="-20.16992" + android:translateY="-18.64258" > + <path + android:name="dot_left_1" + android:pathData="M 13.3878936768 18.7203063965 c 0.0 0.0 -4.0 -4.0 -4.0 -4.0 c 0.0 0.0 -4.0 4.0 -4.0 4.0 c 0.0 0.0 4.0 4.0 4.0 4.0 c 0.0 0.0 4.0 -4.0 4.0 -4.0 Z" + android:fillColor="#FF777777" /> + </group> + </group> + <group + android:name="dot_right" + android:translateX="26.16094" + android:translateY="18.60898" > + <group + android:name="dot_right_pivot" + android:translateX="-26.16094" + android:translateY="-18.60898" > + <path + android:name="dot_right_1" + android:pathData="M 37.3878936768 14.7203063965 c 0.0 0.0 -4.0 4.0 -4.0 4.0 c 0.0 0.0 4.0 4.0 4.0 4.0 c 0.0 0.0 4.0 -4.0 4.0 -4.0 c 0.0 0.0 -4.0 -4.0 -4.0 -4.0 Z" + android:fillColor="#FF777777" /> + </group> + </group> + </group> + </group> +</vector> diff --git a/tests/VectorDrawableTest/res/drawable/ic_bluethooth_v2_animation.xml b/tests/VectorDrawableTest/res/drawable/ic_bluethooth_v2_animation.xml new file mode 100644 index 000000000000..aa05468b1229 --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/ic_bluethooth_v2_animation.xml @@ -0,0 +1,32 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/ic_bluethooth_v2" > + <target + android:name="root_bt" + android:animation="@anim/ic_bluethooth_v2_animation_ic_signal_wifi_4_bar_48px_outlines_" /> + <target + android:name="mask" + android:animation="@anim/ic_bluethooth_v2_animation_mask" /> + <target + android:name="path_1" + android:animation="@anim/ic_bluethooth_v2_animation_path_1" /> + <target + android:name="dot_left" + android:animation="@anim/ic_bluethooth_v2_animation_dot_left" /> + <target + android:name="dot_right" + android:animation="@anim/ic_bluethooth_v2_animation_dot_right" /> +</animated-vector> diff --git a/tests/VectorDrawableTest/res/drawable/ic_cast_v2.xml b/tests/VectorDrawableTest/res/drawable/ic_cast_v2.xml new file mode 100644 index 000000000000..207804ace8ef --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/ic_cast_v2.xml @@ -0,0 +1,123 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:height="48dp" + android:width="48dp" + android:viewportHeight="48" + android:viewportWidth="48" > + <group + android:name="ic_cast_connected_48px_outlines" + android:translateX="24" + android:translateY="24" > + <group + android:name="ic_cast_connected_48px_outlines_pivot" + android:translateX="-24" + android:translateY="-24" > + <clip-path + android:name="mask_1" + android:pathData="M 46.6999969482 3.80000305176 c 0.0 0.0 -44.6999664307 0.0 -44.6999664307 0.0 c 0.0 0.0 0.29997253418 38.25 0.29997253418 38.25 c 0.0 0.0 44.8000030518 -0.100021362305 44.8000030518 -0.100021362305 c 0.0 0.0 -0.400009155273 -38.1499786377 -0.400009155273 -38.1499786377 Z" /> + <group + android:name="waves" + android:alpha="0.5" > + <group + android:name="wave1_position" + android:translateX="2" + android:translateY="42" > + <path + android:name="wave1" + android:pathData="M 0 -4.0 a 4 4 0 0 1 4 4 a 4 4 0 0 1 -4 4 a 4 4 0 0 1 -4 -4 a 4 4 0 0 1 4 -4 Z" + android:strokeColor="#FF777777" + android:strokeWidth="4" + android:fillColor="#00000000" /> + </group> + <group + android:name="wave2_position" + android:translateX="2" + android:translateY="42" > + <path + android:name="wave2" + android:pathData="M 0 -12.0 a 12 12 0 0 1 12 12 a 12 12 0 0 1 -12 12 a 12 12 0 0 1 -12 -12 a 12 12 0 0 1 12 -12 Z" + android:strokeColor="#FF777777" + android:strokeWidth="4" + android:fillColor="#00000000" /> + </group> + <group + android:name="wave3_position" + android:translateX="2" + android:translateY="42" > + <path + android:name="wave3" + android:pathData="M 0 -20.0 a 20 20 0 0 1 20 20 a 20 20 0 0 1 -20 20 a 20 20 0 0 1 -20 -20 a 20 20 0 0 1 20 -20 Z" + android:strokeColor="#FF777777" + android:strokeWidth="4" + android:fillColor="#00000000" /> + </group> + <group + android:name="wave5_position" + android:translateX="2" + android:translateY="42" > + <path + android:name="wave5" + android:pathData="M 0 -0.0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 Z" + android:strokeColor="#FF777777" + android:strokeWidth="4" + android:fillColor="#00000000" /> + </group> + <group + android:name="wave6_position" + android:translateX="2" + android:translateY="42" > + <path + android:name="wave6" + android:pathData="M 0 -0.0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 a 0 0 0 0 1 0 0 Z" + android:strokeColor="#FF777777" + android:strokeWidth="4" + android:fillColor="#00000000" /> + </group> + <group + android:name="ellipse_path_1_position" + android:translateX="2" + android:translateY="42" > + <path + android:name="ellipse_path_1" + android:pathData="M 0 -2.0 a 2 2 0 0 1 2 2 a 2 2 0 0 1 -2 2 a 2 2 0 0 1 -2 -2 a 2 2 0 0 1 2 -2 Z" + android:strokeColor="#FF777777" + android:strokeWidth="4" + android:fillColor="#00000000" /> + </group> + </group> + <group + android:name="screen" + android:translateX="24" + android:translateY="24" + android:alpha="0" > + <path + android:name="screen_1" + android:pathData="M 14 -10 c 0 0 -28 0 -28 0 c 0 0 0 3.30000305176 0 3.30000305176 c 7.89999389648 2.59999084473 14.1999969482 8.80000305176 16.6999969482 16.6999969482 c 0.0 0 11.3000030518 0 11.3000030518 0 c 0 0 0 -20 0 -20 Z" + android:fillColor="#FF777777" /> + </group> + <group + android:name="frame" + android:translateX="24" + android:translateY="24" + android:alpha="0.5" > + <path + android:name="box" + android:pathData="M 18 -18 c 0 0 -36 0 -36 0 c -2.19999694824 0 -4 1.80000305176 -4 4 c 0 0 0 6 0 6 c 0 0 4 0 4 0 c 0 0 0 -6 0 -6 c 0 0 36 0 36 0 c 0 0 0 28 0 28 c 0 0 -14 0 -14 0 c 0 0 0 4 0 4 c 0 0 14 0 14 0 c 2.19999694824 0 4 -1.80000305176 4 -4 c 0 0 0 -28 0 -28 c 0 -2.19999694824 -1.80000305176 -4 -4 -4 Z" + android:fillColor="#FF777777" /> + </group> + </group> + </group> +</vector> diff --git a/tests/VectorDrawableTest/res/drawable/ic_cast_v2_animation.xml b/tests/VectorDrawableTest/res/drawable/ic_cast_v2_animation.xml new file mode 100644 index 000000000000..78842120d1db --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/ic_cast_v2_animation.xml @@ -0,0 +1,41 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/ic_cast_v2" > + <target + android:name="waves" + android:animation="@anim/ic_cast_v2_animation_waves" /> + <target + android:name="wave1" + android:animation="@anim/ic_cast_v2_animation_wave1" /> + <target + android:name="wave2" + android:animation="@anim/ic_cast_v2_animation_wave2" /> + <target + android:name="wave3" + android:animation="@anim/ic_cast_v2_animation_wave3" /> + <target + android:name="wave5" + android:animation="@anim/ic_cast_v2_animation_wave5" /> + <target + android:name="wave6" + android:animation="@anim/ic_cast_v2_animation_wave6" /> + <target + android:name="screen" + android:animation="@anim/ic_cast_v2_animation_screen" /> + <target + android:name="frame" + android:animation="@anim/ic_cast_v2_animation_frame" /> +</animated-vector> diff --git a/tests/VectorDrawableTest/res/drawable/ic_hourglass.xml b/tests/VectorDrawableTest/res/drawable/ic_hourglass.xml new file mode 100644 index 000000000000..5b409227456c --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/ic_hourglass.xml @@ -0,0 +1,74 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:height="24dp" + android:width="24dp" + android:viewportHeight="24" + android:viewportWidth="24" > + <group + android:name="hourglass_frame" + android:translateX="12" + android:translateY="12" + android:scaleX="0.75" + android:scaleY="0.75" > + <group + android:name="hourglass_frame_pivot" + android:translateX="-12" + android:translateY="-12" > + <group + android:name="group_2_2" + android:translateX="12" + android:translateY="6.5" > + <path + android:name="path_2_2" + android:pathData="M 6.52099609375 -3.89300537109 c 0.0 0.0 -6.52099609375 6.87901306152 -6.52099609375 6.87901306152 c 0 0.0 -6.52099609375 -6.87901306152 -6.52099609375 -6.87901306152 c 0.0 0.0 13.0419921875 0.0 13.0419921875 0.0 Z M 9.99800109863 -6.5 c 0.0 0.0 -19.9960021973 0.0 -19.9960021973 0.0 c -0.890991210938 0.0 -1.33700561523 1.07699584961 -0.707000732422 1.70700073242 c 0.0 0.0 10.7050018311 11.2929992676 10.7050018311 11.2929992676 c 0 0.0 10.7050018311 -11.2929992676 10.7050018311 -11.2929992676 c 0.630004882812 -0.630004882812 0.183990478516 -1.70700073242 -0.707000732422 -1.70700073242 Z" + android:fillColor="#FF777777" /> + </group> + <group + android:name="group_1_2" + android:translateX="12" + android:translateY="17.5" > + <path + android:name="path_2_1" + android:pathData="M 0 -2.98600769043 c 0 0.0 6.52099609375 6.87901306152 6.52099609375 6.87901306152 c 0.0 0.0 -13.0419921875 0.0 -13.0419921875 0.0 c 0.0 0.0 6.52099609375 -6.87901306152 6.52099609375 -6.87901306152 Z M 0 -6.5 c 0 0.0 -10.7050018311 11.2929992676 -10.7050018311 11.2929992676 c -0.630004882812 0.630004882812 -0.184005737305 1.70700073242 0.707000732422 1.70700073242 c 0.0 0.0 19.9960021973 0.0 19.9960021973 0.0 c 0.890991210938 0.0 1.33699035645 -1.07699584961 0.707000732422 -1.70700073242 c 0.0 0.0 -10.7050018311 -11.2929992676 -10.7050018311 -11.2929992676 Z" + android:fillColor="#FF777777" /> + </group> + </group> + </group> + <group + android:name="fill_outlines" + android:translateX="12" + android:translateY="12" + android:scaleX="0.75" + android:scaleY="0.75" > + <group + android:name="fill_outlines_pivot" + android:translateX="-12" + android:translateY="-12" > + <clip-path + android:name="mask_1" + android:pathData="M 24 13.3999938965 c 0 0.0 -24 0.0 -24 0.0 c 0 0.0 0 10.6000061035 0 10.6000061035 c 0 0 24 0 24 0 c 0 0 0 -10.6000061035 0 -10.6000061035 Z" /> + <group + android:name="group_1_3" + android:translateX="12" + android:translateY="12" > + <path + android:name="path_1_6" + android:pathData="M 10.7100067139 10.2900085449 c 0.629989624023 0.629989624023 0.179992675781 1.70999145508 -0.710006713867 1.70999145508 c 0 0 -20 0 -20 0 c -0.889999389648 0 -1.33999633789 -1.08000183105 -0.710006713867 -1.70999145508 c 0.0 0.0 9.76000976562 -10.2900085449 9.76000976563 -10.2900085449 c 0.0 0 -9.76000976562 -10.2899932861 -9.76000976563 -10.2899932861 c -0.629989624023 -0.630004882812 -0.179992675781 -1.71000671387 0.710006713867 -1.71000671387 c 0 0 20 0 20 0 c 0.889999389648 0 1.33999633789 1.08000183105 0.710006713867 1.71000671387 c 0.0 0.0 -9.76000976562 10.2899932861 -9.76000976563 10.2899932861 c 0.0 0 9.76000976562 10.2900085449 9.76000976563 10.2900085449 Z" + android:fillColor="#FF777777" /> + </group> + </group> + </group> +</vector> diff --git a/tests/VectorDrawableTest/res/drawable/ic_hourglass_animation.xml b/tests/VectorDrawableTest/res/drawable/ic_hourglass_animation.xml new file mode 100644 index 000000000000..3d87376c314d --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/ic_hourglass_animation.xml @@ -0,0 +1,26 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/ic_hourglass" > + <target + android:name="hourglass_frame" + android:animation="@anim/ic_hourglass_animation_hourglass_frame" /> + <target + android:name="fill_outlines" + android:animation="@anim/ic_hourglass_animation_fill_outlines" /> + <target + android:name="mask_1" + android:animation="@anim/ic_hourglass_animation_mask_1" /> +</animated-vector> diff --git a/tests/VectorDrawableTest/res/drawable/ic_open.xml b/tests/VectorDrawableTest/res/drawable/ic_open.xml new file mode 100644 index 000000000000..ad96094657ed --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/ic_open.xml @@ -0,0 +1,56 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:height="288dp" + android:width="288dp" + android:viewportHeight="288" + android:viewportWidth="288" > + <group + android:name="ball_start" + android:translateX="147.411817411" + android:translateY="129.468428513" + android:scaleX="0.586201598553" + android:scaleY="0.586201598553" > + <group + android:name="shape_1" + android:scaleX="0.76" + android:scaleY="0.748114397321" > + <path + android:name="path_1" + android:pathData="M 0,-17.3838043213 c -9.625,0.0 -17.0795440674,8.28025817871 -17.0795440674,17.4052734375 c 0.0,9.75645446777 7.51704406738,17.6295623779 17.0795440674,17.353515625 c 11.5579986572,-0.333648681641 17.2784118652,-8.72853088379 17.2784118652,-17.353515625 c 0.0,-8.62501525879 -7.65341186523,-17.4052734375 -17.2784118652,-17.4052734375 Z" + android:fillColor="#FFFF9000" + android:fillAlpha="0" /> + </group> + </group> + <group + android:name="ball_swoop" + android:translateX="144" + android:translateY="144" + android:scaleX="0.752248" + android:scaleY="0.752248" + android:rotation="-87.6585365854" > + <path + android:name="path_1_1" + android:pathData="M -56.7679443359,1.03857421875 c 0.0,0.0 191.916503906,-13.9097290039 191.916503906,88.0704345703 c 0.0,58.4487304688 -83.6709594727,90.1372070312 -137.004882812,90.1372070312 c -82.1782226562,0.0 -177.867431641,-63.5512695312 -177.867431641,-178.207641602 c 0.0,-115.985717773 98.7650146484,-178.160949707 177.986938477,-178.160949707 c 76.2376251221,0.0 178.1640625,60.6796875 178.1640625,178.185058594 " + android:strokeColor="#FFFF9000" + android:strokeAlpha="1" + android:strokeWidth="20" + android:strokeLineCap="round" + android:trimPathStart="0.93025" + android:trimPathEnd="0.96248" + android:trimPathOffset="0" + android:fillColor="#00000000" /> + </group> +</vector> diff --git a/tests/VectorDrawableTest/res/drawable/ic_open_animation.xml b/tests/VectorDrawableTest/res/drawable/ic_open_animation.xml new file mode 100644 index 000000000000..83ee90b14b09 --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/ic_open_animation.xml @@ -0,0 +1,29 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/ic_open" > + <target + android:name="ball_start" + android:animation="@anim/ic_open_animation_ball_start" /> + <target + android:name="path_1" + android:animation="@anim/ic_open_animation_path_1" /> + <target + android:name="ball_swoop" + android:animation="@anim/ic_open_animation_ball_swoop" /> + <target + android:name="path_1_1" + android:animation="@anim/ic_open_animation_path_1_1" /> +</animated-vector> diff --git a/tests/VectorDrawableTest/res/drawable/ic_rotate_2_portrait_v2.xml b/tests/VectorDrawableTest/res/drawable/ic_rotate_2_portrait_v2.xml new file mode 100644 index 000000000000..b549423f2db1 --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/ic_rotate_2_portrait_v2.xml @@ -0,0 +1,59 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:height="48dp" + android:viewportHeight="48" + android:viewportWidth="48" + android:width="48dp" > + + <group + android:name="ic_screen_rotation_48px_outlines_1" + android:translateX="24" + android:translateY="24" > + <group + android:name="ic_screen_rotation_48px_outlines_1_pivot" + android:translateX="-24.15" + android:translateY="-24.25" > + <group + android:name="arrows_1" + android:translateX="24.1" + android:translateY="24.1" > + <group + android:name="arrows_1_pivot" + android:translateX="-24.1" + android:translateY="-24.1" > + <path + android:name="arrow_top_1" + android:fillColor="#FF777777" + android:pathData="M 33.1499938965 5.25 c 6.5 3.10000610352 11.1999969482 9.40000915527 11.8999938965 17.0 c 0.0 0.0 3.00001525879 0.0 3.00001525879 0.0 c -1.00001525879 -12.3000030518 -11.3000030518 -22.0 -23.9000091553 -22.0 c -0.399993896484 0.0 -0.899993896484 0.0 -1.30000305176 0.100006103516 c 0.0 0.0 7.60000610352 7.59999084473 7.60000610352 7.59999084473 c 0.0 0.0 2.69999694824 -2.69999694824 2.69999694824 -2.69999694824 Z" /> + <path + android:name="arrow_bottom_1" + android:fillColor="#FF777777" + android:pathData="M 15.1499938965 43.25 c -6.5 -3.09999084473 -11.1999969482 -9.5 -11.8999938965 -17.0 c 0.0 0.0 -3.0 0.0 -3.0 0.0 c 1.0 12.3000030518 11.299987793 22.0 23.8999938965 22.0 c 0.399993896484 0.0 0.899993896484 0.0 1.30000305176 -0.0999908447266 c 0.0 0.0 -7.60000610352 -7.60000610352 -7.60000610352 -7.60000610352 c 0.0 0.0 -2.69999694824 2.69999694824 -2.69999694824 2.69999694824 Z" /> + </group> + </group> + <group + android:name="device_1" + android:translateX="24.14999" + android:translateY="24.25" > + <path + android:name="device_2" + android:fillColor="#FF777777" + android:pathData="M -3.5 -20.5 c -1.19999694824 -1.19999694824 -3.10000610352 -1.19999694824 -4.19999694824 0.0 c 0.0 0.0 -12.8000030518 12.6999969482 -12.8000030518 12.6999969482 c -1.19999694824 1.19999694824 -1.19999694824 3.10000610352 0.0 4.19999694824 c 0.0 0.0 24.0 24.0000152588 24.0 24.0000152588 c 1.19999694824 1.19999694824 3.10000610352 1.19999694824 4.19999694824 0.0 c 0.0 0.0 12.6999969482 -12.700012207 12.6999969482 -12.700012207 c 1.20001220703 -1.19999694824 1.20001220703 -3.09999084473 0.0 -4.19999694824 c 0.0 0.0 -23.8999938965 -24.0 -23.8999938965 -24.0 Z M 2.84999084473 15.5500183105 c 0.0 0.0 -18.6000061035 -18.5000457764 -18.6000061035 -18.5000457764 c 0.0 0.0 12.5999908447 -12.8000030518 12.5999908447 -12.8000030518 c 0.0 0.0 18.6000213623 18.5000457764 18.6000213623 18.5000457764 c 0.0 0.0 -12.6000061035 12.8000030518 -12.6000061035 12.8000030518 Z" /> + </group> + </group> + </group> + +</vector>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/drawable/ic_rotate_2_portrait_v2_animation.xml b/tests/VectorDrawableTest/res/drawable/ic_rotate_2_portrait_v2_animation.xml new file mode 100644 index 000000000000..199fbf8b884e --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/ic_rotate_2_portrait_v2_animation.xml @@ -0,0 +1,26 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/ic_rotate_2_portrait_v2" > + <target + android:name="arrows_1" + android:animation="@anim/ic_rotate_2_portrait_v2_animation_arrows_1" /> + <target + android:name="device_1" + android:animation="@anim/ic_rotate_2_portrait_v2_animation_device_1" /> + <target + android:name="device_2" + android:animation="@anim/ic_rotate_2_portrait_v2_animation_device_2" /> +</animated-vector> diff --git a/tests/VectorDrawableTest/res/drawable/ic_signal_airplane_v2.xml b/tests/VectorDrawableTest/res/drawable/ic_signal_airplane_v2.xml new file mode 100644 index 000000000000..8b2a1a8e4346 --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/ic_signal_airplane_v2.xml @@ -0,0 +1,52 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:height="48dp" + android:width="48dp" + android:viewportHeight="48" + android:viewportWidth="48" > + <group + android:name="ic_signal_airplane" + android:translateX="21.9995" + android:translateY="25.73401" > + <group + android:name="ic_signal_airplane_pivot" + android:translateX="-23.21545" + android:translateY="-18.86649" > + <clip-path + android:name="mask_2" + android:pathData="M 37.8337860107 -40.4599914551 c 0.0 0.0 -35.8077850342 31.5523681641 -35.8077850342 31.5523681641 c 0.0 0.0 9.55097961426 9.55285644531 9.55097961426 9.55285644531 c 0.0 0.0 -2.61698913574 2.09387207031 -2.61698913574 2.09387207031 c 0.0 0.0 -9.75096130371 -9.56428527832 -9.75096130371 -9.56428527832 c 0.0 0.0 -34.6200408936 25.4699249268 -34.6200408936 25.4699249268 c 0.0 0.0 55.9664764404 69.742401123 55.9664764404 69.742401123 c 0.0 0.0 73.2448120117 -59.1047973633 73.2448120117 -59.1047973633 c 0.0 0.0 -55.9664916992 -69.7423400879 -55.9664916992 -69.7423400879 Z" /> + <group + android:name="cross_1" + android:alpha="0" > + <path + android:name="path_1_1" + android:pathData="M 7.54049682617 3.9430847168 c 0.0 0.0 0.324981689453 0.399978637695 0.324981689453 0.399978637695 " + android:strokeColor="#FF777777" + android:strokeWidth="3.5" + android:fillColor="#00000000" /> + </group> + <group + android:name="plane" + android:translateX="23.481" + android:translateY="18.71151" > + <path + android:name="path_3_2" + android:pathData="M 18.9439849854 7.98849487305 c 0.0 0.0 0.0 -4.0 0.0 -4.0 c 0.0 0.0 -16.0 -10.0 -16.0 -10.0 c 0.0 0.0 0.0 -11.0 0.0 -11.0 c 0.0 -1.70001220703 -1.30000305176 -3.0 -3.0 -3.0 c -1.69999694824 0.0 -3.0 1.29998779297 -3.0 3.0 c 0.0 0.0 0.0 11.0 0.0 11.0 c 0.0 0.0 -16.0 10.0 -16.0 10.0 c 0.0 0.0 0.0 4.0 0.0 4.0 c 0.0 0.0 16.0 -5.0 16.0 -5.0 c 0.0 0.0 0.0 11.0 0.0 11.0 c 0.0 0.0 -4.0 3.0 -4.0 3.0 c 0.0 0.0 0.0 3.0 0.0 3.0 c 0.0 0.0 7.0 -2.0 7.0 -2.0 c 0.0 0.0 7.0 2.0 7.0 2.0 c 0.0 0.0 0.0 -3.0 0.0 -3.0 c 0.0 0.0 -4.0 -3.0 -4.0 -3.0 c 0.0 0.0 0.0 -11.0 0.0 -11.0 c 0.0 0.0 16.0 5.0 16.0 5.0 Z" + android:fillColor="#FF777777" /> + </group> + </group> + </group> +</vector> diff --git a/tests/VectorDrawableTest/res/drawable/ic_signal_airplane_v2_animation.xml b/tests/VectorDrawableTest/res/drawable/ic_signal_airplane_v2_animation.xml new file mode 100644 index 000000000000..bde2b38f871a --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/ic_signal_airplane_v2_animation.xml @@ -0,0 +1,29 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/ic_signal_airplane_v2" > + <target + android:name="ic_signal_airplane" + android:animation="@anim/ic_signal_airplane_v2_animation_ic_signal_airplane" /> + <target + android:name="mask_2" + android:animation="@anim/ic_signal_airplane_v2_animation_mask_2" /> + <target + android:name="cross_1" + android:animation="@anim/ic_signal_airplane_v2_animation_cross_1" /> + <target + android:name="path_1_1" + android:animation="@anim/ic_signal_airplane_v2_animation_path_1_1" /> +</animated-vector> diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable29.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable29.xml new file mode 100644 index 000000000000..c0e9b2abba90 --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable29.xml @@ -0,0 +1,28 @@ +<!-- + Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:height="48dp" + android:width="48dp" + android:viewportHeight="1" + android:viewportWidth="1" > + + <group> + <path + android:name="box1" + android:pathData="l0.0.0.5.0.0.5-0.5.0.0-.5z" + android:fillColor="#ff00ff00"/> + </group> +</vector> diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_progress_bar.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable_progress_bar.xml index 4544cae92a31..22cd9959ade8 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable_progress_bar.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable_progress_bar.xml @@ -17,7 +17,8 @@ android:height="64dp" android:width="64dp" android:viewportHeight="64" - android:viewportWidth="64" > + android:viewportWidth="64" + android:name="root_bar" > <group android:name="root" diff --git a/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator.xml b/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator.xml index 0cffa0a9009b..489596c4fe5b 100644 --- a/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator.xml +++ b/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator.xml @@ -1,2 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> <pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:pathData="m0,0q0.4,0.05 0.6,0.3t0.3,0.3l0.1,0.4" />
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator_favorite.xml b/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator_favorite.xml index 935d5b5ef220..3d125e490573 100644 --- a/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator_favorite.xml +++ b/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator_favorite.xml @@ -1,2 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> <pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:pathData="L0.1, 0 C0.10066,0 0.198,1 0.2, 1 L 1,1" />
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator_grouping_1_01.xml b/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator_grouping_1_01.xml index 8c57395e0495..6877bd96285d 100644 --- a/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator_grouping_1_01.xml +++ b/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator_grouping_1_01.xml @@ -1,2 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> <pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:pathData="L 0.09 1 L 1,1" />
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/interpolator/ic_bluethooth_v2_path_1_pathdata_interpolator.xml b/tests/VectorDrawableTest/res/interpolator/ic_bluethooth_v2_path_1_pathdata_interpolator.xml new file mode 100644 index 000000000000..4917f770cae1 --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_bluethooth_v2_path_1_pathdata_interpolator.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 0.16666666667 0.0 0.2 1.0 1.0 1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_1.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_1.xml new file mode 100644 index 000000000000..601cfc68dbea --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_1.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 0.33333333,0.0 0.202777547991,1.0 1.0,1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_2.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_2.xml new file mode 100644 index 000000000000..5011ef923048 --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_2.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 0.0103034467173,0.0 0.701918866569,1.0 1.0,1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_3.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_3.xml new file mode 100644 index 000000000000..7b0af97df466 --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_3.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 0.649706648701,0.0 0.884285938423,1.92358061843 1.0,1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_1.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_1.xml new file mode 100644 index 000000000000..601cfc68dbea --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_1.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 0.33333333,0.0 0.202777547991,1.0 1.0,1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_2.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_2.xml new file mode 100644 index 000000000000..5011ef923048 --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_2.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 0.0103034467173,0.0 0.701918866569,1.0 1.0,1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_3.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_3.xml new file mode 100644 index 000000000000..7b0af97df466 --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_3.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 0.649706648701,0.0 0.884285938423,1.92358061843 1.0,1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatex_interpolator.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatex_interpolator.xml new file mode 100644 index 000000000000..ea11d1ff927a --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatex_interpolator.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 0.353876322169,0.0 0.686452288267,-1.02094740172 1.0,1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_1.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_1.xml new file mode 100644 index 000000000000..7bd5c497968d --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_1.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 0.754478769148,0.0 0.97,1.0 1.0,1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_2.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_2.xml new file mode 100644 index 000000000000..b0ab6e89fd54 --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_2.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 0.33333333,0.0 0.83333333333,1.0 1.0,1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_3.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_3.xml new file mode 100644 index 000000000000..61060a616c78 --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_3.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 0.324310863613,0.0 0.735625629425,-0.0161527278292 1.0,1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathend_interpolator_2.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathend_interpolator_2.xml new file mode 100644 index 000000000000..7e19ef6a03ea --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathend_interpolator_2.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 0.744517024668,0.120263649138 0.135947812437,0.994319475209 1.0,1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathstart_interpolator_2.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathstart_interpolator_2.xml new file mode 100644 index 000000000000..1280715c656c --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathstart_interpolator_2.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 0.781904890372,0.126303002187 0.188007240906,0.953418294755 1.0,1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_1.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_1.xml new file mode 100644 index 000000000000..ddf966efd7d6 --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_1.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 0.000100000000012,0.0 0.0,1.0 1.0,1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_2.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_2.xml new file mode 100644 index 000000000000..624e304a4478 --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_2.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 9.99999999007e-05,0.0 0.0,1.0 1.0,1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_3.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_3.xml new file mode 100644 index 000000000000..3ebee0bfa6f6 --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_3.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 0.000100000000051,0.0 0.83333333333,1.0 1.0,1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_arrows_1_rotation_interpolator.xml b/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_arrows_1_rotation_interpolator.xml new file mode 100644 index 000000000000..f798a84087c6 --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_arrows_1_rotation_interpolator.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 0.4 0.0 0.2 1.0 1.0 1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_arrows_1_scalex_interpolator.xml b/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_arrows_1_scalex_interpolator.xml new file mode 100644 index 000000000000..314cf448b9eb --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_arrows_1_scalex_interpolator.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0.0 0.0 L 1.0 1.0 " /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_device_1_rotation_interpolator.xml b/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_device_1_rotation_interpolator.xml new file mode 100644 index 000000000000..f798a84087c6 --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_device_1_rotation_interpolator.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 0.4 0.0 0.2 1.0 1.0 1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_device_2_pathdata_interpolator.xml b/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_device_2_pathdata_interpolator.xml new file mode 100644 index 000000000000..f798a84087c6 --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_device_2_pathdata_interpolator.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 0.4 0.0 0.2 1.0 1.0 1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/ic_signal_airplane_v2_path_1_1_pathdata_interpolator.xml b/tests/VectorDrawableTest/res/interpolator/ic_signal_airplane_v2_path_1_1_pathdata_interpolator.xml new file mode 100644 index 000000000000..4917f770cae1 --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/ic_signal_airplane_v2_path_1_1_pathdata_interpolator.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 c 0.16666666667 0.0 0.2 1.0 1.0 1.0" /> diff --git a/tests/VectorDrawableTest/res/interpolator/trim_end_interpolator.xml b/tests/VectorDrawableTest/res/interpolator/trim_end_interpolator.xml index b2770cdf00d1..54b5ebd7aa86 100644 --- a/tests/VectorDrawableTest/res/interpolator/trim_end_interpolator.xml +++ b/tests/VectorDrawableTest/res/interpolator/trim_end_interpolator.xml @@ -1,2 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> <pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:pathData="C0.2,0 0.1,1 0.5, 1 L 1,1" />
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/interpolator/trim_start_interpolator.xml b/tests/VectorDrawableTest/res/interpolator/trim_start_interpolator.xml index 798f7e669b49..c06c196088dd 100644 --- a/tests/VectorDrawableTest/res/interpolator/trim_start_interpolator.xml +++ b/tests/VectorDrawableTest/res/interpolator/trim_start_interpolator.xml @@ -1,2 +1,16 @@ +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> <pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:pathData="L0.5,0 C 0.7,0 0.6,1 1, 1" />
\ No newline at end of file diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java index 05bf166a98ce..3045839e5e1e 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java +++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java @@ -26,6 +26,12 @@ public class AnimatedVectorDrawableTest extends Activity implements View.OnClick private static final String LOGCAT = "AnimatedVectorDrawableTest"; protected int[] icon = { + R.drawable.ic_open_animation, + R.drawable.ic_rotate_2_portrait_v2_animation, + R.drawable.ic_signal_airplane_v2_animation, + R.drawable.ic_hourglass_animation, + R.drawable.ic_cast_v2_animation, + R.drawable.ic_bluethooth_v2_animation, R.drawable.animation_vector_linear_progress_bar, R.drawable.animation_vector_drawable_grouping_1, R.drawable.animation_vector_progress_bar, diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java index 37e043551805..1cd6533585ae 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java +++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java @@ -56,6 +56,7 @@ public class VectorDrawablePerformance extends Activity { R.drawable.vector_drawable26, R.drawable.vector_drawable27, R.drawable.vector_drawable28, + R.drawable.vector_drawable29, }; @Override diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp index 117fc2435076..b7f64f63fdbc 100644 --- a/tools/aapt/AaptAssets.cpp +++ b/tools/aapt/AaptAssets.cpp @@ -1141,9 +1141,10 @@ bail: ssize_t AaptAssets::slurpFullTree(Bundle* bundle, const String8& srcDir, const AaptGroupEntry& kind, const String8& resType, - sp<FilePathStore>& fullResPaths) + sp<FilePathStore>& fullResPaths, + const bool overwrite) { - ssize_t res = AaptDir::slurpFullTree(bundle, srcDir, kind, resType, fullResPaths); + ssize_t res = AaptDir::slurpFullTree(bundle, srcDir, kind, resType, fullResPaths, overwrite); if (res > 0) { mGroupEntries.add(kind); } diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h index d809c5b3003c..7ae5368d80bd 100644 --- a/tools/aapt/AaptAssets.h +++ b/tools/aapt/AaptAssets.h @@ -591,7 +591,8 @@ private: const String8& srcDir, const AaptGroupEntry& kind, const String8& resType, - sp<FilePathStore>& fullResPaths); + sp<FilePathStore>& fullResPaths, + const bool overwrite=false); ssize_t slurpResourceTree(Bundle* bundle, const String8& srcDir); ssize_t slurpResourceZip(Bundle* bundle, const char* filename); diff --git a/tools/aapt/AaptConfig.cpp b/tools/aapt/AaptConfig.cpp index 32a0cd3d4872..f447462ae975 100644 --- a/tools/aapt/AaptConfig.cpp +++ b/tools/aapt/AaptConfig.cpp @@ -240,7 +240,9 @@ void applyVersionForCompatibility(ConfigDescription* config) { } uint16_t minSdk = 0; - if (config->smallestScreenWidthDp != ResTable_config::SCREENWIDTH_ANY + if (config->density == ResTable_config::DENSITY_ANY) { + minSdk = SDK_L; + } else if (config->smallestScreenWidthDp != ResTable_config::SCREENWIDTH_ANY || config->screenWidthDp != ResTable_config::SCREENWIDTH_ANY || config->screenHeightDp != ResTable_config::SCREENHEIGHT_ANY) { minSdk = SDK_HONEYCOMB_MR2; @@ -255,8 +257,6 @@ void applyVersionForCompatibility(ConfigDescription* config) { != ResTable_config::SCREENLONG_ANY || config->density != ResTable_config::DENSITY_DEFAULT) { minSdk = SDK_DONUT; - } else if ((config->density == ResTable_config::DENSITY_ANY)) { - minSdk = SDK_L; } if (minSdk > config->sdkVersion) { diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index 1e9e3e20ddf8..f5f70c5cf2ed 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -307,6 +307,7 @@ enum { PUBLIC_KEY_ATTR = 0x010103a6, CATEGORY_ATTR = 0x010103e8, BANNER_ATTR = 0x10103f2, + ISGAME_ATTR = 0x10103f4, }; String8 getComponentName(String8 &pkgName, String8 &componentName) { @@ -1127,13 +1128,35 @@ int doDump(Bundle* bundle) error.string()); goto bail; } + + String8 banner = AaptXml::getResolvedAttribute(res, tree, BANNER_ATTR, &error); + if (error != "") { + fprintf(stderr, "ERROR getting 'android:banner' attribute: %s\n", + error.string()); + goto bail; + } printf("application: label='%s' ", ResTable::normalizeForOutput(label.string()).string()); - printf("icon='%s'\n", ResTable::normalizeForOutput(icon.string()).string()); + printf("icon='%s'", ResTable::normalizeForOutput(icon.string()).string()); + if (banner != "") { + printf(" banner='%s'", ResTable::normalizeForOutput(banner.string()).string()); + } + printf("\n"); if (testOnly != 0) { printf("testOnly='%d'\n", testOnly); } + int32_t isGame = AaptXml::getResolvedIntegerAttribute(res, tree, + ISGAME_ATTR, 0, &error); + if (error != "") { + fprintf(stderr, "ERROR getting 'android:isGame' attribute: %s\n", + error.string()); + goto bail; + } + if (isGame != 0) { + printf("application-isGame\n"); + } + int32_t debuggable = AaptXml::getResolvedIntegerAttribute(res, tree, DEBUGGABLE_ATTR, 0, &error); if (error != "") { diff --git a/tools/aapt/ConfigDescription.h b/tools/aapt/ConfigDescription.h index 779c423fce1a..4f999a2ff0c6 100644 --- a/tools/aapt/ConfigDescription.h +++ b/tools/aapt/ConfigDescription.h @@ -28,10 +28,12 @@ struct ConfigDescription : public android::ResTable_config { memset(this, 0, sizeof(*this)); size = sizeof(android::ResTable_config); } + ConfigDescription(const android::ResTable_config&o) { *static_cast<android::ResTable_config*>(this) = o; size = sizeof(android::ResTable_config); } + ConfigDescription(const ConfigDescription&o) { *static_cast<android::ResTable_config*>(this) = o; } @@ -41,6 +43,7 @@ struct ConfigDescription : public android::ResTable_config { size = sizeof(android::ResTable_config); return *this; } + ConfigDescription& operator=(const ConfigDescription& o) { *static_cast<android::ResTable_config*>(this) = o; return *this; diff --git a/tools/aapt/ResourceIdCache.cpp b/tools/aapt/ResourceIdCache.cpp index d60a07fc243b..8835fb0130a3 100644 --- a/tools/aapt/ResourceIdCache.cpp +++ b/tools/aapt/ResourceIdCache.cpp @@ -9,8 +9,6 @@ #include <utils/Log.h> #include "ResourceIdCache.h" #include <map> -using namespace std; - static size_t mHits = 0; static size_t mMisses = 0; @@ -29,7 +27,7 @@ struct CacheEntry { CacheEntry(const android::String16& name, uint32_t resId) : hashedName(name), id(resId) { } }; -static map< uint32_t, CacheEntry > mIdMap; +static std::map< uint32_t, CacheEntry > mIdMap; // djb2; reasonable choice for strings when collisions aren't particularly important @@ -63,7 +61,7 @@ uint32_t ResourceIdCache::lookup(const android::String16& package, bool onlyPublic) { const String16 hashedName = makeHashableName(package, type, name, onlyPublic); const uint32_t hashcode = hash(hashedName); - map<uint32_t, CacheEntry>::iterator item = mIdMap.find(hashcode); + std::map<uint32_t, CacheEntry>::iterator item = mIdMap.find(hashcode); if (item == mIdMap.end()) { // cache miss mMisses++; diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java index 997b1996259b..4c4454dc494a 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java @@ -95,6 +95,10 @@ public final class BridgeWindow implements IWindow { } @Override + public void dispatchWindowShown() { + } + + @Override public IBinder asBinder() { // pass for now. return null; diff --git a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java index 88988563349f..b8b5fed77e76 100644 --- a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java +++ b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java @@ -223,7 +223,7 @@ public class ICU_Delegate { result.decimalSeparator = '.'; result.groupingSeparator = ','; result.patternSeparator = ' '; - result.percent = '%'; + result.percent = "%"; result.perMill = '\u2030'; result.monetarySeparator = ' '; result.minusSign = "-"; diff --git a/tools/split-select/Abi.cpp b/tools/split-select/Abi.cpp new file mode 100644 index 000000000000..20654b613384 --- /dev/null +++ b/tools/split-select/Abi.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2014 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. + */ + +#include "Abi.h" + +namespace split { +namespace abi { + +static const std::vector<Variant> sNoneVariants = {}; +static const std::vector<Variant> sArmVariants = + {Variant::armeabi, Variant::armeabi_v7a, Variant::arm64_v8a}; +static const std::vector<Variant> sIntelVariants = {Variant::x86, Variant::x86_64}; +static const std::vector<Variant> sMipsVariants = {Variant::mips, Variant::mips64}; + +Family getFamily(Variant variant) { + switch (variant) { + case Variant::none: + return Family::none; + case Variant::armeabi: + case Variant::armeabi_v7a: + case Variant::arm64_v8a: + return Family::arm; + case Variant::x86: + case Variant::x86_64: + return Family::intel; + case Variant::mips: + case Variant::mips64: + return Family::mips; + } + return Family::none; +} + +const std::vector<Variant>& getVariants(Family family) { + switch (family) { + case Family::none: + return sNoneVariants; + case Family::arm: + return sArmVariants; + case Family::intel: + return sIntelVariants; + case Family::mips: + return sMipsVariants; + } + return sNoneVariants; +} + +const char* toString(Variant variant) { + switch (variant) { + case Variant::none: + return ""; + case Variant::armeabi: + return "armeabi"; + case Variant::armeabi_v7a: + return "armeabi-v7a"; + case Variant::arm64_v8a: + return "arm64-v8a"; + case Variant::x86: + return "x86"; + case Variant::x86_64: + return "x86_64"; + case Variant::mips: + return "mips"; + case Variant::mips64: + return "mips64"; + } + return ""; +} + +} // namespace abi +} // namespace split diff --git a/tools/split-select/Abi.h b/tools/split-select/Abi.h new file mode 100644 index 000000000000..3e00eba547ec --- /dev/null +++ b/tools/split-select/Abi.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2014 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. + */ + +#ifndef H_ANDROID_SPLIT_ABI +#define H_ANDROID_SPLIT_ABI + +#include <vector> + +namespace split { +namespace abi { + +enum class Variant { + none = 0, + armeabi, + armeabi_v7a, + arm64_v8a, + x86, + x86_64, + mips, + mips64, +}; + +enum class Family { + none, + arm, + intel, + mips, +}; + +Family getFamily(Variant variant); +const std::vector<Variant>& getVariants(Family family); +const char* toString(Variant variant); + +} // namespace abi +} // namespace split + +#endif // H_ANDROID_SPLIT_ABI diff --git a/tools/split-select/Android.mk b/tools/split-select/Android.mk new file mode 100644 index 000000000000..d0b72877e5b6 --- /dev/null +++ b/tools/split-select/Android.mk @@ -0,0 +1,119 @@ +# +# Copyright (C) 2014 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. +# + +# This tool is prebuilt if we're doing an app-only build. +ifeq ($(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)),) + +# TODO(adamlesinski): Enable OS X builds when I figure out how +# to build with clang and libc++ +ifneq ($(HOST_OS),darwin) + +# ========================================================== +# Setup some common variables for the different build +# targets here. +# ========================================================== +LOCAL_PATH:= $(call my-dir) + +main := Main.cpp +sources := \ + Abi.cpp \ + Grouper.cpp \ + Rule.cpp \ + RuleGenerator.cpp \ + SplitDescription.cpp + +testSources := \ + Grouper_test.cpp \ + Rule_test.cpp \ + RuleGenerator_test.cpp + +cIncludes := \ + external/zlib \ + frameworks/base/tools + +hostLdLibs := +hostStaticLibs := \ + libaapt \ + libandroidfw \ + libpng \ + liblog \ + libutils \ + libcutils \ + libexpat \ + libziparchive-host + +cFlags := -std=c++11 -Wall -Werror + +ifeq ($(HOST_OS),linux) + hostLdLibs += -lrt -ldl -lpthread +endif + +# Statically link libz for MinGW (Win SDK under Linux), +# and dynamically link for all others. +ifneq ($(strip $(USE_MINGW)),) + hostStaticLibs += libz +else + hostLdLibs += -lz +endif + + +# ========================================================== +# Build the host static library: libsplit-select +# ========================================================== +include $(CLEAR_VARS) +LOCAL_MODULE := libsplit-select + +LOCAL_SRC_FILES := $(sources) + +LOCAL_C_INCLUDES += $(cIncludes) +LOCAL_CFLAGS += $(cFlags) -D_DARWIN_UNLIMITED_STREAMS + +include $(BUILD_HOST_STATIC_LIBRARY) + + +# ========================================================== +# Build the host tests: libsplit-select_tests +# ========================================================== +include $(CLEAR_VARS) +LOCAL_MODULE := libsplit-select_tests +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := $(testSources) + +LOCAL_C_INCLUDES += $(cIncludes) +LOCAL_STATIC_LIBRARIES += libsplit-select $(hostStaticLibs) +LOCAL_LDLIBS += $(hostLdLibs) +LOCAL_CFLAGS += $(cFlags) + +include $(BUILD_HOST_NATIVE_TEST) + +# ========================================================== +# Build the host executable: split-select +# ========================================================== +include $(CLEAR_VARS) +LOCAL_MODULE := split-select + +LOCAL_SRC_FILES := $(main) + +LOCAL_C_INCLUDES += $(cIncludes) +LOCAL_STATIC_LIBRARIES += libsplit-select $(hostStaticLibs) +LOCAL_LDLIBS += $(hostLdLibs) +LOCAL_CFLAGS += $(cFlags) + +include $(BUILD_HOST_EXECUTABLE) + +endif # Not OS X +endif # No TARGET_BUILD_APPS or TARGET_BUILD_PDK diff --git a/tools/split-select/Grouper.cpp b/tools/split-select/Grouper.cpp new file mode 100644 index 000000000000..15edf89bd60f --- /dev/null +++ b/tools/split-select/Grouper.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2014 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. + */ + +#include "Grouper.h" + +#include "SplitDescription.h" + +#include <utils/KeyedVector.h> +#include <utils/Vector.h> + +using namespace android; + +namespace split { + +template <typename Key, typename Value> +static void addToVector(KeyedVector<Key, SortedVector<Value> >& group, + const Key& key, const Value& value) { + ssize_t idx = group.indexOfKey(key); + if (idx < 0) { + idx = group.add(key, SortedVector<Value>()); + } + group.editValueAt(idx).add(value); +} + +Vector<SortedVector<SplitDescription> > +groupByMutualExclusivity(const Vector<SplitDescription>& splits) { + Vector<SortedVector<SplitDescription> > groups; + + // Find mutually exclusive splits and group them. + KeyedVector<SplitDescription, SortedVector<SplitDescription> > densityGroups; + KeyedVector<SplitDescription, SortedVector<SplitDescription> > abiGroups; + KeyedVector<SplitDescription, SortedVector<SplitDescription> > localeGroups; + for (const SplitDescription& split : splits) { + if (split.config.density != 0) { + SplitDescription key(split); + key.config.density = 0; + key.config.sdkVersion = 0; // Ignore density so we can support anydpi. + addToVector(densityGroups, key, split); + } else if (split.abi != abi::Variant::none) { + SplitDescription key(split); + key.abi = abi::Variant::none; + addToVector(abiGroups, key, split); + } else if (split.config.locale != 0) { + SplitDescription key(split); + key.config.clearLocale(); + addToVector(localeGroups, key, split); + } else { + groups.add(); + groups.editTop().add(split); + } + } + + const size_t densityCount = densityGroups.size(); + for (size_t i = 0; i < densityCount; i++) { + groups.add(densityGroups[i]); + } + + const size_t abiCount = abiGroups.size(); + for (size_t i = 0; i < abiCount; i++) { + groups.add(abiGroups[i]); + } + + const size_t localeCount = localeGroups.size(); + for (size_t i = 0; i < localeCount; i++) { + groups.add(localeGroups[i]); + } + return groups; +} + +} // namespace split diff --git a/tools/split-select/Grouper.h b/tools/split-select/Grouper.h new file mode 100644 index 000000000000..5cb0b5b862df --- /dev/null +++ b/tools/split-select/Grouper.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2014 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. + */ + +#ifndef H_ANDROID_SPLIT_GROUPER +#define H_ANDROID_SPLIT_GROUPER + +#include "SplitDescription.h" + +#include <utils/SortedVector.h> +#include <utils/Vector.h> + +namespace split { + +android::Vector<android::SortedVector<SplitDescription> > +groupByMutualExclusivity(const android::Vector<SplitDescription>& splits); + +} // namespace split + +#endif // H_ANDROID_SPLIT_GROUPER diff --git a/tools/split-select/Grouper_test.cpp b/tools/split-select/Grouper_test.cpp new file mode 100644 index 000000000000..4d146cdd8ed1 --- /dev/null +++ b/tools/split-select/Grouper_test.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2014 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. + */ + +#include "Grouper.h" + +#include "SplitDescription.h" + +#include <gtest/gtest.h> +#include <initializer_list> +#include <utils/String8.h> +#include <utils/Vector.h> + +using namespace android; + +namespace split { + +class GrouperTest : public ::testing::Test { +protected: + virtual void SetUp() { + Vector<SplitDescription> splits; + addSplit(splits, "en-rUS-sw600dp-hdpi"); + addSplit(splits, "fr-rFR-sw600dp-hdpi"); + addSplit(splits, "fr-rFR-sw600dp-xhdpi"); + addSplit(splits, ":armeabi"); + addSplit(splits, "en-rUS-sw300dp-xhdpi"); + addSplit(splits, "large"); + addSplit(splits, "pl-rPL"); + addSplit(splits, "xlarge"); + addSplit(splits, "en-rUS-sw600dp-xhdpi"); + addSplit(splits, "en-rUS-sw300dp-hdpi"); + addSplit(splits, "xxhdpi"); + addSplit(splits, "hdpi"); + addSplit(splits, "de-rDE"); + addSplit(splits, "xhdpi"); + addSplit(splits, ":x86"); + addSplit(splits, "anydpi"); + addSplit(splits, "v7"); + addSplit(splits, "v8"); + addSplit(splits, "sw600dp"); + addSplit(splits, "sw300dp"); + mGroups = groupByMutualExclusivity(splits); + } + + void addSplit(Vector<SplitDescription>& splits, const char* str); + void expectHasGroupWithSplits(std::initializer_list<const char*> l); + + Vector<SortedVector<SplitDescription> > mGroups; +}; + +TEST_F(GrouperTest, shouldHaveCorrectNumberOfGroups) { + EXPECT_EQ(12u, mGroups.size()); +} + +TEST_F(GrouperTest, shouldGroupDensities) { + expectHasGroupWithSplits({"en-rUS-sw300dp-hdpi", "en-rUS-sw300dp-xhdpi"}); + expectHasGroupWithSplits({"en-rUS-sw600dp-hdpi", "en-rUS-sw600dp-xhdpi"}); + expectHasGroupWithSplits({"fr-rFR-sw600dp-hdpi", "fr-rFR-sw600dp-xhdpi"}); + expectHasGroupWithSplits({"hdpi", "xhdpi", "xxhdpi", "anydpi"}); +} + +TEST_F(GrouperTest, shouldGroupAbi) { + expectHasGroupWithSplits({":armeabi", ":x86"}); +} + +TEST_F(GrouperTest, shouldGroupLocale) { + expectHasGroupWithSplits({"pl-rPL", "de-rDE"}); +} + +TEST_F(GrouperTest, shouldGroupEachSplitIntoItsOwnGroup) { + expectHasGroupWithSplits({"large"}); + expectHasGroupWithSplits({"xlarge"}); + expectHasGroupWithSplits({"v7"}); + expectHasGroupWithSplits({"v8"}); + expectHasGroupWithSplits({"sw600dp"}); + expectHasGroupWithSplits({"sw300dp"}); +} + +// +// Helper methods +// + +void GrouperTest::expectHasGroupWithSplits(std::initializer_list<const char*> l) { + Vector<SplitDescription> splits; + for (const char* str : l) { + splits.add(); + if (!SplitDescription::parse(String8(str), &splits.editTop())) { + ADD_FAILURE() << "Failed to parse SplitDescription " << str; + return; + } + } + const size_t splitCount = splits.size(); + + const size_t groupCount = mGroups.size(); + for (size_t i = 0; i < groupCount; i++) { + const SortedVector<SplitDescription>& group = mGroups[i]; + if (group.size() != splitCount) { + continue; + } + + size_t found = 0; + for (size_t j = 0; j < splitCount; j++) { + if (group.indexOf(splits[j]) >= 0) { + found++; + } + } + + if (found == splitCount) { + return; + } + } + + String8 errorMessage("Failed to find expected group ["); + for (size_t i = 0; i < splitCount; i++) { + if (i != 0) { + errorMessage.append(", "); + } + errorMessage.append(splits[i].toString()); + } + errorMessage.append("].\nActual:\n"); + + for (size_t i = 0; i < groupCount; i++) { + errorMessage.appendFormat("Group %d:\n", int(i + 1)); + const SortedVector<SplitDescription>& group = mGroups[i]; + for (size_t j = 0; j < group.size(); j++) { + errorMessage.append(" "); + errorMessage.append(group[j].toString()); + errorMessage.append("\n"); + } + } + ADD_FAILURE() << errorMessage.string(); +} + +void GrouperTest::addSplit(Vector<SplitDescription>& splits, const char* str) { + splits.add(); + EXPECT_TRUE(SplitDescription::parse(String8(str), &splits.editTop())); +} + +} // namespace split diff --git a/tools/split-select/Main.cpp b/tools/split-select/Main.cpp new file mode 100644 index 000000000000..d6251c3c1511 --- /dev/null +++ b/tools/split-select/Main.cpp @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2014 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. + */ + +#include <algorithm> +#include <cstdio> + +#include "aapt/AaptUtil.h" + +#include "Grouper.h" +#include "Rule.h" +#include "RuleGenerator.h" +#include "SplitDescription.h" + +#include <androidfw/AssetManager.h> +#include <androidfw/ResourceTypes.h> +#include <utils/KeyedVector.h> +#include <utils/Vector.h> + +using namespace android; + +namespace split { + +static void usage() { + fprintf(stderr, + "split-select --help\n" + "split-select --target <config> --split <path/to/apk> [--split <path/to/apk> [...]]\n" + "split-select --generate --split <path/to/apk> [--split <path/to/apk> [...]]\n" + "\n" + " --help Displays more information about this program.\n" + " --target <config> Performs the Split APK selection on the given configuration.\n" + " --generate Generates the logic for selecting the Split APK, in JSON format.\n" + " --split <path/to/apk> Includes a Split APK in the selection process.\n" + "\n" + " Where <config> is an extended AAPT resource qualifier of the form\n" + " 'resource-qualifiers:extended-qualifiers', where 'resource-qualifiers' is an AAPT resource\n" + " qualifier (ex: en-rUS-sw600dp-xhdpi), and 'extended-qualifiers' is an ordered list of one\n" + " qualifier (or none) from each category:\n" + " Architecture: armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, mips\n"); +} + +static void help() { + usage(); + fprintf(stderr, "\n" + " Generates the logic for selecting a Split APK given some target Android device configuration.\n" + " Using the flag --generate will emit a JSON encoded tree of rules that must be satisfied in order\n" + " to install the given Split APK. Using the flag --target along with the device configuration\n" + " will emit the set of Split APKs to install, following the same logic that would have been emitted\n" + " via JSON.\n"); +} + +class SplitSelector { +public: + SplitSelector() = default; + SplitSelector(const Vector<SplitDescription>& splits); + + Vector<SplitDescription> getBestSplits(const SplitDescription& target) const; + + template <typename RuleGenerator> + KeyedVector<SplitDescription, sp<Rule> > getRules() const; + +private: + Vector<SortedVector<SplitDescription> > mGroups; +}; + +SplitSelector::SplitSelector(const Vector<SplitDescription>& splits) + : mGroups(groupByMutualExclusivity(splits)) { +} + +static void selectBestFromGroup(const SortedVector<SplitDescription>& splits, + const SplitDescription& target, Vector<SplitDescription>& splitsOut) { + SplitDescription bestSplit; + bool isSet = false; + const size_t splitCount = splits.size(); + for (size_t j = 0; j < splitCount; j++) { + const SplitDescription& thisSplit = splits[j]; + if (!thisSplit.match(target)) { + continue; + } + + if (!isSet || thisSplit.isBetterThan(bestSplit, target)) { + isSet = true; + bestSplit = thisSplit; + } + } + + if (isSet) { + splitsOut.add(bestSplit); + } +} + +Vector<SplitDescription> SplitSelector::getBestSplits(const SplitDescription& target) const { + Vector<SplitDescription> bestSplits; + const size_t groupCount = mGroups.size(); + for (size_t i = 0; i < groupCount; i++) { + selectBestFromGroup(mGroups[i], target, bestSplits); + } + return bestSplits; +} + +template <typename RuleGenerator> +KeyedVector<SplitDescription, sp<Rule> > SplitSelector::getRules() const { + KeyedVector<SplitDescription, sp<Rule> > rules; + + const size_t groupCount = mGroups.size(); + for (size_t i = 0; i < groupCount; i++) { + const SortedVector<SplitDescription>& splits = mGroups[i]; + const size_t splitCount = splits.size(); + for (size_t j = 0; j < splitCount; j++) { + sp<Rule> rule = Rule::simplify(RuleGenerator::generate(splits, j)); + if (rule != NULL) { + rules.add(splits[j], rule); + } + } + } + return rules; +} + +Vector<SplitDescription> select(const SplitDescription& target, const Vector<SplitDescription>& splits) { + const SplitSelector selector(splits); + return selector.getBestSplits(target); +} + +void generate(const KeyedVector<String8, Vector<SplitDescription> >& splits) { + Vector<SplitDescription> allSplits; + const size_t apkSplitCount = splits.size(); + for (size_t i = 0; i < apkSplitCount; i++) { + allSplits.appendVector(splits[i]); + } + const SplitSelector selector(allSplits); + KeyedVector<SplitDescription, sp<Rule> > rules(selector.getRules<RuleGenerator>()); + + fprintf(stdout, "[\n"); + for (size_t i = 0; i < apkSplitCount; i++) { + sp<Rule> masterRule = new Rule(); + masterRule->op = Rule::OR_SUBRULES; + const Vector<SplitDescription>& splitDescriptions = splits[i]; + const size_t splitDescriptionCount = splitDescriptions.size(); + for (size_t j = 0; j < splitDescriptionCount; j++) { + masterRule->subrules.add(rules.valueFor(splitDescriptions[j])); + } + masterRule = Rule::simplify(masterRule); + fprintf(stdout, " {\n \"path\": \"%s\",\n \"rules\": %s\n }%s\n", + splits.keyAt(i).string(), + masterRule->toJson(2).string(), + i < apkSplitCount - 1 ? "," : ""); + } + fprintf(stdout, "]\n"); +} + +static void removeRuntimeQualifiers(ConfigDescription* outConfig) { + outConfig->imsi = 0; + outConfig->orientation = ResTable_config::ORIENTATION_ANY; + outConfig->screenWidth = ResTable_config::SCREENWIDTH_ANY; + outConfig->screenHeight = ResTable_config::SCREENHEIGHT_ANY; + outConfig->uiMode &= ResTable_config::UI_MODE_NIGHT_ANY; +} + +static Vector<SplitDescription> extractSplitDescriptionsFromApk(const String8& path) { + AssetManager assetManager; + Vector<SplitDescription> splits; + int32_t cookie = 0; + if (!assetManager.addAssetPath(path, &cookie)) { + return splits; + } + + const ResTable& res = assetManager.getResources(false); + if (res.getError() == NO_ERROR) { + Vector<ResTable_config> configs; + res.getConfigurations(&configs); + const size_t configCount = configs.size(); + for (size_t i = 0; i < configCount; i++) { + splits.add(); + splits.editTop().config = configs[i]; + } + } + + AssetDir* dir = assetManager.openNonAssetDir(cookie, "lib"); + if (dir != NULL) { + const size_t fileCount = dir->getFileCount(); + for (size_t i = 0; i < fileCount; i++) { + splits.add(); + Vector<String8> parts = AaptUtil::splitAndLowerCase(dir->getFileName(i), '-'); + if (parseAbi(parts, 0, &splits.editTop()) < 0) { + fprintf(stderr, "Malformed library %s\n", dir->getFileName(i).string()); + splits.pop(); + } + } + delete dir; + } + return splits; +} + +static int main(int argc, char** argv) { + // Skip over the first argument. + argc--; + argv++; + + bool generateFlag = false; + String8 targetConfigStr; + Vector<String8> splitApkPaths; + while (argc > 0) { + const String8 arg(*argv); + if (arg == "--target") { + argc--; + argv++; + if (argc < 1) { + fprintf(stderr, "Missing parameter for --split.\n"); + usage(); + return 1; + } + targetConfigStr.setTo(*argv); + } else if (arg == "--split") { + argc--; + argv++; + if (argc < 1) { + fprintf(stderr, "Missing parameter for --split.\n"); + usage(); + return 1; + } + splitApkPaths.add(String8(*argv)); + } else if (arg == "--generate") { + generateFlag = true; + } else if (arg == "--help") { + help(); + return 0; + } else { + fprintf(stderr, "Unknown argument '%s'\n", arg.string()); + usage(); + return 1; + } + argc--; + argv++; + } + + if (!generateFlag && targetConfigStr == "") { + usage(); + return 1; + } + + if (splitApkPaths.size() == 0) { + usage(); + return 1; + } + + SplitDescription targetSplit; + if (!generateFlag) { + if (!SplitDescription::parse(targetConfigStr, &targetSplit)) { + fprintf(stderr, "Invalid --target config: '%s'\n", + targetConfigStr.string()); + usage(); + return 1; + } + + // We don't want to match on things that will change at run-time + // (orientation, w/h, etc.). + removeRuntimeQualifiers(&targetSplit.config); + } + + KeyedVector<String8, Vector<SplitDescription> > apkPathSplitMap; + KeyedVector<SplitDescription, String8> splitApkPathMap; + Vector<SplitDescription> splitConfigs; + const size_t splitCount = splitApkPaths.size(); + for (size_t i = 0; i < splitCount; i++) { + Vector<SplitDescription> splits = extractSplitDescriptionsFromApk(splitApkPaths[i]); + if (splits.isEmpty()) { + fprintf(stderr, "Invalid --split path: '%s'. No splits found.\n", + splitApkPaths[i].string()); + usage(); + return 1; + } + apkPathSplitMap.replaceValueFor(splitApkPaths[i], splits); + const size_t apkSplitDescriptionCount = splits.size(); + for (size_t j = 0; j < apkSplitDescriptionCount; j++) { + splitApkPathMap.replaceValueFor(splits[j], splitApkPaths[i]); + } + splitConfigs.appendVector(splits); + } + + if (!generateFlag) { + Vector<SplitDescription> matchingConfigs = select(targetSplit, splitConfigs); + const size_t matchingConfigCount = matchingConfigs.size(); + SortedVector<String8> matchingSplitPaths; + for (size_t i = 0; i < matchingConfigCount; i++) { + matchingSplitPaths.add(splitApkPathMap.valueFor(matchingConfigs[i])); + } + + const size_t matchingSplitApkPathCount = matchingSplitPaths.size(); + for (size_t i = 0; i < matchingSplitApkPathCount; i++) { + fprintf(stderr, "%s\n", matchingSplitPaths[i].string()); + } + } else { + generate(apkPathSplitMap); + } + return 0; +} + +} // namespace split + +int main(int argc, char** argv) { + return split::main(argc, argv); +} diff --git a/tools/split-select/Rule.cpp b/tools/split-select/Rule.cpp new file mode 100644 index 000000000000..9559fe2fea1b --- /dev/null +++ b/tools/split-select/Rule.cpp @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2014 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. + */ + +#include "Rule.h" + +#include <utils/String8.h> + +using namespace android; + +namespace split { + +inline static void indentStr(String8& str, int indent) { + while (indent > 0) { + str.append(" "); + indent--; + } +} + +String8 Rule::toJson(int indent) const { + String8 str; + indentStr(str, indent); + str.append("{\n"); + indent++; + indentStr(str, indent); + str.append("\"op\": \""); + switch (op) { + case ALWAYS_TRUE: + str.append("ALWAYS_TRUE"); + break; + case GREATER_THAN: + str.append("GREATER_THAN"); + break; + case LESS_THAN: + str.append("LESS_THAN"); + break; + case EQUALS: + str.append("EQUALS"); + break; + case AND_SUBRULES: + str.append("AND_SUBRULES"); + break; + case OR_SUBRULES: + str.append("OR_SUBRULES"); + break; + case CONTAINS_ANY: + str.append("CONTAINS_ANY"); + break; + default: + str.appendFormat("%d", op); + break; + } + str.append("\""); + + if (negate) { + str.append(",\n"); + indentStr(str, indent); + str.append("\"negate\": true"); + } + + bool includeKey = true; + switch (op) { + case AND_SUBRULES: + case OR_SUBRULES: + includeKey = false; + break; + default: + break; + } + + if (includeKey) { + str.append(",\n"); + indentStr(str, indent); + str.append("\"property\": \""); + switch (key) { + case NONE: + str.append("NONE"); + break; + case SDK_VERSION: + str.append("SDK_VERSION"); + break; + case SCREEN_DENSITY: + str.append("SCREEN_DENSITY"); + break; + case NATIVE_PLATFORM: + str.append("NATIVE_PLATFORM"); + break; + case LANGUAGE: + str.append("LANGUAGE"); + break; + default: + str.appendFormat("%d", key); + break; + } + str.append("\""); + } + + if (op == AND_SUBRULES || op == OR_SUBRULES) { + str.append(",\n"); + indentStr(str, indent); + str.append("\"subrules\": [\n"); + const size_t subruleCount = subrules.size(); + for (size_t i = 0; i < subruleCount; i++) { + str.append(subrules[i]->toJson(indent + 1)); + if (i != subruleCount - 1) { + str.append(","); + } + str.append("\n"); + } + indentStr(str, indent); + str.append("]"); + } else { + switch (key) { + case SDK_VERSION: + case SCREEN_DENSITY: { + str.append(",\n"); + indentStr(str, indent); + str.append("\"args\": ["); + const size_t argCount = longArgs.size(); + for (size_t i = 0; i < argCount; i++) { + if (i != 0) { + str.append(", "); + } + str.appendFormat("%d", longArgs[i]); + } + str.append("]"); + break; + } + case LANGUAGE: + case NATIVE_PLATFORM: { + str.append(",\n"); + indentStr(str, indent); + str.append("\"args\": ["); + const size_t argCount = stringArgs.size(); + for (size_t i = 0; i < argCount; i++) { + if (i != 0) { + str.append(", "); + } + str.append(stringArgs[i]); + } + str.append("]"); + break; + } + default: + break; + } + } + str.append("\n"); + indent--; + indentStr(str, indent); + str.append("}"); + return str; +} + +sp<Rule> Rule::simplify(sp<Rule> rule) { + if (rule->op != AND_SUBRULES && rule->op != OR_SUBRULES) { + return rule; + } + + Vector<sp<Rule> > newSubrules; + newSubrules.setCapacity(rule->subrules.size()); + const size_t subruleCount = rule->subrules.size(); + for (size_t i = 0; i < subruleCount; i++) { + sp<Rule> simplifiedRule = simplify(rule->subrules.editItemAt(i)); + if (simplifiedRule != NULL) { + if (simplifiedRule->op == rule->op) { + newSubrules.appendVector(simplifiedRule->subrules); + } else { + newSubrules.add(simplifiedRule); + } + } + } + + const size_t newSubruleCount = newSubrules.size(); + if (newSubruleCount == 0) { + return NULL; + } else if (subruleCount == 1) { + return newSubrules.editTop(); + } + rule->subrules = newSubrules; + return rule; +} + +} // namespace split diff --git a/tools/split-select/Rule.h b/tools/split-select/Rule.h new file mode 100644 index 000000000000..8029931f7c6a --- /dev/null +++ b/tools/split-select/Rule.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2014 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. + */ + +#ifndef H_ANDROID_SPLIT_RULE +#define H_ANDROID_SPLIT_RULE + +#include "SplitDescription.h" + +#include <utils/RefBase.h> +#include <utils/StrongPointer.h> +#include <utils/String8.h> +#include <utils/Vector.h> + +namespace split { + +struct Rule : public virtual android::RefBase { + inline Rule(); + + enum Operator { + LESS_THAN = 1, + GREATER_THAN, + EQUALS, + CONTAINS_ANY, + CONTAINS_ALL, + IS_TRUE, + IS_FALSE, + AND_SUBRULES, + OR_SUBRULES, + ALWAYS_TRUE, + }; + + Operator op; + + enum Key { + NONE = 0, + SDK_VERSION, + SCREEN_DENSITY, + LANGUAGE, + NATIVE_PLATFORM, + TOUCH_SCREEN, + SCREEN_SIZE, + SCREEN_LAYOUT, + }; + + Key key; + bool negate; + + android::Vector<android::String8> stringArgs; + android::Vector<int> longArgs; + android::Vector<double> doubleArgs; + android::Vector<android::sp<Rule> > subrules; + + android::String8 toJson(int indent=0) const; + + static android::sp<Rule> simplify(android::sp<Rule> rule); +}; + +Rule::Rule() +: op(ALWAYS_TRUE) +, key(NONE) +, negate(false) {} + +} // namespace split + +#endif // H_ANDROID_SPLIT_RULE diff --git a/tools/split-select/RuleGenerator.cpp b/tools/split-select/RuleGenerator.cpp new file mode 100644 index 000000000000..669ae781aace --- /dev/null +++ b/tools/split-select/RuleGenerator.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2014 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. + */ + +#include "RuleGenerator.h" + +#include <algorithm> +#include <cmath> +#include <vector> +#include <androidfw/ResourceTypes.h> + +using namespace android; + +namespace split { + +// Calculate the point at which the density selection changes between l and h. +static inline int findMid(int l, int h) { + double root = sqrt((h*h) + (8*l*h)); + return (double(-h) + root) / 2.0; +} + +sp<Rule> RuleGenerator::generateDensity(const Vector<int>& allDensities, size_t index) { + sp<Rule> densityRule = new Rule(); + densityRule->op = Rule::AND_SUBRULES; + + const bool anyDensity = allDensities[index] == ResTable_config::DENSITY_ANY; + sp<Rule> any = new Rule(); + any->op = Rule::EQUALS; + any->key = Rule::SCREEN_DENSITY; + any->longArgs.add((int)ResTable_config::DENSITY_ANY); + any->negate = !anyDensity; + densityRule->subrules.add(any); + + if (!anyDensity) { + if (index > 0) { + sp<Rule> gt = new Rule(); + gt->op = Rule::GREATER_THAN; + gt->key = Rule::SCREEN_DENSITY; + gt->longArgs.add(findMid(allDensities[index - 1], allDensities[index]) - 1); + densityRule->subrules.add(gt); + } + + if (index + 1 < allDensities.size() && allDensities[index + 1] != ResTable_config::DENSITY_ANY) { + sp<Rule> lt = new Rule(); + lt->op = Rule::LESS_THAN; + lt->key = Rule::SCREEN_DENSITY; + lt->longArgs.add(findMid(allDensities[index], allDensities[index + 1])); + densityRule->subrules.add(lt); + } + } + return densityRule; +} + +sp<Rule> RuleGenerator::generateAbi(const Vector<abi::Variant>& splitAbis, size_t index) { + const abi::Variant thisAbi = splitAbis[index]; + const std::vector<abi::Variant>& familyVariants = abi::getVariants(abi::getFamily(thisAbi)); + + std::vector<abi::Variant>::const_iterator start = + std::find(familyVariants.begin(), familyVariants.end(), thisAbi); + + std::vector<abi::Variant>::const_iterator end = familyVariants.end(); + if (index + 1 < splitAbis.size()) { + end = std::find(start, familyVariants.end(), splitAbis[index + 1]); + } + + sp<Rule> abiRule = new Rule(); + abiRule->op = Rule::CONTAINS_ANY; + abiRule->key = Rule::NATIVE_PLATFORM; + while (start != end) { + abiRule->stringArgs.add(String8(abi::toString(*start))); + ++start; + } + return abiRule; +} + +sp<Rule> RuleGenerator::generate(const SortedVector<SplitDescription>& group, size_t index) { + sp<Rule> rootRule = new Rule(); + rootRule->op = Rule::AND_SUBRULES; + + if (group[index].config.locale != 0) { + sp<Rule> locale = new Rule(); + locale->op = Rule::EQUALS; + locale->key = Rule::LANGUAGE; + char str[RESTABLE_MAX_LOCALE_LEN]; + group[index].config.getBcp47Locale(str); + locale->stringArgs.add(String8(str)); + rootRule->subrules.add(locale); + } + + if (group[index].config.sdkVersion != 0) { + sp<Rule> sdk = new Rule(); + sdk->op = Rule::GREATER_THAN; + sdk->key = Rule::SDK_VERSION; + sdk->longArgs.add(group[index].config.sdkVersion - 1); + rootRule->subrules.add(sdk); + } + + if (group[index].config.density != 0) { + size_t densityIndex = 0; + Vector<int> allDensities; + allDensities.add(group[index].config.density); + + const size_t groupSize = group.size(); + for (size_t i = 0; i < groupSize; i++) { + if (group[i].config.density != group[index].config.density) { + // This group differs by density. + allDensities.clear(); + for (size_t j = 0; j < groupSize; j++) { + allDensities.add(group[j].config.density); + } + densityIndex = index; + break; + } + } + rootRule->subrules.add(generateDensity(allDensities, densityIndex)); + } + + if (group[index].abi != abi::Variant::none) { + size_t abiIndex = 0; + Vector<abi::Variant> allVariants; + allVariants.add(group[index].abi); + + const size_t groupSize = group.size(); + for (size_t i = 0; i < groupSize; i++) { + if (group[i].abi != group[index].abi) { + // This group differs by ABI. + allVariants.clear(); + for (size_t j = 0; j < groupSize; j++) { + allVariants.add(group[j].abi); + } + abiIndex = index; + break; + } + } + rootRule->subrules.add(generateAbi(allVariants, abiIndex)); + } + + return rootRule; +} + +} // namespace split diff --git a/tools/split-select/RuleGenerator.h b/tools/split-select/RuleGenerator.h new file mode 100644 index 000000000000..619acd92287c --- /dev/null +++ b/tools/split-select/RuleGenerator.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2014 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. + */ + +#ifndef H_ANDROID_SPLIT_RULE_GENERATOR +#define H_ANDROID_SPLIT_RULE_GENERATOR + +#include "Abi.h" +#include "Rule.h" +#include "SplitDescription.h" + +#include <utils/SortedVector.h> +#include <utils/Vector.h> + +namespace split { + +struct RuleGenerator { + // Generate rules for a Split given the group of mutually exclusive splits it belongs to + static android::sp<Rule> generate(const android::SortedVector<SplitDescription>& group, size_t index); + + static android::sp<Rule> generateAbi(const android::Vector<abi::Variant>& allVariants, size_t index); + static android::sp<Rule> generateDensity(const android::Vector<int>& allDensities, size_t index); +}; + +} // namespace split + +#endif // H_ANDROID_SPLIT_RULE_GENERATOR diff --git a/tools/split-select/RuleGenerator_test.cpp b/tools/split-select/RuleGenerator_test.cpp new file mode 100644 index 000000000000..60baabe414b4 --- /dev/null +++ b/tools/split-select/RuleGenerator_test.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2014 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. + */ + +#include "RuleGenerator.h" + +#include <algorithm> +#include <gtest/gtest.h> +#include <utils/String8.h> + +using namespace android; + +namespace split { + +static void expectDensityRule(const Vector<int>& densities, int density, int greaterThan, int lessThan); +static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant, + std::initializer_list<const char*> matches); + +TEST(RuleGeneratorTest, testAbiRules) { + Vector<abi::Variant> abis; + abis.add(abi::Variant::armeabi); + abis.add(abi::Variant::armeabi_v7a); + abis.add(abi::Variant::x86); + std::sort(abis.begin(), abis.end()); + + expectAbiRule(abis, abi::Variant::armeabi, {"armeabi"}); + expectAbiRule(abis, abi::Variant::armeabi_v7a, {"armeabi-v7a", "arm64-v8a"}); + expectAbiRule(abis, abi::Variant::x86, {"x86", "x86_64"}); +} + +TEST(RuleGeneratorTest, testDensityRules) { + Vector<int> densities; + densities.add(ConfigDescription::DENSITY_HIGH); + densities.add(ConfigDescription::DENSITY_XHIGH); + densities.add(ConfigDescription::DENSITY_XXHIGH); + densities.add(ConfigDescription::DENSITY_ANY); + + ASSERT_LT(263, ConfigDescription::DENSITY_XHIGH); + ASSERT_GT(262, ConfigDescription::DENSITY_HIGH); + ASSERT_LT(363, ConfigDescription::DENSITY_XXHIGH); + ASSERT_GT(362, ConfigDescription::DENSITY_XHIGH); + + expectDensityRule(densities, ConfigDescription::DENSITY_HIGH, 0, 263); + expectDensityRule(densities, ConfigDescription::DENSITY_XHIGH, 262, 363); + expectDensityRule(densities, ConfigDescription::DENSITY_XXHIGH, 362, 0); + expectDensityRule(densities, ConfigDescription::DENSITY_ANY, 0, 0); +} + +// +// Helper methods. +// + +static void expectDensityRule(const Vector<int>& densities, int density, int greaterThan, int lessThan) { + const int* iter = std::find(densities.begin(), densities.end(), density); + if (densities.end() == iter) { + ADD_FAILURE() << density << "dpi was not in the density list."; + return; + } + + sp<Rule> rule = RuleGenerator::generateDensity(densities, iter - densities.begin()); + if (rule->op != Rule::AND_SUBRULES) { + ADD_FAILURE() << "Op in rule for " << density << "dpi is not Rule::AND_SUBRULES."; + return; + } + + size_t index = 0; + + bool isAnyDpi = density == ConfigDescription::DENSITY_ANY; + + sp<Rule> anyDpiRule = rule->subrules[index++]; + EXPECT_EQ(Rule::EQUALS, anyDpiRule->op) + << "for " << density << "dpi ANY DPI rule"; + EXPECT_EQ(Rule::SCREEN_DENSITY, anyDpiRule->key) + << "for " << density << "dpi ANY DPI rule"; + EXPECT_EQ(isAnyDpi == false, anyDpiRule->negate) + << "for " << density << "dpi ANY DPI rule"; + if (anyDpiRule->longArgs.size() == 1) { + EXPECT_EQ(ConfigDescription::DENSITY_ANY, anyDpiRule->longArgs[0]) + << "for " << density << "dpi ANY DPI rule"; + } else { + EXPECT_EQ(1u, anyDpiRule->longArgs.size()) + << "for " << density << "dpi ANY DPI rule"; + } + + + if (greaterThan != 0) { + sp<Rule> greaterThanRule = rule->subrules[index++]; + EXPECT_EQ(Rule::GREATER_THAN, greaterThanRule->op) + << "for " << density << "dpi GREATER_THAN rule"; + EXPECT_EQ(Rule::SCREEN_DENSITY, greaterThanRule->key) + << "for " << density << "dpi GREATER_THAN rule"; + if (greaterThanRule->longArgs.size() == 1) { + EXPECT_EQ(greaterThan, greaterThanRule->longArgs[0]) + << "for " << density << "dpi GREATER_THAN rule"; + } else { + EXPECT_EQ(1u, greaterThanRule->longArgs.size()) + << "for " << density << "dpi GREATER_THAN rule"; + } + } + + if (lessThan != 0) { + sp<Rule> lessThanRule = rule->subrules[index++]; + EXPECT_EQ(Rule::LESS_THAN, lessThanRule->op) + << "for " << density << "dpi LESS_THAN rule"; + EXPECT_EQ(Rule::SCREEN_DENSITY, lessThanRule->key) + << "for " << density << "dpi LESS_THAN rule"; + if (lessThanRule->longArgs.size() == 1) { + EXPECT_EQ(lessThan, lessThanRule->longArgs[0]) + << "for " << density << "dpi LESS_THAN rule"; + } else { + EXPECT_EQ(1u, lessThanRule->longArgs.size()) + << "for " << density << "dpi LESS_THAN rule"; + } + } +} + +static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant, + std::initializer_list<const char*> matches) { + const abi::Variant* iter = std::find(abis.begin(), abis.end(), variant); + if (abis.end() == iter) { + ADD_FAILURE() << abi::toString(variant) << " was not in the abi list."; + return; + } + + sp<Rule> rule = RuleGenerator::generateAbi(abis, iter - abis.begin()); + + EXPECT_EQ(Rule::CONTAINS_ANY, rule->op) + << "for " << abi::toString(variant) << " rule"; + EXPECT_EQ(Rule::NATIVE_PLATFORM, rule->key) + << " for " << abi::toString(variant) << " rule"; + EXPECT_EQ(matches.size(), rule->stringArgs.size()) + << " for " << abi::toString(variant) << " rule"; + + for (const char* match : matches) { + if (rule->stringArgs.end() == + std::find(rule->stringArgs.begin(), rule->stringArgs.end(), String8(match))) { + ADD_FAILURE() << "Rule for abi " << abi::toString(variant) + << " does not contain match for expected abi " << match; + } + } +} + +} // namespace split diff --git a/tools/split-select/Rule_test.cpp b/tools/split-select/Rule_test.cpp new file mode 100644 index 000000000000..aca74331dfc8 --- /dev/null +++ b/tools/split-select/Rule_test.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2014 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. + */ + +#include "Rule.h" + +#include "SplitDescription.h" + +#include <algorithm> +#include <string> +#include <gtest/gtest.h> +#include <utils/String8.h> + +using namespace android; + +namespace split { + +TEST(RuleTest, generatesValidJson) { + sp<Rule> rule = new Rule(); + rule->op = Rule::AND_SUBRULES; + + sp<Rule> subrule = new Rule(); + subrule->op = Rule::EQUALS; + subrule->key = Rule::SDK_VERSION; + subrule->longArgs.add(7); + rule->subrules.add(subrule); + + subrule = new Rule(); + subrule->op = Rule::OR_SUBRULES; + rule->subrules.add(subrule); + + sp<Rule> subsubrule = new Rule(); + subsubrule->op = Rule::GREATER_THAN; + subsubrule->key = Rule::SCREEN_DENSITY; + subsubrule->longArgs.add(10); + subrule->subrules.add(subsubrule); + + subsubrule = new Rule(); + subsubrule->op = Rule::LESS_THAN; + subsubrule->key = Rule::SCREEN_DENSITY; + subsubrule->longArgs.add(5); + subrule->subrules.add(subsubrule); + + std::string expected( + "{" + " \"op\": \"AND_SUBRULES\"," + " \"subrules\": [" + " {" + " \"op\": \"EQUALS\"," + " \"property\": \"SDK_VERSION\"," + " \"args\": [7]" + " }," + " {" + " \"op\": \"OR_SUBRULES\"," + " \"subrules\": [" + " {" + " \"op\": \"GREATER_THAN\"," + " \"property\": \"SCREEN_DENSITY\"," + " \"args\": [10]" + " }," + " {" + " \"op\": \"LESS_THAN\"," + " \"property\": \"SCREEN_DENSITY\"," + " \"args\": [5]" + " }" + " ]" + " }" + " ]" + "}"); + // Trim + expected.erase(std::remove_if(expected.begin(), expected.end(), ::isspace), expected.end()); + + std::string result(rule->toJson().string()); + + // Trim + result.erase(std::remove_if(result.begin(), result.end(), ::isspace), result.end()); + + ASSERT_EQ(expected, result); +} + +TEST(RuleTest, simplifiesSingleSubruleRules) { + sp<Rule> rule = new Rule(); + rule->op = Rule::AND_SUBRULES; + + sp<Rule> subrule = new Rule(); + subrule->op = Rule::EQUALS; + subrule->key = Rule::SDK_VERSION; + subrule->longArgs.add(7); + rule->subrules.add(subrule); + + sp<Rule> simplified = Rule::simplify(rule); + EXPECT_EQ(Rule::EQUALS, simplified->op); + EXPECT_EQ(Rule::SDK_VERSION, simplified->key); + ASSERT_EQ(1u, simplified->longArgs.size()); + EXPECT_EQ(7, simplified->longArgs[0]); +} + +TEST(RuleTest, simplifiesNestedSameOpSubrules) { + sp<Rule> rule = new Rule(); + rule->op = Rule::AND_SUBRULES; + + sp<Rule> subrule = new Rule(); + subrule->op = Rule::AND_SUBRULES; + rule->subrules.add(subrule); + + sp<Rule> subsubrule = new Rule(); + subsubrule->op = Rule::EQUALS; + subsubrule->key = Rule::SDK_VERSION; + subsubrule->longArgs.add(7); + subrule->subrules.add(subsubrule); + + subrule = new Rule(); + subrule->op = Rule::EQUALS; + subrule->key = Rule::SDK_VERSION; + subrule->longArgs.add(8); + rule->subrules.add(subrule); + + sp<Rule> simplified = Rule::simplify(rule); + EXPECT_EQ(Rule::AND_SUBRULES, simplified->op); + ASSERT_EQ(2u, simplified->subrules.size()); + + sp<Rule> simplifiedSubrule = simplified->subrules[0]; + EXPECT_EQ(Rule::EQUALS, simplifiedSubrule->op); + EXPECT_EQ(Rule::SDK_VERSION, simplifiedSubrule->key); + ASSERT_EQ(1u, simplifiedSubrule->longArgs.size()); + EXPECT_EQ(7, simplifiedSubrule->longArgs[0]); + + simplifiedSubrule = simplified->subrules[1]; + EXPECT_EQ(Rule::EQUALS, simplifiedSubrule->op); + EXPECT_EQ(Rule::SDK_VERSION, simplifiedSubrule->key); + ASSERT_EQ(1u, simplifiedSubrule->longArgs.size()); + EXPECT_EQ(8, simplifiedSubrule->longArgs[0]); +} + +} // namespace split diff --git a/tools/split-select/SplitDescription.cpp b/tools/split-select/SplitDescription.cpp new file mode 100644 index 000000000000..8037ef01f909 --- /dev/null +++ b/tools/split-select/SplitDescription.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2014 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. + */ + +#include "SplitDescription.h" + +#include "aapt/AaptConfig.h" +#include "aapt/AaptUtil.h" + +#include <utils/String8.h> +#include <utils/Vector.h> + +using namespace android; + +namespace split { + +SplitDescription::SplitDescription() +: abi(abi::Variant::none) { +} + +int SplitDescription::compare(const SplitDescription& rhs) const { + int cmp; + cmp = (int)abi - (int)rhs.abi; + if (cmp != 0) return cmp; + return config.compareLogical(rhs.config); +} + +bool SplitDescription::isBetterThan(const SplitDescription& o, const SplitDescription& target) const { + if (abi != abi::Variant::none || o.abi != abi::Variant::none) { + abi::Family family = abi::getFamily(abi); + abi::Family oFamily = abi::getFamily(o.abi); + if (family != oFamily) { + return family != abi::Family::none; + } + + if (int(target.abi) - int(abi) < int(target.abi) - int(o.abi)) { + return true; + } + } + return config.isBetterThan(o.config, &target.config); +} + +bool SplitDescription::match(const SplitDescription& o) const { + if (abi != abi::Variant::none) { + abi::Family family = abi::getFamily(abi); + abi::Family oFamily = abi::getFamily(o.abi); + if (family != oFamily) { + return false; + } + + if (int(abi) > int(o.abi)) { + return false; + } + } + return config.match(o.config); +} + +String8 SplitDescription::toString() const { + String8 extension; + if (abi != abi::Variant::none) { + if (extension.isEmpty()) { + extension.append(":"); + } else { + extension.append("-"); + } + extension.append(abi::toString(abi)); + } + String8 str(config.toString()); + str.append(extension); + return str; +} + +ssize_t parseAbi(const Vector<String8>& parts, const ssize_t index, + SplitDescription* outSplit) { + const ssize_t N = parts.size(); + abi::Variant abi = abi::Variant::none; + ssize_t endIndex = index; + if (parts[endIndex] == "arm64") { + endIndex++; + if (endIndex < N) { + if (parts[endIndex] == "v8a") { + endIndex++; + abi = abi::Variant::arm64_v8a; + } + } + } else if (parts[endIndex] == "armeabi") { + endIndex++; + abi = abi::Variant::armeabi; + if (endIndex < N) { + if (parts[endIndex] == "v7a") { + endIndex++; + abi = abi::Variant::armeabi_v7a; + } + } + } else if (parts[endIndex] == "x86") { + endIndex++; + abi = abi::Variant::x86; + } else if (parts[endIndex] == "x86_64") { + endIndex++; + abi = abi::Variant::x86_64; + } else if (parts[endIndex] == "mips") { + endIndex++; + abi = abi::Variant::mips; + } else if (parts[endIndex] == "mips64") { + endIndex++; + abi = abi::Variant::mips64; + } + + if (abi == abi::Variant::none && endIndex != index) { + return -1; + } + + if (outSplit != NULL) { + outSplit->abi = abi; + } + return endIndex; +} + +bool SplitDescription::parse(const String8& str, SplitDescription* outSplit) { + ssize_t index = str.find(":"); + + String8 configStr; + String8 extensionStr; + if (index >= 0) { + configStr.setTo(str.string(), index); + extensionStr.setTo(str.string() + index + 1); + } else { + configStr.setTo(str); + } + + SplitDescription split; + if (!AaptConfig::parse(configStr, &split.config)) { + return false; + } + + Vector<String8> parts = AaptUtil::splitAndLowerCase(extensionStr, '-'); + const ssize_t N = parts.size(); + index = 0; + + if (extensionStr.length() == 0) { + goto success; + } + + index = parseAbi(parts, index, &split); + if (index < 0) { + return false; + } else { + if (index == N) { + goto success; + } + } + + // Unrecognized + return false; + +success: + if (outSplit != NULL) { + *outSplit = split; + } + return true; +} + +} // namespace split diff --git a/tools/split-select/SplitDescription.h b/tools/split-select/SplitDescription.h new file mode 100644 index 000000000000..5fcafc86f9c4 --- /dev/null +++ b/tools/split-select/SplitDescription.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2014 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. + */ + +#ifndef H_ANDROID_SPLIT_SPLIT_DESCRIPTION +#define H_ANDROID_SPLIT_SPLIT_DESCRIPTION + +#include "aapt/ConfigDescription.h" +#include "Abi.h" + +#include <utils/String8.h> +#include <utils/Vector.h> + +namespace split { + +struct SplitDescription { + SplitDescription(); + SplitDescription(const SplitDescription&) = default; + + ConfigDescription config; + abi::Variant abi; + + int compare(const SplitDescription& rhs) const; + inline bool operator<(const SplitDescription& rhs) const; + inline bool operator==(const SplitDescription& rhs) const; + inline bool operator!=(const SplitDescription& rhs) const; + + bool match(const SplitDescription& o) const; + bool isBetterThan(const SplitDescription& o, const SplitDescription& target) const; + + android::String8 toString() const; + + static bool parse(const android::String8& str, SplitDescription* outSplit); +}; + +ssize_t parseAbi(const android::Vector<android::String8>& parts, const ssize_t index, + SplitDescription* outSplit); + +bool SplitDescription::operator<(const SplitDescription& rhs) const { + return compare(rhs) < 0; +} + +bool SplitDescription::operator==(const SplitDescription& rhs) const { + return compare(rhs) == 0; +} + +bool SplitDescription::operator!=(const SplitDescription& rhs) const { + return compare(rhs) != 0; +} + +} // namespace split + +#endif // H_ANDROID_SPLIT_SPLIT_DESCRIPTION diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 02e610cee9bf..0db7658b1928 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -977,7 +977,8 @@ public class WifiConfiguration implements Parcelable { if (this.didSelfAdd) sbuf.append(" didSelfAdd"); if (this.selfAdded) sbuf.append(" selfAdded"); if (this.noInternetAccess) sbuf.append(" noInternetAccess"); - if (this.didSelfAdd || this.selfAdded || this.noInternetAccess) { + if (this.ephemeral) sbuf.append(" ephemeral"); + if (this.didSelfAdd || this.selfAdded || this.noInternetAccess || this.ephemeral) { sbuf.append("\n"); } sbuf.append(" KeyMgmt:"); @@ -1434,6 +1435,7 @@ public class WifiConfiguration implements Parcelable { autoJoinStatus = source.autoJoinStatus; selfAdded = source.selfAdded; noInternetAccess = source.noInternetAccess; + ephemeral = source.ephemeral; if (source.visibility != null) { visibility = new Visibility(source.visibility); } @@ -1510,6 +1512,7 @@ public class WifiConfiguration implements Parcelable { dest.writeInt(selfAdded ? 1 : 0); dest.writeInt(didSelfAdd ? 1 : 0); dest.writeInt(noInternetAccess ? 1 : 0); + dest.writeInt(ephemeral ? 1 : 0); dest.writeInt(creatorUid); dest.writeInt(lastConnectUid); dest.writeInt(lastUpdateUid); @@ -1570,6 +1573,7 @@ public class WifiConfiguration implements Parcelable { config.selfAdded = in.readInt() != 0; config.didSelfAdd = in.readInt() != 0; config.noInternetAccess = in.readInt() != 0; + config.ephemeral = in.readInt() != 0; config.creatorUid = in.readInt(); config.lastConnectUid = in.readInt(); config.lastUpdateUid = in.readInt(); |