diff options
215 files changed, 4665 insertions, 2027 deletions
diff --git a/Android.mk b/Android.mk index 56e9df649f7b..8f7779ea2c32 100644 --- a/Android.mk +++ b/Android.mk @@ -175,6 +175,7 @@ LOCAL_SRC_FILES += \ core/java/android/nfc/INfcAdapterExtras.aidl \ core/java/android/nfc/INfcTag.aidl \ core/java/android/nfc/INfcCardEmulation.aidl \ + core/java/android/nfc/INfcLockscreenDispatch.aidl \ core/java/android/os/IBatteryPropertiesListener.aidl \ core/java/android/os/IBatteryPropertiesRegistrar.aidl \ core/java/android/os/ICancellationSignal.aidl \ diff --git a/api/current.txt b/api/current.txt index 16383885f99b..9643598fb3c5 100644 --- a/api/current.txt +++ b/api/current.txt @@ -937,6 +937,8 @@ package android { field public static final int progressTintMode = 16843878; // 0x1010466 field public static final int prompt = 16843131; // 0x101017b field public static final int propertyName = 16843489; // 0x10102e1 + field public static final int propertyXName = 16843894; // 0x1010476 + field public static final int propertyYName = 16843895; // 0x1010477 field public static final int protectionLevel = 16842761; // 0x1010009 field public static final int publicKey = 16843686; // 0x10103a6 field public static final int queryActionMsg = 16843227; // 0x10101db @@ -955,6 +957,7 @@ package android { field public static final int ratingBarStyleIndicator = 16843280; // 0x1010210 field public static final int ratingBarStyleSmall = 16842877; // 0x101007d field public static final int readPermission = 16842759; // 0x1010007 + field public static final int relinquishTaskIdentity = 16843896; // 0x1010478 field public static final int repeatCount = 16843199; // 0x10101bf field public static final int repeatMode = 16843200; // 0x10101c0 field public static final int reqFiveWayNav = 16843314; // 0x1010232 @@ -8090,6 +8093,7 @@ package android.content.pm { field public static final int FLAG_IMMERSIVE = 2048; // 0x800 field public static final int FLAG_MULTIPROCESS = 1; // 0x1 field public static final int FLAG_NO_HISTORY = 128; // 0x80 + field public static final int FLAG_RELINQUISH_TASK_IDENTITY = 4096; // 0x1000 field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000 field public static final int FLAG_STATE_NOT_NEEDED = 16; // 0x10 field public static final int LAUNCH_MULTIPLE = 0; // 0x0 @@ -12839,6 +12843,7 @@ package android.hardware.camera2.params { method public boolean isOutputSupportedFor(int); method public static boolean isOutputSupportedFor(java.lang.Class<T>); method public boolean isOutputSupportedFor(android.view.Surface); + field public static final long NO_MIN_FRAME_DURATION = 0L; // 0x0L } public final class TonemapCurve { @@ -13746,7 +13751,9 @@ package android.media { field public static final int CHANNEL_OUT_QUAD = 204; // 0xcc field public static final int CHANNEL_OUT_STEREO = 12; // 0xc field public static final int CHANNEL_OUT_SURROUND = 1052; // 0x41c + field public static final int ENCODING_AC3 = 5; // 0x5 field public static final int ENCODING_DEFAULT = 1; // 0x1 + field public static final int ENCODING_E_AC3 = 6; // 0x6 field public static final int ENCODING_INVALID = 0; // 0x0 field public static final int ENCODING_PCM_16BIT = 2; // 0x2 field public static final int ENCODING_PCM_8BIT = 3; // 0x3 @@ -13798,6 +13805,7 @@ package android.media { method public deprecated void setWiredHeadsetOn(boolean); method public deprecated boolean shouldVibrate(int); method public void startBluetoothSco(); + method public void startBluetoothScoVirtualCall(); method public void stopBluetoothSco(); method public void unloadSoundEffects(); method public void unregisterMediaButtonEventReceiver(android.content.ComponentName); @@ -13820,6 +13828,7 @@ package android.media { field public static final int AUDIOFOCUS_REQUEST_FAILED = 0; // 0x0 field public static final int AUDIOFOCUS_REQUEST_GRANTED = 1; // 0x1 field public static final int ERROR = -1; // 0xffffffff + field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa field public static final java.lang.String EXTRA_RINGER_MODE = "android.media.EXTRA_RINGER_MODE"; field public static final java.lang.String EXTRA_SCO_AUDIO_PREVIOUS_STATE = "android.media.extra.SCO_AUDIO_PREVIOUS_STATE"; field public static final java.lang.String EXTRA_SCO_AUDIO_STATE = "android.media.extra.SCO_AUDIO_STATE"; @@ -17639,6 +17648,7 @@ package android.nfc { method public boolean invokeBeam(android.app.Activity); method public boolean isEnabled(); method public boolean isNdefPushEnabled(); + method public boolean registerLockscreenDispatch(android.nfc.NfcAdapter.NfcLockscreenDispatch, int[]); method public void setBeamPushUris(android.net.Uri[], android.app.Activity); method public void setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity); method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...); @@ -17674,6 +17684,10 @@ package android.nfc { method public abstract android.nfc.NdefMessage createNdefMessage(android.nfc.NfcEvent); } + public static abstract interface NfcAdapter.NfcLockscreenDispatch { + method public abstract boolean onTagDetected(android.nfc.Tag); + } + public static abstract interface NfcAdapter.OnNdefPushCompleteCallback { method public abstract void onNdefPushComplete(android.nfc.NfcEvent); } @@ -23462,7 +23476,7 @@ package android.provider { field public static final java.lang.String CONTENT_DIRECTORY = "data"; } - public static final class ContactsContract.Contacts.Entity implements android.provider.BaseColumns android.provider.ContactsContract.BaseSyncColumns android.provider.ContactsContract.ContactNameColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns android.provider.ContactsContract.DataColumns android.provider.ContactsContract.RawContactsColumns android.provider.ContactsContract.StatusColumns android.provider.ContactsContract.SyncColumns { + public static final class ContactsContract.Contacts.Entity implements android.provider.BaseColumns android.provider.ContactsContract.BaseSyncColumns android.provider.ContactsContract.ContactNameColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns android.provider.ContactsContract.DataColumns android.provider.ContactsContract.DataUsageStatColumns android.provider.ContactsContract.RawContactsColumns android.provider.ContactsContract.StatusColumns android.provider.ContactsContract.SyncColumns { field public static final java.lang.String CONTENT_DIRECTORY = "entities"; field public static final java.lang.String DATA_ID = "data_id"; field public static final java.lang.String RAW_CONTACT_ID = "raw_contact_id"; @@ -27796,7 +27810,6 @@ package android.telecomm { field public static final java.lang.String ACTION_CALL_SERVICE; field public static final java.lang.String ACTION_CALL_SERVICE_PROVIDER; field public static final java.lang.String ACTION_CALL_SERVICE_SELECTOR; - field public static final java.lang.String ACTION_CHANGE_DEFAULT_PHONE = "android.telecomm.ACTION_CHANGE_DEFAULT_PHONE"; field public static final java.lang.String ACTION_INCOMING_CALL = "android.intent.action.INCOMING_CALL"; field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ',' field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';' @@ -27804,7 +27817,6 @@ package android.telecomm { field public static final java.lang.String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecomm.extra.CALL_DISCONNECT_MESSAGE"; field public static final java.lang.String EXTRA_CALL_SERVICE_DESCRIPTOR = "android.intent.extra.CALL_SERVICE_DESCRIPTOR"; field public static final java.lang.String EXTRA_INCOMING_CALL_EXTRAS = "android.intent.extra.INCOMING_CALL_EXTRAS"; - field public static final java.lang.String EXTRA_PACKAGE_NAME = "package"; field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.intent.extra.START_CALL_WITH_SPEAKERPHONE"; } diff --git a/cmds/media/src/com/android/commands/media/Media.java b/cmds/media/src/com/android/commands/media/Media.java index 92c6a51e8849..4e9136130c6c 100644 --- a/cmds/media/src/com/android/commands/media/Media.java +++ b/cmds/media/src/com/android/commands/media/Media.java @@ -17,12 +17,19 @@ package com.android.commands.media; -import android.app.PendingIntent; +import android.app.ActivityManager; import android.content.Context; -import android.graphics.Bitmap; -import android.media.IAudioService; -import android.media.IRemoteControlDisplay; +import android.media.MediaMetadata; +import android.media.session.ISessionController; +import android.media.session.ISessionManager; +import android.media.session.MediaController; +import android.media.session.MediaSessionInfo; +import android.media.session.PlaybackState; +import android.media.session.RouteInfo; import android.os.Bundle; +import android.os.HandlerThread; +import android.os.IBinder; +import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; @@ -30,16 +37,17 @@ import android.util.AndroidException; import android.view.InputDevice; import android.view.KeyCharacterMap; import android.view.KeyEvent; + import com.android.internal.os.BaseCommand; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; +import java.util.List; public class Media extends BaseCommand { - - private IAudioService mAudioService; + private ISessionManager mSessionService; /** * Command-line entry point. @@ -54,29 +62,35 @@ public class Media extends BaseCommand { out.println( "usage: media [subcommand] [options]\n" + " media dispatch KEY\n" + - " media remote-display\n" + + " media list-sessions\n" + + " media monitor <sessionId>\n" + "\n" + - "media dispatch: dispatch a media key to the current media client.\n" + + "media dispatch: dispatch a media key to the system.\n" + " KEY may be: play, pause, play-pause, mute, headsethook,\n" + - " stop, next, previous, rewind, recordm fast-forword.\n" + - "media remote-display: monitor remote display updates.\n" + " stop, next, previous, rewind, record, fast-forword.\n" + + "media list-sessions: print a list of the current sessions.\n" + + "media monitor: monitor updates to the specified session.\n" + + " Use the sessionId from list-sessions.\n" ); } public void onRun() throws Exception { - mAudioService = IAudioService.Stub.asInterface(ServiceManager.checkService( - Context.AUDIO_SERVICE)); - if (mAudioService == null) { + mSessionService = ISessionManager.Stub.asInterface(ServiceManager.checkService( + Context.MEDIA_SESSION_SERVICE)); + if (mSessionService == null) { System.err.println(NO_SYSTEM_ERROR_CODE); - throw new AndroidException("Can't connect to audio service; is the system running?"); + throw new AndroidException( + "Can't connect to media session service; is the system running?"); } String op = nextArgRequired(); if (op.equals("dispatch")) { runDispatch(); - } else if (op.equals("remote-display")) { - runRemoteDisplay(); + } else if (op.equals("list-sessions")) { + runListSessions(); + } else if (op.equals("monitor")) { + runMonitor(); } else { showError("Error: unknown command '" + op + "'"); return; @@ -85,11 +99,39 @@ public class Media extends BaseCommand { private void sendMediaKey(KeyEvent event) { try { - mAudioService.dispatchMediaKeyEvent(event); + mSessionService.dispatchMediaKeyEvent(event, false); } catch (RemoteException e) { } } + private void runMonitor() throws Exception { + String id = nextArgRequired(); + if (id == null) { + showError("Error: must include a session id"); + return; + } + boolean success = false; + try { + List<IBinder> sessions = mSessionService + .getSessions(null, ActivityManager.getCurrentUser()); + for (IBinder session : sessions) { + MediaController controller = MediaController.fromBinder(ISessionController.Stub + .asInterface(session)); + if (controller != null && controller.getSessionInfo().getId().equals(id)) { + ControllerMonitor monitor = new ControllerMonitor(controller); + monitor.run(); + success = true; + break; + } + } + } catch (Exception e) { + System.out.println("***Error monitoring session*** " + e.getMessage()); + } + if (!success) { + System.out.println("No session found with id " + id); + } + } + private void runDispatch() throws Exception { String cmd = nextArgRequired(); int keycode; @@ -127,65 +169,49 @@ public class Media extends BaseCommand { KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD)); } - class RemoteDisplayMonitor extends IRemoteControlDisplay.Stub { - RemoteDisplayMonitor() { - } + class ControllerMonitor extends MediaController.Callback { + private final MediaController mController; - - @Override - public void setCurrentClientId(int clientGeneration, PendingIntent clientMediaIntent, - boolean clearing) { - System.out.println("New client: id=" + clientGeneration - + " intent=" + clientMediaIntent + " clearing=" + clearing); + public ControllerMonitor(MediaController controller) { + mController = controller; } - @Override - public void setEnabled(boolean enabled) { - System.out.println("New enable state= " + (enabled ? "enabled" : "disabled")); + public void onSessionEvent(String event, Bundle extras) { + System.out.println("onSessionEvent event=" + event + ", extras=" + extras); } @Override - public void setPlaybackState(int generationId, int state, long stateChangeTimeMs, - long currentPosMs, float speed) { - System.out.println("New state: id=" + generationId + " state=" + state - + " time=" + stateChangeTimeMs + " pos=" + currentPosMs + " speed=" + speed); + public void onRouteChanged(RouteInfo route) { + System.out.println("onRouteChanged " + route); } @Override - public void setTransportControlInfo(int generationId, int transportControlFlags, - int posCapabilities) { - System.out.println("New control info: id=" + generationId - + " flags=0x" + Integer.toHexString(transportControlFlags) - + " cap=0x" + Integer.toHexString(posCapabilities)); + public void onPlaybackStateChanged(PlaybackState state) { + System.out.println("onPlaybackStateChanged " + state); } @Override - public void setMetadata(int generationId, Bundle metadata) { - System.out.println("New metadata: id=" + generationId - + " data=" + metadata); - } - - @Override - public void setArtwork(int generationId, Bitmap artwork) { - System.out.println("New artwork: id=" + generationId - + " art=" + artwork); - } - - @Override - public void setAllMetadata(int generationId, Bundle metadata, Bitmap artwork) { - System.out.println("New metadata+artwork: id=" + generationId - + " data=" + metadata + " art=" + artwork); + public void onMetadataChanged(MediaMetadata metadata) { + String mmString = metadata == null ? null : "title=" + metadata + .getString(MediaMetadata.METADATA_KEY_TITLE); + System.out.println("onMetadataChanged " + mmString); } void printUsageMessage() { - System.out.println("Monitoring remote control displays... available commands:"); + System.out.println("V2Monitoring session " + mController.getSessionInfo().getId() + + "... available commands:"); System.out.println("(q)uit: finish monitoring"); } void run() throws RemoteException { printUsageMessage(); - - mAudioService.registerRemoteControlDisplay(this, 0, 0); + HandlerThread cbThread = new HandlerThread("MediaCb") { + @Override + protected void onLooperPrepared() { + mController.addCallback(ControllerMonitor.this); + } + }; + cbThread.start(); try { InputStreamReader converter = new InputStreamReader(System.in); @@ -209,17 +235,35 @@ public class Media extends BaseCommand { printUsageMessage(); } } - } catch (IOException e) { e.printStackTrace(); } finally { - mAudioService.unregisterRemoteControlDisplay(this); + cbThread.getLooper().quit(); + try { + mController.removeCallback(this); + } catch (Exception e) { + // ignoring + } } } } - private void runRemoteDisplay() throws Exception { - RemoteDisplayMonitor monitor = new RemoteDisplayMonitor(); - monitor.run(); + private void runListSessions() { + System.out.println("Sessions:"); + try { + List<IBinder> sessions = mSessionService + .getSessions(null, ActivityManager.getCurrentUser()); + for (IBinder session : sessions) { + MediaController controller = MediaController.fromBinder(ISessionController.Stub + .asInterface(session)); + if (controller != null) { + MediaSessionInfo info = controller.getSessionInfo(); + System.out.println(" id=" + info.getId() + ", package=" + + info.getPackageName()); + } + } + } catch (Exception e) { + System.out.println("***Error listing sessions***"); + } } } diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java index 06f5aca1b644..39fcf733ecf5 100644 --- a/core/java/android/animation/AnimatorInflater.java +++ b/core/java/android/animation/AnimatorInflater.java @@ -17,11 +17,13 @@ package android.animation; import android.content.Context; import android.content.res.Resources; +import android.content.res.Resources.NotFoundException; import android.content.res.Resources.Theme; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; -import android.content.res.Resources.NotFoundException; +import android.graphics.Path; import android.util.AttributeSet; +import android.util.PathParser; import android.util.StateSet; import android.util.TypedValue; import android.util.Xml; @@ -158,7 +160,7 @@ public class AnimatorInflater { int stateIndex = 0; for (int i = 0; i < attributeCount; i++) { int attrName = attributeSet.getAttributeNameResource(i); - if (attrName == com.android.internal.R.attr.animation) { + if (attrName == R.attr.animation) { animator = loadAnimator(context, attributeSet.getAttributeResourceValue(i, 0)); } else { @@ -186,36 +188,43 @@ public class AnimatorInflater { } } + /** + * @param anim Null if this is a ValueAnimator, otherwise this is an + * ObjectAnimator + * @param arrayAnimator Incoming typed array for Animator's attributes. + * @param arrayObjectAnimator Incoming typed array for Object Animator's + * attributes. + */ + private static void parseAnimatorFromTypeArray(ValueAnimator anim, + TypedArray arrayAnimator, TypedArray arrayObjectAnimator) { + long duration = arrayAnimator.getInt(R.styleable.Animator_duration, 300); - private static void parseAnimatorFromTypeArray(ValueAnimator anim, TypedArray a) { - long duration = a.getInt(com.android.internal.R.styleable.Animator_duration, 300); - - long startDelay = a.getInt(com.android.internal.R.styleable.Animator_startOffset, 0); + long startDelay = arrayAnimator.getInt(R.styleable.Animator_startOffset, 0); - int valueType = a.getInt(com.android.internal.R.styleable.Animator_valueType, + int valueType = arrayAnimator.getInt(R.styleable.Animator_valueType, VALUE_TYPE_FLOAT); if (anim == null) { anim = new ValueAnimator(); } - TypeEvaluator evaluator = null; - int valueFromIndex = com.android.internal.R.styleable.Animator_valueFrom; - int valueToIndex = com.android.internal.R.styleable.Animator_valueTo; + TypeEvaluator evaluator = null; + int valueFromIndex = R.styleable.Animator_valueFrom; + int valueToIndex = R.styleable.Animator_valueTo; boolean getFloats = (valueType == VALUE_TYPE_FLOAT); - TypedValue tvFrom = a.peekValue(valueFromIndex); + TypedValue tvFrom = arrayAnimator.peekValue(valueFromIndex); boolean hasFrom = (tvFrom != null); int fromType = hasFrom ? tvFrom.type : 0; - TypedValue tvTo = a.peekValue(valueToIndex); + TypedValue tvTo = arrayAnimator.peekValue(valueToIndex); boolean hasTo = (tvTo != null); int toType = hasTo ? tvTo.type : 0; if ((hasFrom && (fromType >= TypedValue.TYPE_FIRST_COLOR_INT) && (fromType <= TypedValue.TYPE_LAST_COLOR_INT)) || - (hasTo && (toType >= TypedValue.TYPE_FIRST_COLOR_INT) && - (toType <= TypedValue.TYPE_LAST_COLOR_INT))) { + (hasTo && (toType >= TypedValue.TYPE_FIRST_COLOR_INT) && + (toType <= TypedValue.TYPE_LAST_COLOR_INT))) { // special case for colors: ignore valueType and get ints getFloats = false; evaluator = ArgbEvaluator.getInstance(); @@ -226,15 +235,15 @@ public class AnimatorInflater { float valueTo; if (hasFrom) { if (fromType == TypedValue.TYPE_DIMENSION) { - valueFrom = a.getDimension(valueFromIndex, 0f); + valueFrom = arrayAnimator.getDimension(valueFromIndex, 0f); } else { - valueFrom = a.getFloat(valueFromIndex, 0f); + valueFrom = arrayAnimator.getFloat(valueFromIndex, 0f); } if (hasTo) { if (toType == TypedValue.TYPE_DIMENSION) { - valueTo = a.getDimension(valueToIndex, 0f); + valueTo = arrayAnimator.getDimension(valueToIndex, 0f); } else { - valueTo = a.getFloat(valueToIndex, 0f); + valueTo = arrayAnimator.getFloat(valueToIndex, 0f); } anim.setFloatValues(valueFrom, valueTo); } else { @@ -242,9 +251,9 @@ public class AnimatorInflater { } } else { if (toType == TypedValue.TYPE_DIMENSION) { - valueTo = a.getDimension(valueToIndex, 0f); + valueTo = arrayAnimator.getDimension(valueToIndex, 0f); } else { - valueTo = a.getFloat(valueToIndex, 0f); + valueTo = arrayAnimator.getFloat(valueToIndex, 0f); } anim.setFloatValues(valueTo); } @@ -253,21 +262,21 @@ public class AnimatorInflater { int valueTo; if (hasFrom) { if (fromType == TypedValue.TYPE_DIMENSION) { - valueFrom = (int) a.getDimension(valueFromIndex, 0f); + valueFrom = (int) arrayAnimator.getDimension(valueFromIndex, 0f); } else if ((fromType >= TypedValue.TYPE_FIRST_COLOR_INT) && (fromType <= TypedValue.TYPE_LAST_COLOR_INT)) { - valueFrom = a.getColor(valueFromIndex, 0); + valueFrom = arrayAnimator.getColor(valueFromIndex, 0); } else { - valueFrom = a.getInt(valueFromIndex, 0); + valueFrom = arrayAnimator.getInt(valueFromIndex, 0); } if (hasTo) { if (toType == TypedValue.TYPE_DIMENSION) { - valueTo = (int) a.getDimension(valueToIndex, 0f); + valueTo = (int) arrayAnimator.getDimension(valueToIndex, 0f); } else if ((toType >= TypedValue.TYPE_FIRST_COLOR_INT) && (toType <= TypedValue.TYPE_LAST_COLOR_INT)) { - valueTo = a.getColor(valueToIndex, 0); + valueTo = arrayAnimator.getColor(valueToIndex, 0); } else { - valueTo = a.getInt(valueToIndex, 0); + valueTo = arrayAnimator.getInt(valueToIndex, 0); } anim.setIntValues(valueFrom, valueTo); } else { @@ -276,12 +285,12 @@ public class AnimatorInflater { } else { if (hasTo) { if (toType == TypedValue.TYPE_DIMENSION) { - valueTo = (int) a.getDimension(valueToIndex, 0f); + valueTo = (int) arrayAnimator.getDimension(valueToIndex, 0f); } else if ((toType >= TypedValue.TYPE_FIRST_COLOR_INT) && - (toType <= TypedValue.TYPE_LAST_COLOR_INT)) { - valueTo = a.getColor(valueToIndex, 0); + (toType <= TypedValue.TYPE_LAST_COLOR_INT)) { + valueTo = arrayAnimator.getColor(valueToIndex, 0); } else { - valueTo = a.getInt(valueToIndex, 0); + valueTo = arrayAnimator.getInt(valueToIndex, 0); } anim.setIntValues(valueTo); } @@ -291,18 +300,59 @@ public class AnimatorInflater { anim.setDuration(duration); anim.setStartDelay(startDelay); - if (a.hasValue(com.android.internal.R.styleable.Animator_repeatCount)) { + if (arrayAnimator.hasValue(R.styleable.Animator_repeatCount)) { anim.setRepeatCount( - a.getInt(com.android.internal.R.styleable.Animator_repeatCount, 0)); + arrayAnimator.getInt(R.styleable.Animator_repeatCount, 0)); } - if (a.hasValue(com.android.internal.R.styleable.Animator_repeatMode)) { + if (arrayAnimator.hasValue(R.styleable.Animator_repeatMode)) { anim.setRepeatMode( - a.getInt(com.android.internal.R.styleable.Animator_repeatMode, + arrayAnimator.getInt(R.styleable.Animator_repeatMode, ValueAnimator.RESTART)); } if (evaluator != null) { anim.setEvaluator(evaluator); } + + if (arrayObjectAnimator != null) { + ObjectAnimator oa = (ObjectAnimator) anim; + String pathData = arrayObjectAnimator.getString(R.styleable.PropertyAnimator_pathData); + + // Note that if there is a pathData defined in the Object Animator, + // valueFrom / valueTo will be overwritten by the pathData. + if (pathData != null) { + String propertyXName = + arrayObjectAnimator.getString(R.styleable.PropertyAnimator_propertyXName); + String propertyYName = + arrayObjectAnimator.getString(R.styleable.PropertyAnimator_propertyYName); + + if (propertyXName == null && propertyYName == null) { + throw new IllegalArgumentException("propertyXName or propertyYName" + + " is needed for PathData in Object Animator"); + } else { + Path path = PathParser.createPathFromPathData(pathData); + Keyframe[][] keyframes = PropertyValuesHolder.createKeyframes(path, !getFloats); + PropertyValuesHolder x = null; + PropertyValuesHolder y = null; + if (propertyXName != null) { + x = PropertyValuesHolder.ofKeyframe(propertyXName, keyframes[0]); + } + if (propertyYName != null) { + y = PropertyValuesHolder.ofKeyframe(propertyYName, keyframes[1]); + } + if (x == null) { + oa.setValues(y); + } else if (y == null) { + oa.setValues(x); + } else { + oa.setValues(x, y); + } + } + } else { + String propertyName = + arrayObjectAnimator.getString(R.styleable.PropertyAnimator_propertyName); + oa.setPropertyName(propertyName); + } + } } private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser) @@ -338,11 +388,11 @@ public class AnimatorInflater { anim = new AnimatorSet(); TypedArray a; if (theme != null) { - a = theme.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AnimatorSet, 0, 0); + a = theme.obtainStyledAttributes(attrs, R.styleable.AnimatorSet, 0, 0); } else { - a = res.obtainAttributes(attrs, com.android.internal.R.styleable.AnimatorSet); + a = res.obtainAttributes(attrs, R.styleable.AnimatorSet); } - int ordering = a.getInt(com.android.internal.R.styleable.AnimatorSet_ordering, + int ordering = a.getInt(R.styleable.AnimatorSet_ordering, TOGETHER); createAnimatorFromXml(res, theme, parser, attrs, (AnimatorSet) anim, ordering); a.recycle(); @@ -380,19 +430,6 @@ public class AnimatorInflater { loadAnimator(res, theme, attrs, anim); - TypedArray a; - if (theme != null) { - a = theme.obtainStyledAttributes(attrs, R.styleable.PropertyAnimator, 0, 0); - } else { - a = res.obtainAttributes(attrs, R.styleable.PropertyAnimator); - } - - String propertyName = a.getString(R.styleable.PropertyAnimator_propertyName); - - anim.setPropertyName(propertyName); - - a.recycle(); - return anim; } @@ -402,26 +439,41 @@ public class AnimatorInflater { * * @param res The resources * @param attrs The set of attributes holding the animation parameters + * @param anim Null if this is a ValueAnimator, otherwise this is an + * ObjectAnimator */ private static ValueAnimator loadAnimator(Resources res, Theme theme, AttributeSet attrs, ValueAnimator anim) throws NotFoundException { - TypedArray a; + TypedArray arrayAnimator = null; + TypedArray arrayObjectAnimator = null; + if (theme != null) { - a = theme.obtainStyledAttributes(attrs, R.styleable.Animator, 0, 0); + arrayAnimator = theme.obtainStyledAttributes(attrs, R.styleable.Animator, 0, 0); } else { - a = res.obtainAttributes(attrs, R.styleable.Animator); + arrayAnimator = res.obtainAttributes(attrs, R.styleable.Animator); } - parseAnimatorFromTypeArray(anim, a); + // If anim is not null, then it is an object animator. + if (anim != null) { + if (theme != null) { + arrayObjectAnimator = theme.obtainStyledAttributes(attrs, + R.styleable.PropertyAnimator, 0, 0); + } else { + arrayObjectAnimator = res.obtainAttributes(attrs, R.styleable.PropertyAnimator); + } + } + parseAnimatorFromTypeArray(anim, arrayAnimator, arrayObjectAnimator); final int resID = - a.getResourceId(com.android.internal.R.styleable.Animator_interpolator, 0); + arrayAnimator.getResourceId(R.styleable.Animator_interpolator, 0); if (resID > 0) { anim.setInterpolator(AnimationUtils.loadInterpolator(res, theme, resID)); } - a.recycle(); + + arrayAnimator.recycle(); + arrayObjectAnimator.recycle(); return anim; } diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java index c7030b0a4b0a..fa9b1e3f9230 100644 --- a/core/java/android/app/ActivityTransitionCoordinator.java +++ b/core/java/android/app/ActivityTransitionCoordinator.java @@ -233,6 +233,13 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { if (getViewsTransition() != null) { getDecor().captureTransitioningViews(mTransitioningViews); mTransitioningViews.removeAll(mSharedElements); + Rect r = new Rect(); + for (int i = mTransitioningViews.size() - 1; i >= 0; i--) { + View view = mTransitioningViews.get(i); + if (!view.getGlobalVisibleRect(r)) { + mTransitioningViews.remove(i); + } + } } setEpicenter(); } diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index ef4099ff8944..5998d7a0d16c 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -1184,6 +1184,7 @@ class ApplicationThreadProxy implements IApplicationThread { data.writeInt(level); mRemote.transact(SCHEDULE_TRIM_MEMORY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); + data.recycle(); } public void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin, diff --git a/core/java/android/app/backup/BackupTransport.java b/core/java/android/app/backup/BackupTransport.java index 706ef043dccb..4631323558db 100644 --- a/core/java/android/app/backup/BackupTransport.java +++ b/core/java/android/app/backup/BackupTransport.java @@ -31,12 +31,22 @@ import com.android.internal.backup.IBackupTransport; * @hide */ public class BackupTransport { + // Zero return always means things are okay. If returned from + // getNextFullRestoreDataChunk(), it means that no data could be delivered at + // this time, but the restore is still running and the caller should simply + // retry. public static final int TRANSPORT_OK = 0; - public static final int TRANSPORT_ERROR = 1; - public static final int TRANSPORT_NOT_INITIALIZED = 2; - public static final int TRANSPORT_PACKAGE_REJECTED = 3; - public static final int AGENT_ERROR = 4; - public static final int AGENT_UNKNOWN = 5; + + // -1 is special; it is used in getNextFullRestoreDataChunk() to indicate that + // we've delivered the entire data stream for the current restore target. + public static final int NO_MORE_DATA = -1; + + // Result codes that indicate real errors are negative and not -1 + public static final int TRANSPORT_ERROR = -1000; + public static final int TRANSPORT_NOT_INITIALIZED = -1001; + public static final int TRANSPORT_PACKAGE_REJECTED = -1002; + public static final int AGENT_ERROR = -1003; + public static final int AGENT_UNKNOWN = -1004; IBackupTransport mBinderImpl = new TransportImpl(); /** @hide */ @@ -370,11 +380,14 @@ public class BackupTransport { * @param socket The file descriptor that the transport will use for delivering the * streamed archive. The transport must close this socket in all cases when returning * from this method. - * @return 0 when no more data for the current package is available. A positive value - * indicates the presence of that many bytes to be delivered to the app. Any negative - * return value is treated as equivalent to {@link BackupTransport#TRANSPORT_ERROR}, - * indicating a fatal error condition that precludes further restore operations - * on the current dataset. + * @return {@link #NO_MORE_DATA} when no more data for the current package is available. + * A positive value indicates the presence of that many bytes to be delivered to the app. + * A value of zero indicates that no data was deliverable at this time, but the restore + * is still running and the caller should retry. {@link #TRANSPORT_PACKAGE_REJECTED} + * means that the current package's restore operation should be aborted, but that + * the transport itself is still in a good state and so a multiple-package restore + * sequence can still be continued. Any other negative return value is treated as a + * fatal error condition that aborts all further restore operations on the current dataset. */ public int getNextFullRestoreDataChunk(ParcelFileDescriptor socket) { return 0; diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index abc8cde2c9eb..bcf1e8760e75 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -252,6 +252,13 @@ public class ActivityInfo extends ComponentInfo */ public static final int FLAG_IMMERSIVE = 0x0800; /** + * Bit in {@link #flags}: If set, a task rooted at this activity will have its + * baseIntent replaced by the activity immediately above this. Each activity may further + * relinquish its identity to the activity above it using this flag. Set from the + * android.R.attr#relinquishTaskIdentity attribute. + */ + public static final int FLAG_RELINQUISH_TASK_IDENTITY = 0x1000; + /** * Bit in {@link #flags} indicating that tasks started with this activity are to be * removed from the recent list of tasks when the last activity in the task is finished. * {@link android.R.attr#autoRemoveFromRecents} diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index b5ceebe5afb5..9d871c544a0f 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -2892,6 +2892,7 @@ public abstract class PackageManager { PackageParser.Package pkg = parser.parseMonolithicPackage(apkFile, 0); if ((flags & GET_SIGNATURES) != 0) { parser.collectCertificates(pkg, 0); + parser.collectManifestDigest(pkg); } PackageUserState state = new PackageUserState(); return PackageParser.generatePackageInfo(pkg, null, flags, 0, 0, null, state); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 546f3a52c366..b40a441a88d6 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -744,6 +744,8 @@ public class PackageParser { * {@code AndroidManifest.xml}, {@code true} is returned. */ public void collectManifestDigest(Package pkg) throws PackageParserException { + pkg.manifestDigest = null; + // TODO: extend to gather digest for split APKs try { final StrictJarFile jarFile = new StrictJarFile(pkg.codePath); @@ -2627,6 +2629,12 @@ public class PackageParser { false)) { a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS; } + + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestActivity_relinquishTaskIdentity, + false)) { + a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY; + } } else { a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE; a.info.configChanges = 0; diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 0705e0ce8e1b..44fc3b6a8423 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -172,6 +172,11 @@ public class Camera { private static final int NO_ERROR = 0; private static final int EACCESS = -13; private static final int ENODEV = -19; + private static final int EBUSY = -16; + private static final int EINVAL = -22; + private static final int ENOSYS = -38; + private static final int EUSERS = -87; + private static final int EOPNOTSUPP = -95; /** * Broadcast Action: A new picture is taken by the camera, and the entry of @@ -190,6 +195,22 @@ public class Camera { public static final String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO"; /** + * Camera HAL device API version 1.0 + * @hide + */ + public static final int CAMERA_HAL_API_VERSION_1_0 = 0x100; + + /** + * A constant meaning the normal camera connect/open will be used. + * @hide + */ + public static final int CAMERA_HAL_API_VERSION_NORMAL_OPEN = -2; + + /** + * Used to indicate HAL version un-specified. + */ + private static final int CAMERA_HAL_API_VERSION_UNSPECIFIED = -1; + /** * Hardware face detection. It does not use much CPU. */ private static final int CAMERA_FACE_DETECTION_HW = 0; @@ -331,6 +352,111 @@ public class Camera { return null; } + /** + * Creates a new Camera object to access a particular hardware camera with + * given hal API version. If the same camera is opened by other applications + * or the hal API version is not supported by this device, this will throw a + * RuntimeException. + * <p> + * You must call {@link #release()} when you are done using the camera, + * otherwise it will remain locked and be unavailable to other applications. + * <p> + * Your application should only have one Camera object active at a time for + * a particular hardware camera. + * <p> + * Callbacks from other methods are delivered to the event loop of the + * thread which called open(). If this thread has no event loop, then + * callbacks are delivered to the main application event loop. If there is + * no main application event loop, callbacks are not delivered. + * <p class="caution"> + * <b>Caution:</b> On some devices, this method may take a long time to + * complete. It is best to call this method from a worker thread (possibly + * using {@link android.os.AsyncTask}) to avoid blocking the main + * application UI thread. + * + * @param cameraId The hardware camera to access, between 0 and + * {@link #getNumberOfCameras()}-1. + * @param halVersion The HAL API version this camera device to be opened as. When + * it is {@value #CAMERA_HAL_API_VERSION_NORMAL_OPEN}, the methods will be equivalent + * to {@link #open}, but more detailed error information will be returned to managed code. + * @return a new Camera object, connected, locked and ready for use. + * @throws RuntimeException if opening the camera fails (for example, if the + * camera is in use by another process or device policy manager has disabled + * the camera). + * @see android.app.admin.DevicePolicyManager#getCameraDisabled(android.content.ComponentName) + * + * @hide + */ + public static Camera openLegacy(int cameraId, int halVersion) { + return new Camera(cameraId, halVersion); + } + + /** + * Create a legacy camera object. + * + * @param cameraId The hardware camera to access, between 0 and + * {@link #getNumberOfCameras()}-1. + * @param halVersion The HAL API version this camera device to be opened as. + */ + private Camera(int cameraId, int halVersion) { + int err = cameraInit(cameraId, halVersion); + if (checkInitErrors(err)) { + switch(err) { + case EACCESS: + throw new RuntimeException("Fail to connect to camera service"); + case ENODEV: + throw new RuntimeException("Camera initialization failed"); + case ENOSYS: + throw new RuntimeException("Camera initialization failed because some methods" + + " are not implemented"); + case EOPNOTSUPP: + throw new RuntimeException("Camera initialization failed because the hal" + + " version is not supported by this device"); + case EINVAL: + throw new RuntimeException("Camera initialization failed because the input" + + " arugments are invalid"); + case EBUSY: + throw new RuntimeException("Camera initialization failed because the camera" + + " device was already opened"); + case EUSERS: + throw new RuntimeException("Camera initialization failed because the max" + + " number of camera devices were already opened"); + default: + // Should never hit this. + throw new RuntimeException("Unknown camera error"); + } + } + } + + private int cameraInit(int cameraId, int halVersion) { + // This function should be only called by Camera(int cameraId, int halVersion). + if (halVersion < CAMERA_HAL_API_VERSION_1_0 && + halVersion != CAMERA_HAL_API_VERSION_NORMAL_OPEN) { + throw new IllegalArgumentException("Invalid HAL version " + halVersion); + } + + mShutterCallback = null; + mRawImageCallback = null; + mJpegCallback = null; + mPreviewCallback = null; + mPostviewCallback = null; + mUsingPreviewAllocation = false; + mZoomListener = null; + + Looper looper; + if ((looper = Looper.myLooper()) != null) { + mEventHandler = new EventHandler(this, looper); + } else if ((looper = Looper.getMainLooper()) != null) { + mEventHandler = new EventHandler(this, looper); + } else { + mEventHandler = null; + } + + String packageName = ActivityThread.currentPackageName(); + + return native_setup(new WeakReference<Camera>(this), cameraId, halVersion, packageName); + } + Camera(int cameraId) { int err = cameraInit(cameraId); if (checkInitErrors(err)) { @@ -369,7 +495,8 @@ public class Camera { String packageName = ActivityThread.currentPackageName(); - return native_setup(new WeakReference<Camera>(this), cameraId, packageName); + return native_setup(new WeakReference<Camera>(this), cameraId, + CAMERA_HAL_API_VERSION_UNSPECIFIED, packageName); } /** @@ -396,7 +523,7 @@ public class Camera { release(); } - private native final int native_setup(Object camera_this, int cameraId, + private native final int native_setup(Object camera_this, int cameraId, int halVersion, String packageName); private native final void native_release(); diff --git a/core/java/android/hardware/ICameraService.aidl b/core/java/android/hardware/ICameraService.aidl index 31896f55b09f..2bc3dd40a980 100644 --- a/core/java/android/hardware/ICameraService.aidl +++ b/core/java/android/hardware/ICameraService.aidl @@ -74,4 +74,11 @@ interface ICameraService int getLegacyParameters(int cameraId, out String[] parameters); // Determines if a particular API version is supported; see ICameraService.h for version defines int supportsCameraApi(int cameraId, int apiVersion); + + int connectLegacy(ICameraClient client, int cameraId, + int halVersion, + String clientPackageName, + int clientUid, + // Container for an ICamera object + out BinderHolder device); } diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index 5a02435d3a29..dad1854b03cb 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -248,7 +248,6 @@ public abstract class CameraMetadata<TKey> { * <li>Manual frame duration control<ul> * <li>{@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration}</li> * <li>{@link CameraCharacteristics#SENSOR_INFO_MAX_FRAME_DURATION android.sensor.info.maxFrameDuration}</li> - * <li>{@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap}</li> * </ul> * </li> * <li>Manual exposure control<ul> @@ -279,6 +278,9 @@ public abstract class CameraMetadata<TKey> { * result.</p> * <p>A given camera device may also support additional manual sensor controls, * but this capability only covers the above list of controls.</p> + * <p>If this is supported, {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} will + * additionally return a min frame duration that is greater than + * zero for each supported size-format combination.</p> * * @see CaptureRequest#BLACK_LEVEL_LOCK * @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index 2cfb611acdd0..5bc59dca6705 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -18,6 +18,7 @@ package android.hardware.camera2; import android.hardware.camera2.CameraCharacteristics.Key; import android.hardware.camera2.impl.CameraMetadataNative; +import android.hardware.camera2.utils.HashCodeHelpers; import android.hardware.camera2.utils.TypeReference; import android.os.Parcel; import android.os.Parcelable; @@ -280,7 +281,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> @Override public int hashCode() { - return mSettings.hashCode(); + return HashCodeHelpers.hashCode(mSettings, mSurfaceSet, mUserTag); } public static final Parcelable.Creator<CaptureRequest> CREATOR = diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index d9f3af4f0151..de1d9a39114d 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -28,6 +28,8 @@ import android.hardware.camera2.ICameraDeviceUser; import android.hardware.camera2.TotalCaptureResult; import android.hardware.camera2.utils.CameraBinderDecorator; import android.hardware.camera2.utils.CameraRuntimeException; +import android.hardware.camera2.utils.CloseableLock; +import android.hardware.camera2.utils.CloseableLock.ScopedLock; import android.hardware.camera2.utils.LongParcelable; import android.os.Handler; import android.os.IBinder; @@ -57,13 +59,14 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { // TODO: guard every function with if (!mRemoteDevice) check (if it was closed) private ICameraDeviceUser mRemoteDevice; - private final Object mLock = new Object(); + private final CloseableLock mCloseLock; private final CameraDeviceCallbacks mCallbacks = new CameraDeviceCallbacks(); private final StateListener mDeviceListener; private volatile StateListener mSessionStateListener; private final Handler mDeviceHandler; + private volatile boolean mClosing = false; private boolean mInError = false; private boolean mIdle = true; @@ -100,7 +103,9 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { private final Runnable mCallOnOpened = new Runnable() { @Override public void run() { - if (!CameraDeviceImpl.this.isClosed()) { + try (ScopedLock scopedLock = mCloseLock.acquireLock()) { + if (scopedLock == null) return; // Camera already closed + StateListener sessionListener = mSessionStateListener; if (sessionListener != null) { sessionListener.onOpened(CameraDeviceImpl.this); @@ -113,7 +118,9 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { private final Runnable mCallOnUnconfigured = new Runnable() { @Override public void run() { - if (!CameraDeviceImpl.this.isClosed()) { + try (ScopedLock scopedLock = mCloseLock.acquireLock()) { + if (scopedLock == null) return; // Camera already closed + StateListener sessionListener = mSessionStateListener; if (sessionListener != null) { sessionListener.onUnconfigured(CameraDeviceImpl.this); @@ -126,7 +133,9 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { private final Runnable mCallOnActive = new Runnable() { @Override public void run() { - if (!CameraDeviceImpl.this.isClosed()) { + try (ScopedLock scopedLock = mCloseLock.acquireLock()) { + if (scopedLock == null) return; // Camera already closed + StateListener sessionListener = mSessionStateListener; if (sessionListener != null) { sessionListener.onActive(CameraDeviceImpl.this); @@ -139,7 +148,9 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { private final Runnable mCallOnBusy = new Runnable() { @Override public void run() { - if (!CameraDeviceImpl.this.isClosed()) { + try (ScopedLock scopedLock = mCloseLock.acquireLock()) { + if (scopedLock == null) return; // Camera already closed + StateListener sessionListener = mSessionStateListener; if (sessionListener != null) { sessionListener.onBusy(CameraDeviceImpl.this); @@ -150,20 +161,29 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { }; private final Runnable mCallOnClosed = new Runnable() { + private boolean mClosedOnce = false; + @Override public void run() { + if (mClosedOnce) { + throw new AssertionError("Don't post #onClosed more than once"); + } + StateListener sessionListener = mSessionStateListener; if (sessionListener != null) { sessionListener.onClosed(CameraDeviceImpl.this); } mDeviceListener.onClosed(CameraDeviceImpl.this); + mClosedOnce = true; } }; private final Runnable mCallOnIdle = new Runnable() { @Override public void run() { - if (!CameraDeviceImpl.this.isClosed()) { + try (ScopedLock scopedLock = mCloseLock.acquireLock()) { + if (scopedLock == null) return; // Camera already closed + StateListener sessionListener = mSessionStateListener; if (sessionListener != null) { sessionListener.onIdle(CameraDeviceImpl.this); @@ -176,7 +196,9 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { private final Runnable mCallOnDisconnected = new Runnable() { @Override public void run() { - if (!CameraDeviceImpl.this.isClosed()) { + try (ScopedLock scopedLock = mCloseLock.acquireLock()) { + if (scopedLock == null) return; // Camera already closed + StateListener sessionListener = mSessionStateListener; if (sessionListener != null) { sessionListener.onDisconnected(CameraDeviceImpl.this); @@ -195,6 +217,7 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { mDeviceListener = listener; mDeviceHandler = handler; mCharacteristics = characteristics; + mCloseLock = new CloseableLock(/*name*/"CD-" + mCameraId); final int MAX_TAG_LEN = 23; String tag = String.format("CameraDevice-JV-%s", mCameraId); @@ -210,8 +233,8 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { } public void setRemoteDevice(ICameraDeviceUser remoteDevice) { + try (ScopedLock scopedLock = mCloseLock.acquireLock()) { // TODO: Move from decorator to direct binder-mediated exceptions - synchronized(mLock) { // If setRemoteFailure already called, do nothing if (mInError) return; @@ -254,7 +277,9 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { } final int code = failureCode; final boolean isError = failureIsError; - synchronized (mLock) { + try (ScopedLock scopedLock = mCloseLock.acquireLock()) { + if (scopedLock == null) return; // Camera already closed, can't go to error state + mInError = true; mDeviceHandler.post(new Runnable() { @Override @@ -280,7 +305,7 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { if (outputs == null) { outputs = new ArrayList<Surface>(); } - synchronized (mLock) { + try (ScopedLock scopedLock = mCloseLock.acquireExclusiveLock()) { checkIfCameraClosedOrInError(); HashSet<Surface> addSet = new HashSet<Surface>(outputs); // Streams to create @@ -344,7 +369,7 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { public void createCaptureSession(List<Surface> outputs, CameraCaptureSession.StateListener listener, Handler handler) throws CameraAccessException { - synchronized (mLock) { + try (ScopedLock scopedLock = mCloseLock.acquireExclusiveLock()) { if (DEBUG) { Log.d(TAG, "createCaptureSession"); } @@ -389,7 +414,7 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { @Override public CaptureRequest.Builder createCaptureRequest(int templateType) throws CameraAccessException { - synchronized (mLock) { + try (ScopedLock scopedLock = mCloseLock.acquireExclusiveLock()) { checkIfCameraClosedOrInError(); CameraMetadataNative templatedRequest = new CameraMetadataNative(); @@ -509,7 +534,7 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { handler = checkHandler(handler); } - synchronized (mLock) { + try (ScopedLock scopedLock = mCloseLock.acquireExclusiveLock()) { checkIfCameraClosedOrInError(); int requestId; @@ -581,7 +606,7 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { @Override public void stopRepeating() throws CameraAccessException { - synchronized (mLock) { + try (ScopedLock scopedLock = mCloseLock.acquireExclusiveLock()) { checkIfCameraClosedOrInError(); if (mRepeatingRequestId != REQUEST_ID_NONE) { @@ -612,7 +637,7 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { private void waitUntilIdle() throws CameraAccessException { - synchronized (mLock) { + try (ScopedLock scopedLock = mCloseLock.acquireExclusiveLock()) { checkIfCameraClosedOrInError(); if (mRepeatingRequestId != REQUEST_ID_NONE) { throw new IllegalStateException("Active repeating request ongoing"); @@ -633,7 +658,7 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { @Override public void flush() throws CameraAccessException { - synchronized (mLock) { + try (ScopedLock scopedLock = mCloseLock.acquireExclusiveLock()) { checkIfCameraClosedOrInError(); mDeviceHandler.post(mCallOnBusy); @@ -656,8 +681,15 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { @Override public void close() { - synchronized (mLock) { + mClosing = true; + // Acquire exclusive lock, close, release (idempotent) + mCloseLock.close(); + /* + * The rest of this is safe, since no other methods will be able to execute + * (they will throw ISE instead; the callbacks will get dropped) + */ + { try { if (mRemoteDevice != null) { mRemoteDevice.disconnect(); @@ -805,7 +837,12 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { // remove request from mCaptureListenerMap final int requestId = frameNumberRequestPair.getValue(); final CaptureListenerHolder holder; - synchronized (mLock) { + try (ScopedLock scopedLock = mCloseLock.acquireLock()) { + if (scopedLock == null) { + Log.w(TAG, "Camera closed while checking sequences"); + return; + } + int index = mCaptureListenerMap.indexOfKey(requestId); holder = (index >= 0) ? mCaptureListenerMap.valueAt(index) : null; @@ -890,9 +927,12 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { @Override public void onCameraError(final int errorCode, CaptureResultExtras resultExtras) { Runnable r = null; - if (isClosed()) return; - synchronized(mLock) { + try (ScopedLock scopedLock = mCloseLock.acquireLock()) { + if (scopedLock == null) { + return; // Camera already closed + } + mInError = true; switch (errorCode) { case ERROR_CAMERA_DISCONNECTED: @@ -914,25 +954,24 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { break; } CameraDeviceImpl.this.mDeviceHandler.post(r); - } - // Fire onCaptureSequenceCompleted - if (DEBUG) { - Log.v(TAG, String.format("got error frame %d", resultExtras.getFrameNumber())); + // Fire onCaptureSequenceCompleted + if (DEBUG) { + Log.v(TAG, String.format("got error frame %d", resultExtras.getFrameNumber())); + } + mFrameNumberTracker.updateTracker(resultExtras.getFrameNumber(), /*error*/true); + checkAndFireSequenceComplete(); } - mFrameNumberTracker.updateTracker(resultExtras.getFrameNumber(), /*error*/true); - checkAndFireSequenceComplete(); - } @Override public void onCameraIdle() { - if (isClosed()) return; - if (DEBUG) { Log.d(TAG, "Camera now idle"); } - synchronized (mLock) { + try (ScopedLock scopedLock = mCloseLock.acquireLock()) { + if (scopedLock == null) return; // Camera already closed + if (!CameraDeviceImpl.this.mIdle) { CameraDeviceImpl.this.mDeviceHandler.post(mCallOnIdle); } @@ -948,30 +987,33 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { } final CaptureListenerHolder holder; - // Get the listener for this frame ID, if there is one - synchronized (mLock) { + try (ScopedLock scopedLock = mCloseLock.acquireLock()) { + if (scopedLock == null) return; // Camera already closed + + // Get the listener for this frame ID, if there is one holder = CameraDeviceImpl.this.mCaptureListenerMap.get(requestId); - } - if (holder == null) { - return; - } + if (holder == null) { + return; + } - if (isClosed()) return; + if (isClosed()) return; - // Dispatch capture start notice - holder.getHandler().post( - new Runnable() { - @Override - public void run() { - if (!CameraDeviceImpl.this.isClosed()) { - holder.getListener().onCaptureStarted( - CameraDeviceImpl.this, - holder.getRequest(resultExtras.getSubsequenceId()), - timestamp); + // Dispatch capture start notice + holder.getHandler().post( + new Runnable() { + @Override + public void run() { + if (!CameraDeviceImpl.this.isClosed()) { + holder.getListener().onCaptureStarted( + CameraDeviceImpl.this, + holder.getRequest(resultExtras.getSubsequenceId()), + timestamp); + } } - } - }); + }); + + } } @Override @@ -984,88 +1026,91 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { + requestId); } + try (ScopedLock scopedLock = mCloseLock.acquireLock()) { + if (scopedLock == null) return; // Camera already closed - // TODO: Handle CameraCharacteristics access from CaptureResult correctly. - result.set(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE, - getCharacteristics().get(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE)); + // TODO: Handle CameraCharacteristics access from CaptureResult correctly. + result.set(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE, + getCharacteristics().get(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE)); - final CaptureListenerHolder holder; - synchronized (mLock) { - holder = CameraDeviceImpl.this.mCaptureListenerMap.get(requestId); - } + final CaptureListenerHolder holder = + CameraDeviceImpl.this.mCaptureListenerMap.get(requestId); - Boolean quirkPartial = result.get(CaptureResult.QUIRKS_PARTIAL_RESULT); - boolean quirkIsPartialResult = (quirkPartial != null && quirkPartial); + Boolean quirkPartial = result.get(CaptureResult.QUIRKS_PARTIAL_RESULT); + boolean quirkIsPartialResult = (quirkPartial != null && quirkPartial); - // Update tracker (increment counter) when it's not a partial result. - if (!quirkIsPartialResult) { - mFrameNumberTracker.updateTracker(resultExtras.getFrameNumber(), /*error*/false); - } + // Update tracker (increment counter) when it's not a partial result. + if (!quirkIsPartialResult) { + mFrameNumberTracker.updateTracker(resultExtras.getFrameNumber(), + /*error*/false); + } - // Check if we have a listener for this - if (holder == null) { - if (DEBUG) { - Log.d(TAG, - "holder is null, early return at frame " - + resultExtras.getFrameNumber()); + // Check if we have a listener for this + if (holder == null) { + if (DEBUG) { + Log.d(TAG, + "holder is null, early return at frame " + + resultExtras.getFrameNumber()); + } + return; } - return; - } - if (isClosed()) { - if (DEBUG) { - Log.d(TAG, - "camera is closed, early return at frame " - + resultExtras.getFrameNumber()); + if (isClosed()) { + if (DEBUG) { + Log.d(TAG, + "camera is closed, early return at frame " + + resultExtras.getFrameNumber()); + } + return; } - return; - } - final CaptureRequest request = holder.getRequest(resultExtras.getSubsequenceId()); + final CaptureRequest request = holder.getRequest(resultExtras.getSubsequenceId()); - Runnable resultDispatch = null; + Runnable resultDispatch = null; - // Either send a partial result or the final capture completed result - if (quirkIsPartialResult) { - final CaptureResult resultAsCapture = - new CaptureResult(result, request, requestId); + // Either send a partial result or the final capture completed result + if (quirkIsPartialResult) { + final CaptureResult resultAsCapture = + new CaptureResult(result, request, requestId); - // Partial result - resultDispatch = new Runnable() { - @Override - public void run() { - if (!CameraDeviceImpl.this.isClosed()){ - holder.getListener().onCapturePartial( - CameraDeviceImpl.this, - request, - resultAsCapture); + // Partial result + resultDispatch = new Runnable() { + @Override + public void run() { + if (!CameraDeviceImpl.this.isClosed()){ + holder.getListener().onCapturePartial( + CameraDeviceImpl.this, + request, + resultAsCapture); + } } - } - }; - } else { - final TotalCaptureResult resultAsCapture = - new TotalCaptureResult(result, request, requestId); + }; + } else { + final TotalCaptureResult resultAsCapture = + new TotalCaptureResult(result, request, requestId); - // Final capture result - resultDispatch = new Runnable() { - @Override - public void run() { - if (!CameraDeviceImpl.this.isClosed()){ - holder.getListener().onCaptureCompleted( - CameraDeviceImpl.this, - request, - resultAsCapture); + // Final capture result + resultDispatch = new Runnable() { + @Override + public void run() { + if (!CameraDeviceImpl.this.isClosed()){ + holder.getListener().onCaptureCompleted( + CameraDeviceImpl.this, + request, + resultAsCapture); + } } - } - }; - } + }; + } - holder.getHandler().post(resultDispatch); + holder.getHandler().post(resultDispatch); + + // Fire onCaptureSequenceCompleted + if (!quirkIsPartialResult) { + checkAndFireSequenceComplete(); + } - // Fire onCaptureSequenceCompleted - if (!quirkIsPartialResult) { - checkAndFireSequenceComplete(); } } @@ -1101,10 +1146,9 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { } } + /** Whether the camera device has started to close (may not yet have finished) */ private boolean isClosed() { - synchronized(mLock) { - return (mRemoteDevice == null); - } + return mClosing; } private CameraCharacteristics getCharacteristics() { diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java index 54d9c3c32e7d..e4412ce666c4 100644 --- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java +++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java @@ -169,7 +169,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { } int numSurfaces = mSurfaces.size(); if (numSurfaces > 0) { - surfaces = new ArrayList<Surface>(); + surfaces = new ArrayList<>(); for (int i = 0; i < numSurfaces; ++i) { surfaces.add(mSurfaces.valueAt(i)); } diff --git a/core/java/android/hardware/camera2/legacy/GLThreadManager.java b/core/java/android/hardware/camera2/legacy/GLThreadManager.java index 038255762040..5d44fd28609d 100644 --- a/core/java/android/hardware/camera2/legacy/GLThreadManager.java +++ b/core/java/android/hardware/camera2/legacy/GLThreadManager.java @@ -100,6 +100,7 @@ public class GLThreadManager { break; case MSG_ALLOW_FRAMES: mDroppingFrames = false; + break; default: Log.e(TAG, "Unhandled message " + msg.what + " on GLThread."); break; diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java index c34a34de021e..50515a2927a6 100644 --- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java +++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java @@ -23,7 +23,6 @@ import android.hardware.camera2.impl.CaptureResultExtras; import android.hardware.camera2.ICameraDeviceCallbacks; import android.hardware.camera2.utils.LongParcelable; import android.hardware.camera2.impl.CameraMetadataNative; -import android.hardware.camera2.utils.CameraBinderDecorator; import android.hardware.camera2.utils.CameraRuntimeException; import android.os.ConditionVariable; import android.os.Handler; @@ -34,7 +33,8 @@ import android.view.Surface; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; + +import static android.hardware.camera2.utils.CameraBinderDecorator.*; /** * This class emulates the functionality of a Camera2 device using a the old Camera class. @@ -50,9 +50,11 @@ public class LegacyCameraDevice implements AutoCloseable { public static final String DEBUG_PROP = "HAL1ShimLogging"; private final String TAG; + private static final boolean DEBUG = false; private final int mCameraId; private final ICameraDeviceCallbacks mDeviceCallbacks; private final CameraDeviceState mDeviceState = new CameraDeviceState(); + private List<Surface> mConfiguredSurfaces; private final ConditionVariable mIdle = new ConditionVariable(/*open*/true); @@ -84,6 +86,9 @@ public class LegacyCameraDevice implements AutoCloseable { mResultHandler.post(new Runnable() { @Override public void run() { + if (DEBUG) { + Log.d(TAG, "doing onError callback."); + } try { mDeviceCallbacks.onCameraError(errorCode, extras); } catch (RemoteException e) { @@ -92,13 +97,14 @@ public class LegacyCameraDevice implements AutoCloseable { } } }); - - } @Override public void onConfiguring() { // Do nothing + if (DEBUG) { + Log.d(TAG, "doing onConfiguring callback."); + } } @Override @@ -108,6 +114,9 @@ public class LegacyCameraDevice implements AutoCloseable { mResultHandler.post(new Runnable() { @Override public void run() { + if (DEBUG) { + Log.d(TAG, "doing onIdle callback."); + } try { mDeviceCallbacks.onCameraIdle(); } catch (RemoteException e) { @@ -126,6 +135,9 @@ public class LegacyCameraDevice implements AutoCloseable { mResultHandler.post(new Runnable() { @Override public void run() { + if (DEBUG) { + Log.d(TAG, "doing onCaptureStarted callback."); + } try { // TODO: Don't fake timestamp mDeviceCallbacks.onCaptureStarted(extras, timestamp); @@ -135,7 +147,6 @@ public class LegacyCameraDevice implements AutoCloseable { } } }); - } @Override @@ -145,6 +156,9 @@ public class LegacyCameraDevice implements AutoCloseable { mResultHandler.post(new Runnable() { @Override public void run() { + if (DEBUG) { + Log.d(TAG, "doing onCaptureResult callback."); + } try { // TODO: Don't fake metadata mDeviceCallbacks.onResultReceived(result, extras); @@ -200,16 +214,35 @@ public class LegacyCameraDevice implements AutoCloseable { /** * Configure the device with a set of output surfaces. * + * <p>Using empty or {@code null} {@code outputs} is the same as unconfiguring.</p> + * + * <p>Every surface in {@code outputs} must be non-{@code null}.</p> + * * @param outputs a list of surfaces to set. - * @return an error code for this binder operation, or {@link CameraBinderDecorator.NO_ERROR} + * @return an error code for this binder operation, or {@link NO_ERROR} * on success. */ public int configureOutputs(List<Surface> outputs) { + if (outputs != null) { + for (Surface output : outputs) { + if (output == null) { + Log.e(TAG, "configureOutputs - null outputs are not allowed"); + return BAD_VALUE; + } + } + } + int error = mDeviceState.setConfiguring(); - if (error == CameraBinderDecorator.NO_ERROR) { + if (error == NO_ERROR) { mRequestThreadManager.configure(outputs); error = mDeviceState.setIdle(); } + + // TODO: May also want to check the surfaces more deeply (e.g. state, formats, sizes..) + if (error == NO_ERROR) { + mConfiguredSurfaces = outputs != null ? new ArrayList<>(outputs) : null; + } + return error; } @@ -226,7 +259,35 @@ public class LegacyCameraDevice implements AutoCloseable { */ public int submitRequestList(List<CaptureRequest> requestList, boolean repeating, /*out*/LongParcelable frameNumber) { - // TODO: validate request here + if (requestList == null || requestList.isEmpty()) { + Log.e(TAG, "submitRequestList - Empty/null requests are not allowed"); + return BAD_VALUE; + } + + // Make sure that there all requests have at least 1 surface; all surfaces are non-null + for (CaptureRequest request : requestList) { + if (request.getTargets().isEmpty()) { + Log.e(TAG, "submitRequestList - " + + "Each request must have at least one Surface target"); + return BAD_VALUE; + } + + for (Surface surface : request.getTargets()) { + if (surface == null) { + Log.e(TAG, "submitRequestList - Null Surface targets are not allowed"); + return BAD_VALUE; + } else if (mConfiguredSurfaces == null) { + Log.e(TAG, "submitRequestList - must configure " + + " device with valid surfaces before submitting requests"); + return INVALID_OPERATION; + } else if (!mConfiguredSurfaces.contains(surface)) { + Log.e(TAG, "submitRequestList - cannot use a surface that wasn't configured"); + return BAD_VALUE; + } + } + } + + // TODO: further validation of request here mIdle.close(); return mRequestThreadManager.submitCaptureRequests(requestList, repeating, frameNumber); diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java index 8bb066fd09a3..6fa2134571fb 100644 --- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java +++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java @@ -21,12 +21,16 @@ import android.hardware.Camera; import android.hardware.Camera.CameraInfo; import android.hardware.Camera.Size; import android.hardware.camera2.CameraCharacteristics; +import android.hardware.camera2.CaptureRequest; +import android.hardware.camera2.CaptureResult; import android.hardware.camera2.impl.CameraMetadataNative; import android.hardware.camera2.params.StreamConfiguration; import android.hardware.camera2.params.StreamConfigurationDuration; import android.util.Log; +import android.util.Range; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import static com.android.internal.util.Preconditions.*; @@ -44,6 +48,11 @@ public class LegacyMetadataMapper { private static final int HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22; private static final int HAL_PIXEL_FORMAT_BLOB = 0x21; + private static final long APPROXIMATE_CAPTURE_DELAY_MS = 200; // ms + private static final long APPROXIMATE_SENSOR_AREA = (1 << 20); // 8mp + private static final long APPROXIMATE_JPEG_ENCODE_TIME = 600; // ms + private static final long NS_PER_MS = 1000000; + /** * Create characteristics for a legacy device by mapping the {@code parameters} * and {@code info} @@ -86,14 +95,13 @@ public class LegacyMetadataMapper { private static void mapCameraParameters(CameraMetadataNative m, Camera.Parameters p) { mapStreamConfigs(m, p); + mapAeConfig(m, p); + mapCapabilities(m, p); // TODO: map other fields } private static void mapStreamConfigs(CameraMetadataNative m, Camera.Parameters p) { - // TODO: set non-empty durations - m.set(SCALER_AVAILABLE_MIN_FRAME_DURATIONS, new StreamConfigurationDuration[] {} ); - m.set(SCALER_AVAILABLE_STALL_DURATIONS, new StreamConfigurationDuration[] {} ); ArrayList<StreamConfiguration> availableStreamConfigs = new ArrayList<>(); /* @@ -122,10 +130,74 @@ public class LegacyMetadataMapper { String.format("mapStreamConfigs - Skipping non-public format %x", format)); } } + + List<Camera.Size> jpegSizes = p.getSupportedPictureSizes(); appendStreamConfig(availableStreamConfigs, HAL_PIXEL_FORMAT_BLOB, p.getSupportedPictureSizes()); m.set(SCALER_AVAILABLE_STREAM_CONFIGURATIONS, availableStreamConfigs.toArray(new StreamConfiguration[0])); + + // No frame durations available + m.set(SCALER_AVAILABLE_MIN_FRAME_DURATIONS, new StreamConfigurationDuration[0]); + + StreamConfigurationDuration[] jpegStalls = + new StreamConfigurationDuration[jpegSizes.size()]; + int i = 0; + long longestStallDuration = -1; + for (Camera.Size s : jpegSizes) { + long stallDuration = calculateJpegStallDuration(s); + jpegStalls[i++] = new StreamConfigurationDuration(HAL_PIXEL_FORMAT_BLOB, s.width, + s.height, stallDuration); + if (longestStallDuration < stallDuration) { + longestStallDuration = stallDuration; + } + } + // Set stall durations for jpeg, other formats use default stall duration + m.set(SCALER_AVAILABLE_STALL_DURATIONS, jpegStalls); + + m.set(SENSOR_INFO_MAX_FRAME_DURATION, longestStallDuration); + } + + @SuppressWarnings({"unchecked"}) + private static void mapAeConfig(CameraMetadataNative m, Camera.Parameters p) { + + List<int[]> fpsRanges = p.getSupportedPreviewFpsRange(); + if (fpsRanges == null) { + throw new AssertionError("Supported FPS ranges cannot be null."); + } + int rangesSize = fpsRanges.size(); + if (rangesSize <= 0) { + throw new AssertionError("At least one FPS range must be supported."); + } + Range<Integer>[] ranges = new Range[rangesSize]; + int i = 0; + for (int[] r : fpsRanges) { + ranges[i++] = Range.create(r[Camera.Parameters.PREVIEW_FPS_MIN_INDEX], + r[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]); + } + m.set(CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, ranges); + + List<String> antiBandingModes = p.getSupportedAntibanding(); + int antiBandingModesSize = antiBandingModes.size(); + if (antiBandingModesSize > 0) { + int[] modes = new int[antiBandingModesSize]; + int j = 0; + for (String mode : antiBandingModes) { + int convertedMode = convertAntiBandingMode(mode); + if (convertedMode == -1) { + Log.w(TAG, "Antibanding mode " + ((mode == null) ? "NULL" : mode) + + " not supported, skipping..."); + } else { + modes[j++] = convertedMode; + } + } + m.set(CONTROL_AE_AVAILABLE_ANTIBANDING_MODES, Arrays.copyOf(modes, j)); + } + } + + private static void mapCapabilities(CameraMetadataNative m, Camera.Parameters p) { + int[] capabilities = { REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE }; + m.set(REQUEST_AVAILABLE_CAPABILITIES, capabilities); } private static void appendStreamConfig( @@ -136,4 +208,115 @@ public class LegacyMetadataMapper { configs.add(config); } } + + /** + * Returns -1 if the anti-banding mode string is null, or not supported. + */ + private static int convertAntiBandingMode(final String mode) { + if (mode == null) { + return -1; + } + switch(mode) { + case Camera.Parameters.ANTIBANDING_OFF: { + return CONTROL_AE_ANTIBANDING_MODE_OFF; + } + case Camera.Parameters.ANTIBANDING_50HZ: { + return CONTROL_AE_ANTIBANDING_MODE_50HZ; + } + case Camera.Parameters.ANTIBANDING_60HZ: { + return CONTROL_AE_ANTIBANDING_MODE_60HZ; + } + case Camera.Parameters.ANTIBANDING_AUTO: { + return CONTROL_AE_ANTIBANDING_MODE_AUTO; + } + default: { + return -1; + } + } + } + + /** + * Returns null if the anti-banding mode enum is not supported. + */ + private static String convertAntiBandingModeToLegacy(int mode) { + switch(mode) { + case CONTROL_AE_ANTIBANDING_MODE_OFF: { + return Camera.Parameters.ANTIBANDING_OFF; + } + case CONTROL_AE_ANTIBANDING_MODE_50HZ: { + return Camera.Parameters.ANTIBANDING_50HZ; + } + case CONTROL_AE_ANTIBANDING_MODE_60HZ: { + return Camera.Parameters.ANTIBANDING_60HZ; + } + case CONTROL_AE_ANTIBANDING_MODE_AUTO: { + return Camera.Parameters.ANTIBANDING_AUTO; + } + default: { + return null; + } + } + } + + + private static int[] convertAeFpsRangeToLegacy(Range<Integer> fpsRange) { + int[] legacyFps = new int[2]; + legacyFps[Camera.Parameters.PREVIEW_FPS_MIN_INDEX] = fpsRange.getLower(); + legacyFps[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] = fpsRange.getUpper(); + return legacyFps; + } + + /** + * Return the stall duration for a given output jpeg size in nanoseconds. + * + * <p>An 8mp image is chosen to have a stall duration of 0.8 seconds.</p> + */ + private static long calculateJpegStallDuration(Camera.Size size) { + long baseDuration = APPROXIMATE_CAPTURE_DELAY_MS * NS_PER_MS; // 200ms for capture + long area = size.width * (long) size.height; + long stallPerArea = APPROXIMATE_JPEG_ENCODE_TIME * NS_PER_MS / + APPROXIMATE_SENSOR_AREA; // 600ms stall for 8mp + return baseDuration + area * stallPerArea; + } + + /** + * Generate capture result metadata from legacy camera parameters. + * + * @param params a {@link Camera.Parameters} object to generate metadata from. + * @param request the {@link CaptureRequest} used for this result. + * @param timestamp the timestamp to use for this result in nanoseconds. + * @return a {@link CameraMetadataNative} object containing result metadata. + */ + public static CameraMetadataNative convertResultMetadata(Camera.Parameters params, + CaptureRequest request, + long timestamp) { + CameraMetadataNative result = new CameraMetadataNative(); + result.set(CaptureResult.LENS_FOCAL_LENGTH, params.getFocalLength()); + result.set(CaptureResult.SENSOR_TIMESTAMP, timestamp); + + // TODO: Remaining result metadata tags conversions. + return result; + } + + /** + * Set the legacy parameters using the request metadata. + * + * @param request a {@link CaptureRequest} object to generate parameters from. + * @param params the a {@link Camera.Parameters} to set parameters in. + */ + public static void convertRequestMetadata(CaptureRequest request, + /*out*/Camera.Parameters params) { + Integer antiBandingMode = request.get(CaptureRequest.CONTROL_AE_ANTIBANDING_MODE); + if (antiBandingMode != null) { + String legacyMode = convertAntiBandingModeToLegacy(antiBandingMode); + if (legacyMode != null) params.setAntibanding(legacyMode); + } + + Range<Integer> aeFpsRange = request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE); + if (aeFpsRange != null) { + int[] legacyFps = convertAeFpsRangeToLegacy(aeFpsRange); + params.setPreviewFpsRange(legacyFps[Camera.Parameters.PREVIEW_FPS_MIN_INDEX], + legacyFps[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]); + } + } } diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java index 7b522ffa36ce..e0f3429d8bec 100644 --- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java +++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java @@ -16,11 +16,9 @@ package android.hardware.camera2.legacy; -import android.graphics.ImageFormat; import android.graphics.SurfaceTexture; import android.hardware.Camera; import android.hardware.camera2.CaptureRequest; -import android.hardware.camera2.CaptureResult; import android.hardware.camera2.utils.LongParcelable; import android.hardware.camera2.impl.CameraMetadataNative; import android.os.ConditionVariable; @@ -71,21 +69,26 @@ public class RequestThreadManager { private static final float ASPECT_RATIO_TOLERANCE = 0.01f; private boolean mPreviewRunning = false; + private volatile long mLastJpegTimestamp; + private volatile long mLastPreviewTimestamp; private volatile RequestHolder mInFlightPreview; private volatile RequestHolder mInFlightJpeg; - private List<Surface> mPreviewOutputs = new ArrayList<Surface>(); - private List<Surface> mCallbackOutputs = new ArrayList<Surface>(); + private final List<Surface> mPreviewOutputs = new ArrayList<Surface>(); + private final List<Surface> mCallbackOutputs = new ArrayList<Surface>(); private GLThreadManager mGLThreadManager; private SurfaceTexture mPreviewTexture; + private Camera.Parameters mParams; private Size mIntermediateBufferSize; private final RequestQueue mRequestQueue = new RequestQueue(); + private CaptureRequest mLastRequest = null; private SurfaceTexture mDummyTexture; private Surface mDummySurface; private final FpsCounter mPrevCounter = new FpsCounter("Incoming Preview"); + private final FpsCounter mRequestCounter = new FpsCounter("Incoming Requests"); /** * Container object for Configure messages. @@ -209,23 +212,34 @@ public class RequestThreadManager { } }; + private final Camera.ShutterCallback mJpegShutterCallback = new Camera.ShutterCallback() { + @Override + public void onShutter() { + mLastJpegTimestamp = SystemClock.elapsedRealtimeNanos(); + } + }; + private final SurfaceTexture.OnFrameAvailableListener mPreviewCallback = new SurfaceTexture.OnFrameAvailableListener() { @Override public void onFrameAvailable(SurfaceTexture surfaceTexture) { - if (DEBUG) { - mPrevCounter.countAndLog(); - } RequestHolder holder = mInFlightPreview; if (holder == null) { + mGLThreadManager.queueNewFrame(null); Log.w(TAG, "Dropping preview frame."); - mInFlightPreview = null; return; } + + if (DEBUG) { + mPrevCounter.countAndLog(); + } + mInFlightPreview = null; + if (holder.hasPreviewTargets()) { mGLThreadManager.queueNewFrame(holder.getHolderTargets()); } + mLastPreviewTimestamp = surfaceTexture.getTimestamp(); mReceivedPreview.open(); } }; @@ -252,7 +266,7 @@ public class RequestThreadManager { } mInFlightJpeg = request; // TODO: Hook up shutter callback to CameraDeviceStateListener#onCaptureStarted - mCamera.takePicture(/*shutter*/null, /*raw*/null, mJpegCallback); + mCamera.takePicture(mJpegShutterCallback, /*raw*/null, mJpegCallback); mPreviewRunning = false; } @@ -300,19 +314,20 @@ public class RequestThreadManager { mInFlightPreview = null; mInFlightJpeg = null; - - for (Surface s : outputs) { - int format = LegacyCameraDevice.nativeDetectSurfaceType(s); - switch (format) { - case CameraMetadataNative.NATIVE_JPEG_FORMAT: - mCallbackOutputs.add(s); - break; - default: - mPreviewOutputs.add(s); - break; + if (outputs != null) { + for (Surface s : outputs) { + int format = LegacyCameraDevice.nativeDetectSurfaceType(s); + switch (format) { + case CameraMetadataNative.NATIVE_JPEG_FORMAT: + mCallbackOutputs.add(s); + break; + default: + mPreviewOutputs.add(s); + break; + } } } - + mParams = mCamera.getParameters(); if (mPreviewOutputs.size() > 0) { List<Size> outputSizes = new ArrayList<>(outputs.size()); for (Surface s : mPreviewOutputs) { @@ -323,13 +338,11 @@ public class RequestThreadManager { Size largestOutput = findLargestByArea(outputSizes); - Camera.Parameters params = mCamera.getParameters(); - // Find largest jpeg dimension - assume to have the same aspect ratio as sensor. - List<Size> supportedJpegSizes = convertSizeList(params.getSupportedPictureSizes()); + List<Size> supportedJpegSizes = convertSizeList(mParams.getSupportedPictureSizes()); Size largestJpegDimen = findLargestByArea(supportedJpegSizes); - List<Size> supportedPreviewSizes = convertSizeList(params.getSupportedPreviewSizes()); + List<Size> supportedPreviewSizes = convertSizeList(mParams.getSupportedPreviewSizes()); // Use smallest preview dimension with same aspect ratio as sensor that is >= than all // of the configured output dimensions. If none exists, fall back to using the largest @@ -357,8 +370,6 @@ public class RequestThreadManager { } } - - // TODO: Detect and optimize single-output paths here to skip stream teeing. if (mGLThreadManager == null) { mGLThreadManager = new GLThreadManager(mCameraId); @@ -419,7 +430,6 @@ public class RequestThreadManager { private final Handler.Callback mRequestHandlerCb = new Handler.Callback() { private boolean mCleanup = false; - private List<RequestHolder> mRepeating = null; @SuppressWarnings("unchecked") @Override @@ -428,10 +438,14 @@ public class RequestThreadManager { return true; } + if (DEBUG) { + Log.d(TAG, "Request thread handling message:" + msg.what); + } switch (msg.what) { case MSG_CONFIGURE_OUTPUTS: ConfigureHolder config = (ConfigureHolder) msg.obj; - Log.i(TAG, "Configure outputs: " + config.surfaces.size() + + int sizes = config.surfaces != null ? config.surfaces.size() : 0; + Log.i(TAG, "Configure outputs: " + sizes + " surfaces configured."); try { configureOutputs(config.surfaces); @@ -459,7 +473,15 @@ public class RequestThreadManager { List<RequestHolder> requests = nextBurst.first.produceRequestHolders(nextBurst.second); for (RequestHolder holder : requests) { + CaptureRequest request = holder.getRequest(); + if (mLastRequest == null || mLastRequest != request) { + mLastRequest = request; + LegacyMetadataMapper.convertRequestMetadata(mLastRequest, + /*out*/mParams); + mCamera.setParameters(mParams); + } mDeviceState.setCaptureStart(holder); + long timestamp = 0; try { if (holder.hasPreviewTargets()) { mReceivedPreview.close(); @@ -468,6 +490,7 @@ public class RequestThreadManager { // TODO: report error to CameraDevice Log.e(TAG, "Hit timeout for preview callback!"); } + timestamp = mLastPreviewTimestamp; } if (holder.hasJpegTargets()) { mReceivedJpeg.close(); @@ -478,16 +501,19 @@ public class RequestThreadManager { Log.e(TAG, "Hit timeout for jpeg callback!"); } mInFlightJpeg = null; + timestamp = mLastJpegTimestamp; } } catch (IOException e) { // TODO: err handling throw new IOError(e); } - Camera.Parameters params = mCamera.getParameters(); - CameraMetadataNative result = convertResultMetadata(params, - holder.getRequest()); + CameraMetadataNative result = LegacyMetadataMapper.convertResultMetadata(mParams, + request, timestamp); mDeviceState.setCaptureResult(holder, result); } + if (DEBUG) { + mRequestCounter.countAndLog(); + } break; case MSG_CLEANUP: mCleanup = true; @@ -506,15 +532,6 @@ public class RequestThreadManager { } }; - private CameraMetadataNative convertResultMetadata(Camera.Parameters params, - CaptureRequest request) { - CameraMetadataNative result = new CameraMetadataNative(); - result.set(CaptureResult.LENS_FOCAL_LENGTH, params.getFocalLength()); - - // TODO: Remaining result metadata tags conversions. - return result; - } - /** * Create a new RequestThreadManager. * @@ -597,12 +614,14 @@ public class RequestThreadManager { /** - * Configure with the current output Surfaces. + * Configure with the current list of output Surfaces. * * <p> * This operation blocks until the configuration is complete. * </p> * + * <p>Using a {@code null} or empty {@code outputs} list is the equivalent of unconfiguring.</p> + * * @param outputs a {@link java.util.Collection} of outputs to configure. */ public void configure(Collection<Surface> outputs) { diff --git a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java index 49f419f2dcf0..e9d32f0caa34 100644 --- a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java +++ b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java @@ -486,6 +486,7 @@ public class SurfaceTextureRenderer { } checkGlError("before updateTexImage"); mSurfaceTexture.updateTexImage(); + if (targetSurfaces == null) return; for (EGLSurfaceHolder holder : mSurfaces) { if (targetSurfaces.contains(holder.surface)) { makeCurrent(holder.eglSurface); diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java index 30364258fe94..fff171b92c1e 100644 --- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java +++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java @@ -63,6 +63,12 @@ import static com.android.internal.util.Preconditions.*; public final class StreamConfigurationMap { private static final String TAG = "StreamConfigurationMap"; + + /** + * Indicates that a minimum frame duration is not available for a particular configuration. + */ + public static final long NO_MIN_FRAME_DURATION = 0; + /** * Create a new {@link StreamConfigurationMap}. * @@ -359,7 +365,9 @@ public final class StreamConfigurationMap { * * @param format an image format from {@link ImageFormat} or {@link PixelFormat} * @param size an output-compatible size - * @return a minimum frame duration {@code >=} 0 in nanoseconds + * @return a minimum frame duration {@code >} 0 in nanoseconds, or + * {@link #NO_MIN_FRAME_DURATION} if the minimum frame duration is not available (this + * can only occur on limited mode devices). * * @throws IllegalArgumentException if {@code format} or {@code size} was not supported * @throws NullPointerException if {@code size} was {@code null} @@ -406,7 +414,9 @@ public final class StreamConfigurationMap { * a class which is supported by {@link #isOutputSupportedFor(Class)} and has a * non-empty array returned by {@link #getOutputSizes(Class)} * @param size an output-compatible size - * @return a minimum frame duration {@code >=} 0 in nanoseconds + * @return a minimum frame duration {@code >} 0 in nanoseconds, or + * {@link #NO_MIN_FRAME_DURATION} if the minimum frame duration is not available (this + * can only occur on limited mode devices). * * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported * @throws NullPointerException if {@code size} or {@code klass} was {@code null} @@ -892,7 +902,7 @@ public final class StreamConfigurationMap { private long getDurationDefault(int duration) { switch (duration) { case DURATION_MIN_FRAME: - throw new AssertionError("Minimum frame durations are required to be listed"); + return NO_MIN_FRAME_DURATION; case DURATION_STALL: return 0L; // OK. A lack of a stall duration implies a 0 stall duration default: diff --git a/core/java/android/hardware/camera2/utils/CloseableLock.java b/core/java/android/hardware/camera2/utils/CloseableLock.java new file mode 100644 index 000000000000..af55055c2d32 --- /dev/null +++ b/core/java/android/hardware/camera2/utils/CloseableLock.java @@ -0,0 +1,330 @@ +/* + * 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.hardware.camera2.utils; + +import android.util.Log; + +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +/** + * Implement a shared/exclusive lock that can be closed. + * + * <p>A shared lock can be acquired if any other shared locks are also acquired. An + * exclusive lock acquire will block until all shared locks have been released.</p> + * + * <p>Locks are re-entrant; trying to acquire another lock (of the same type) + * while a lock is already held will immediately succeed.</p> + * + * <p>Acquiring to acquire a shared lock while holding an exclusive lock or vice versa is not + * supported; attempting it will throw an {@link IllegalStateException}.</p> + * + * <p>If the lock is closed, all future and current acquires will immediately return {@code null}. + * </p> + */ +public class CloseableLock implements AutoCloseable { + + private static final boolean VERBOSE = false; + + private final String TAG = "CloseableLock"; + private final String mName; + + private volatile boolean mClosed = false; + + /** If an exclusive lock is acquired by some thread. */ + private boolean mExclusive = false; + /** + * How many shared locks are acquired by any thread: + * + * <p>Reentrant locking increments this. If an exclusive lock is held, + * this value will stay at 0.</p> + */ + private int mSharedLocks = 0; + + private final ReentrantLock mLock = new ReentrantLock(); + /** This condition automatically releases mLock when waiting; re-acquiring it after notify */ + private final Condition mCondition = mLock.newCondition(); + + /** How many times the current thread is holding the lock */ + private final ThreadLocal<Integer> mLockCount = + new ThreadLocal<Integer>() { + @Override protected Integer initialValue() { + return 0; + } + }; + + /** + * Helper class to release a lock at the end of a try-with-resources statement. + */ + public class ScopedLock implements AutoCloseable { + private ScopedLock() {} + + /** Release the lock with {@link CloseableLock#releaseLock}. */ + @Override + public void close() { + releaseLock(); + } + } + + /** + * Create a new instance; starts out with 0 locks acquired. + */ + public CloseableLock() { + mName = ""; + } + + /** + * Create a new instance; starts out with 0 locks acquired. + * + * @param name set an optional name for logging functionality + */ + public CloseableLock(String name) { + mName = name; + } + + /** + * Acquires the lock exclusively (blocking), marks it as closed, then releases the lock. + * + * <p>Marking a lock as closed will fail all further acquisition attempts; + * it will also immediately unblock all other threads currently trying to acquire a lock.</p> + * + * <p>This operation is idempotent; calling it more than once has no effect.</p> + * + * @throws IllegalStateException + * if an attempt is made to {@code close} while this thread has a lock acquired + */ + @Override + public void close() { + if (mClosed) { + log("close - already closed; ignoring"); + return; + } + + ScopedLock scoper = acquireExclusiveLock(); + // Already closed by another thread? + if (scoper == null) { + return; + } else if (mLockCount.get() != 1) { + // Future: may want to add a #releaseAndClose to allow this. + throw new IllegalStateException( + "Cannot close while one or more acquired locks are being held by this " + + "thread; release all other locks first"); + } + + try { + mLock.lock(); + + mClosed = true; + mExclusive = false; + mSharedLocks = 0; + mLockCount.remove(); + + // Notify all threads that are waiting to unblock and return immediately + mCondition.signalAll(); + } finally { + mLock.unlock(); + } + + log("close - completed"); + } + + /** + * Try to acquire the lock non-exclusively, blocking until the operation completes. + * + * <p>If the lock has already been closed, or being closed before this operation returns, + * the call will immediately return {@code false}.</p> + * + * <p>If other threads hold a non-exclusive lock (and the lock is not yet closed), + * this operation will return immediately. If another thread holds an exclusive lock, + * this thread will block until the exclusive lock has been released.</p> + * + * <p>This lock is re-entrant; acquiring more than one non-exclusive lock per thread is + * supported, and must be matched by an equal number of {@link #releaseLock} calls.</p> + * + * @return {@code ScopedLock} instance if the lock was acquired, or {@code null} if the lock + * was already closed. + * + * @throws IllegalStateException if this thread is already holding an exclusive lock + */ + public ScopedLock acquireLock() { + + int ownedLocks; + + try { + mLock.lock(); + + // Lock is already closed, all further acquisitions will fail + if (mClosed) { + log("acquire lock early aborted (already closed)"); + return null; + } + + ownedLocks = mLockCount.get(); + + // This thread is already holding an exclusive lock + if (mExclusive && ownedLocks > 0) { + throw new IllegalStateException( + "Cannot acquire shared lock while holding exclusive lock"); + } + + // Is another thread holding the exclusive lock? Block until we can get in. + while (mExclusive) { + mCondition.awaitUninterruptibly(); + + // Did another thread #close while we were waiting? Unblock immediately. + if (mClosed) { + log("acquire lock unblocked aborted (already closed)"); + return null; + } + } + + mSharedLocks++; + + ownedLocks = mLockCount.get() + 1; + mLockCount.set(ownedLocks); + } finally { + mLock.unlock(); + } + + log("acquired lock (local own count = " + ownedLocks + ""); + return new ScopedLock(); + } + + /** + * Try to acquire the lock exclusively, blocking until all other threads release their locks. + * + * <p>If the lock has already been closed, or being closed before this operation returns, + * the call will immediately return {@code false}.</p> + * + * <p>If any other threads are holding a lock, this thread will block until all + * other locks are released.</p> + * + * <p>This lock is re-entrant; acquiring more than one exclusive lock per thread is supported, + * and must be matched by an equal number of {@link #releaseLock} calls.</p> + * + * @return {@code ScopedLock} instance if the lock was acquired, or {@code null} if the lock + * was already closed. + * + * @throws IllegalStateException + * if an attempt is made to acquire an exclusive lock while already holding a lock + */ + public ScopedLock acquireExclusiveLock() { + + int ownedLocks; + + try { + mLock.lock(); + + // Lock is already closed, all further acquisitions will fail + if (mClosed) { + log("acquire exclusive lock early aborted (already closed)"); + return null; + } + + ownedLocks = mLockCount.get(); + + // This thread is already holding a shared lock + if (!mExclusive && ownedLocks > 0) { + throw new IllegalStateException( + "Cannot acquire exclusive lock while holding shared lock"); + } + + /* + * Is another thread holding the lock? Block until we can get in. + * + * If we are already holding the lock, always let it through since + * we are just reentering the exclusive lock. + */ + while (ownedLocks == 0 && (mExclusive || mSharedLocks > 0)) { + mCondition.awaitUninterruptibly(); + + // Did another thread #close while we were waiting? Unblock immediately. + if (mClosed) { + log("acquire exclusive lock unblocked aborted (already closed)"); + return null; + } + } + + mExclusive = true; + + ownedLocks = mLockCount.get() + 1; + mLockCount.set(ownedLocks); + } finally { + mLock.unlock(); + } + + log("acquired exclusive lock (local own count = " + ownedLocks + ""); + return new ScopedLock(); + } + + /** + * Release a single lock that was acquired. + * + * <p>Any other other that is blocked and trying to acquire a lock will get a chance + * to acquire the lock.</p> + * + * @throws IllegalStateException if no locks were acquired, or if the lock was already closed + */ + public void releaseLock() { + if (mLockCount.get() <= 0) { + throw new IllegalStateException( + "Cannot release lock that was not acquired by this thread"); + } + + int ownedLocks; + + try { + mLock.lock(); + + // Lock is already closed, it couldn't have been acquired in the first place + if (mClosed) { + throw new IllegalStateException("Do not release after the lock has been closed"); + } + + if (!mExclusive) { + mSharedLocks--; + } else { + if (mSharedLocks != 0) { + throw new AssertionError("Too many shared locks " + mSharedLocks); + } + } + + ownedLocks = mLockCount.get() - 1; + mLockCount.set(ownedLocks); + + if (ownedLocks == 0 && mExclusive) { + // Wake up any threads that might be waiting for the exclusive lock to be released + mExclusive = false; + mCondition.signalAll(); + } else if (ownedLocks == 0 && mSharedLocks == 0) { + // Wake up any threads that might be trying to get the exclusive lock + mCondition.signalAll(); + } + } finally { + mLock.unlock(); + } + + log("released lock (local lock count " + ownedLocks + ")"); + } + + private void log(String what) { + if (VERBOSE) { + Log.v(TAG + "[" + mName + "]", what); + } + } + +} diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index 9218c111d824..53e87a6f2656 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -25,6 +25,7 @@ import android.nfc.IAppCallback; import android.nfc.INfcAdapterExtras; import android.nfc.INfcTag; import android.nfc.INfcCardEmulation; +import android.nfc.INfcLockscreenDispatch; import android.os.Bundle; /** @@ -52,4 +53,6 @@ interface INfcAdapter void setReaderMode (IBinder b, IAppCallback callback, int flags, in Bundle extras); void setP2pModes(int initatorModes, int targetModes); + + void registerLockscreenDispatch(INfcLockscreenDispatch lockscreenDispatch, in int[] techList); } diff --git a/core/java/android/nfc/INfcLockscreenDispatch.aidl b/core/java/android/nfc/INfcLockscreenDispatch.aidl new file mode 100644 index 000000000000..27e9a8ccb2d2 --- /dev/null +++ b/core/java/android/nfc/INfcLockscreenDispatch.aidl @@ -0,0 +1,12 @@ +package android.nfc; + +import android.nfc.Tag; + +/** + * @hide + */ +interface INfcLockscreenDispatch { + + boolean onTagDetected(in Tag tag); + +} diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index dd8e41c0067b..899106639dd7 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -380,6 +380,16 @@ public final class NfcAdapter { public Uri[] createBeamUris(NfcEvent event); } + + /** + * A callback to be invoked when an application has registered for receiving + * tags at the lockscreen. + */ + public interface NfcLockscreenDispatch { + public boolean onTagDetected(Tag tag); + } + + /** * Helper to check if this device has FEATURE_NFC, but without using * a context. @@ -1417,6 +1427,23 @@ public final class NfcAdapter { } } + public boolean registerLockscreenDispatch(final NfcLockscreenDispatch lockscreenDispatch, + int[] techList) { + try { + sService.registerLockscreenDispatch(new INfcLockscreenDispatch.Stub() { + @Override + public boolean onTagDetected(Tag tag) throws RemoteException { + return lockscreenDispatch.onTagDetected(tag); + } + }, techList); + } catch (RemoteException e) { + attemptDeadServiceRecovery(e); + return false; + } + + return true; + } + /** * @hide */ diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 1e7d7f1d4830..8038a38062c6 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -1694,7 +1694,7 @@ public final class ContactsContract { */ public static final class Entity implements BaseColumns, ContactsColumns, ContactNameColumns, RawContactsColumns, BaseSyncColumns, SyncColumns, DataColumns, - StatusColumns, ContactOptionsColumns, ContactStatusColumns { + StatusColumns, ContactOptionsColumns, ContactStatusColumns, DataUsageStatColumns { /** * no public constructor since this is a utility class */ @@ -7813,6 +7813,25 @@ public final class ContactsContract { "pinned_position_update"); /** + * <p> + * The method to invoke in order to undemote a formerly demoted contact. The contact id of + * the contact must be provided as an argument. If the contact was not previously demoted, + * nothing will be done. + * </p> + * + * <p> + * Example: + * <pre> + * final long contactId = 10; + * resolver.call(ContactsContract.AUTHORITY_URI, PinnedPositions.UNDEMOTE_METHOD, + * String.valueOf(contactId), null); + * </pre> + * + * </p> + */ + public static final String UNDEMOTE_METHOD = "undemote"; + + /** * Default value for the pinned position of an unpinned contact. Also equal to * {@link Integer#MAX_VALUE}. */ diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 06c05eedc8ab..2a5e9fd904ef 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -4537,12 +4537,6 @@ public final class Settings { public static final String SMS_DEFAULT_APPLICATION = "sms_default_application"; /** - * Specifies the package name currently configured to be the primary phone application - * @hide - */ - public static final String PHONE_DEFAULT_APPLICATION = "phone_default_application"; - - /** * Name of a package that the current user has explicitly allowed to see all of that * user's notifications. * diff --git a/core/java/android/util/PathParser.java b/core/java/android/util/PathParser.java new file mode 100644 index 000000000000..f90ce51be891 --- /dev/null +++ b/core/java/android/util/PathParser.java @@ -0,0 +1,528 @@ +/* + * 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 android.graphics.Path; +import android.util.Log; + +import java.util.ArrayList; +import java.util.Arrays; + +/** + * @hide + */ +public class PathParser { + static final String LOGTAG = PathParser.class.getSimpleName(); + + /** + * @param pathData The string representing a path, the same as "d" string in svg file. + * @return the generated Path object. + */ + public static Path createPathFromPathData(String pathData) { + Path path = new Path(); + PathDataNode[] nodes = createNodesFromPathData(pathData); + if (nodes != null) { + PathDataNode.nodesToPath(nodes, path); + return path; + } + return null; + } + + /** + * @param pathData The string representing a path, the same as "d" string in svg file. + * @return an array of the PathDataNode. + */ + public static PathDataNode[] createNodesFromPathData(String pathData) { + int start = 0; + int end = 1; + + ArrayList<PathDataNode> list = new ArrayList<PathDataNode>(); + while (end < pathData.length()) { + end = nextStart(pathData, end); + String s = pathData.substring(start, end); + float[] val = getFloats(s); + addNode(list, s.charAt(0), val); + + start = end; + end++; + } + if ((end - start) == 1 && start < pathData.length()) { + addNode(list, pathData.charAt(start), new float[0]); + } + return list.toArray(new PathDataNode[list.size()]); + } + + private static int nextStart(String s, int end) { + char c; + + while (end < s.length()) { + c = s.charAt(end); + if (((c - 'A') * (c - 'Z') <= 0) || (((c - 'a') * (c - 'z') <= 0))) { + return end; + } + end++; + } + return end; + } + + private static void addNode(ArrayList<PathDataNode> list, char cmd, float[] val) { + list.add(new PathDataNode(cmd, val)); + } + + + /** + * Parse the floats in the string. + * This is an optimized version of parseFloat(s.split(",|\\s")); + * + * @param s the string containing a command and list of floats + * @return array of floats + */ + private static float[] getFloats(String s) { + if (s.charAt(0) == 'z' | s.charAt(0) == 'Z') { + return new float[0]; + } + try { + float[] tmp = new float[s.length()]; + int count = 0; + int pos = 1, end; + while ((end = extract(s, pos)) >= 0) { + if (pos < end) { + tmp[count++] = Float.parseFloat(s.substring(pos, end)); + } + pos = end + 1; + } + // handle the final float if there is one + if (pos < s.length()) { + tmp[count++] = Float.parseFloat(s.substring(pos, s.length())); + } + return Arrays.copyOf(tmp, count); + } catch (NumberFormatException e){ + Log.e(LOGTAG,"error in parsing \""+s+"\""); + throw e; + } + } + + /** + * Calculate the position of the next comma or space + * @param s the string to search + * @param start the position to start searching + * @return the position of the next comma or space or -1 if none found + */ + private static int extract(String s, int start) { + int space = s.indexOf(' ', start); + int comma = s.indexOf(',', start); + if (space == -1) { + return comma; + } + if (comma == -1) { + return space; + } + return (comma > space) ? space : comma; + } + + public static class PathDataNode { + private char mType; + private float[] mParams; + + private PathDataNode(char type, float[] params) { + mType = type; + mParams = params; + } + + private PathDataNode(PathDataNode n) { + mType = n.mType; + mParams = Arrays.copyOf(n.mParams, n.mParams.length); + } + + public static void nodesToPath(PathDataNode[] node, Path path) { + float[] current = new float[4]; + char previousCommand = 'm'; + for (int i = 0; i < node.length; i++) { + addCommand(path, current, previousCommand, node[i].mType, node[i].mParams); + previousCommand = node[i].mType; + } + } + + private static void addCommand(Path path, float[] current, + char previousCmd, char cmd, float[] val) { + + int incr = 2; + float currentX = current[0]; + float currentY = current[1]; + float ctrlPointX = current[2]; + float ctrlPointY = current[3]; + float reflectiveCtrlPointX; + float reflectiveCtrlPointY; + + switch (cmd) { + case 'z': + case 'Z': + path.close(); + return; + case 'm': + case 'M': + case 'l': + case 'L': + case 't': + case 'T': + incr = 2; + break; + case 'h': + case 'H': + case 'v': + case 'V': + incr = 1; + break; + case 'c': + case 'C': + incr = 6; + break; + case 's': + case 'S': + case 'q': + case 'Q': + incr = 4; + break; + case 'a': + case 'A': + incr = 7; + break; + } + for (int k = 0; k < val.length; k += incr) { + switch (cmd) { + case 'm': // moveto - Start a new sub-path (relative) + path.rMoveTo(val[k + 0], val[k + 1]); + currentX += val[k + 0]; + currentY += val[k + 1]; + break; + case 'M': // moveto - Start a new sub-path + path.moveTo(val[k + 0], val[k + 1]); + currentX = val[k + 0]; + currentY = val[k + 1]; + break; + case 'l': // lineto - Draw a line from the current point (relative) + path.rLineTo(val[k + 0], val[k + 1]); + currentX += val[k + 0]; + currentY += val[k + 1]; + break; + case 'L': // lineto - Draw a line from the current point + path.lineTo(val[k + 0], val[k + 1]); + currentX = val[k + 0]; + currentY = val[k + 1]; + break; + case 'z': // closepath - Close the current subpath + case 'Z': // closepath - Close the current subpath + path.close(); + break; + case 'h': // horizontal lineto - Draws a horizontal line (relative) + path.rLineTo(val[k + 0], 0); + currentX += val[k + 0]; + break; + case 'H': // horizontal lineto - Draws a horizontal line + path.lineTo(val[k + 0], currentY); + currentX = val[k + 0]; + break; + case 'v': // vertical lineto - Draws a vertical line from the current point (r) + path.rLineTo(0, val[k + 0]); + currentY += val[k + 0]; + break; + case 'V': // vertical lineto - Draws a vertical line from the current point + path.lineTo(currentX, val[k + 0]); + currentY = val[k + 0]; + break; + case 'c': // curveto - Draws a cubic Bézier curve (relative) + path.rCubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3], + val[k + 4], val[k + 5]); + + ctrlPointX = currentX + val[k + 2]; + ctrlPointY = currentY + val[k + 3]; + currentX += val[k + 4]; + currentY += val[k + 5]; + + break; + case 'C': // curveto - Draws a cubic Bézier curve + path.cubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3], + val[k + 4], val[k + 5]); + currentX = val[k + 4]; + currentY = val[k + 5]; + ctrlPointX = val[k + 2]; + ctrlPointY = val[k + 3]; + break; + case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp) + reflectiveCtrlPointX = 0; + reflectiveCtrlPointY = 0; + if (previousCmd == 'c' || previousCmd == 's' + || previousCmd == 'C' || previousCmd == 'S') { + reflectiveCtrlPointX = currentX - ctrlPointX; + reflectiveCtrlPointY = currentY - ctrlPointY; + } + path.rCubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY, + val[k + 0], val[k + 1], + val[k + 2], val[k + 3]); + + ctrlPointX = currentX + val[k + 0]; + ctrlPointY = currentY + val[k + 1]; + currentX += val[k + 2]; + currentY += val[k + 3]; + break; + case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp) + reflectiveCtrlPointX = currentX; + reflectiveCtrlPointY = currentY; + if (previousCmd == 'c' || previousCmd == 's' + || previousCmd == 'C' || previousCmd == 'S') { + reflectiveCtrlPointX = 2 * currentX - ctrlPointX; + reflectiveCtrlPointY = 2 * currentY - ctrlPointY; + } + path.cubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY, + val[k + 0], val[k + 1], val[k + 2], val[k + 3]); + ctrlPointX = val[k + 0]; + ctrlPointY = val[k + 1]; + currentX = val[k + 2]; + currentY = val[k + 3]; + break; + case 'q': // Draws a quadratic Bézier (relative) + path.rQuadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]); + ctrlPointX = currentX + val[k + 0]; + ctrlPointY = currentY + val[k + 1]; + currentX += val[k + 2]; + currentY += val[k + 3]; + break; + case 'Q': // Draws a quadratic Bézier + path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]); + ctrlPointX = val[k + 0]; + ctrlPointY = val[k + 1]; + currentX = val[k + 2]; + currentY = val[k + 3]; + break; + case 't': // Draws a quadratic Bézier curve(reflective control point)(relative) + reflectiveCtrlPointX = 0; + reflectiveCtrlPointY = 0; + if (previousCmd == 'q' || previousCmd == 't' + || previousCmd == 'Q' || previousCmd == 'T') { + reflectiveCtrlPointX = currentX - ctrlPointX; + reflectiveCtrlPointY = currentY - ctrlPointY; + } + path.rQuadTo(reflectiveCtrlPointX, reflectiveCtrlPointY, + val[k + 0], val[k + 1]); + ctrlPointX = currentX + reflectiveCtrlPointX; + ctrlPointY = currentY + reflectiveCtrlPointY; + currentX += val[k + 0]; + currentY += val[k + 1]; + break; + case 'T': // Draws a quadratic Bézier curve (reflective control point) + reflectiveCtrlPointX = currentX; + reflectiveCtrlPointY = currentY; + if (previousCmd == 'q' || previousCmd == 't' + || previousCmd == 'Q' || previousCmd == 'T') { + reflectiveCtrlPointX = 2 * currentX - ctrlPointX; + reflectiveCtrlPointY = 2 * currentY - ctrlPointY; + } + path.quadTo(reflectiveCtrlPointX, reflectiveCtrlPointY, + val[k + 0], val[k + 1]); + ctrlPointX = reflectiveCtrlPointX; + ctrlPointY = reflectiveCtrlPointY; + currentX = val[k + 0]; + currentY = val[k + 1]; + break; + case 'a': // Draws an elliptical arc + // (rx ry x-axis-rotation large-arc-flag sweep-flag x y) + drawArc(path, + currentX, + currentY, + val[k + 5] + currentX, + val[k + 6] + currentY, + val[k + 0], + val[k + 1], + val[k + 2], + val[k + 3] != 0, + val[k + 4] != 0); + currentX += val[k + 5]; + currentY += val[k + 6]; + ctrlPointX = currentX; + ctrlPointY = currentY; + break; + case 'A': // Draws an elliptical arc + drawArc(path, + currentX, + currentY, + val[k + 5], + val[k + 6], + val[k + 0], + val[k + 1], + val[k + 2], + val[k + 3] != 0, + val[k + 4] != 0); + currentX = val[k + 5]; + currentY = val[k + 6]; + ctrlPointX = currentX; + ctrlPointY = currentY; + break; + } + previousCmd = cmd; + } + current[0] = currentX; + current[1] = currentY; + current[2] = ctrlPointX; + current[3] = ctrlPointY; + } + + private static void drawArc(Path p, + float x0, + float y0, + float x1, + float y1, + float a, + float b, + float theta, + boolean isMoreThanHalf, + boolean isPositiveArc) { + + /* Convert rotation angle from degrees to radians */ + double thetaD = Math.toRadians(theta); + /* Pre-compute rotation matrix entries */ + double cosTheta = Math.cos(thetaD); + double sinTheta = Math.sin(thetaD); + /* Transform (x0, y0) and (x1, y1) into unit space */ + /* using (inverse) rotation, followed by (inverse) scale */ + double x0p = (x0 * cosTheta + y0 * sinTheta) / a; + double y0p = (-x0 * sinTheta + y0 * cosTheta) / b; + double x1p = (x1 * cosTheta + y1 * sinTheta) / a; + double y1p = (-x1 * sinTheta + y1 * cosTheta) / b; + + /* Compute differences and averages */ + double dx = x0p - x1p; + double dy = y0p - y1p; + double xm = (x0p + x1p) / 2; + double ym = (y0p + y1p) / 2; + /* Solve for intersecting unit circles */ + double dsq = dx * dx + dy * dy; + if (dsq == 0.0) { + Log.w(LOGTAG, " Points are coincident"); + return; /* Points are coincident */ + } + double disc = 1.0 / dsq - 1.0 / 4.0; + if (disc < 0.0) { + Log.w(LOGTAG, "Points are too far apart " + dsq); + float adjust = (float) (Math.sqrt(dsq) / 1.99999); + drawArc(p, x0, y0, x1, y1, a * adjust, + b * adjust, theta, isMoreThanHalf, isPositiveArc); + return; /* Points are too far apart */ + } + double s = Math.sqrt(disc); + double sdx = s * dx; + double sdy = s * dy; + double cx; + double cy; + if (isMoreThanHalf == isPositiveArc) { + cx = xm - sdy; + cy = ym + sdx; + } else { + cx = xm + sdy; + cy = ym - sdx; + } + + double eta0 = Math.atan2((y0p - cy), (x0p - cx)); + + double eta1 = Math.atan2((y1p - cy), (x1p - cx)); + + double sweep = (eta1 - eta0); + if (isPositiveArc != (sweep >= 0)) { + if (sweep > 0) { + sweep -= 2 * Math.PI; + } else { + sweep += 2 * Math.PI; + } + } + + cx *= a; + cy *= b; + double tcx = cx; + cx = cx * cosTheta - cy * sinTheta; + cy = tcx * sinTheta + cy * cosTheta; + + arcToBezier(p, cx, cy, a, b, x0, y0, thetaD, eta0, sweep); + } + + /** + * Converts an arc to cubic Bezier segments and records them in p. + * + * @param p The target for the cubic Bezier segments + * @param cx The x coordinate center of the ellipse + * @param cy The y coordinate center of the ellipse + * @param a The radius of the ellipse in the horizontal direction + * @param b The radius of the ellipse in the vertical direction + * @param e1x E(eta1) x coordinate of the starting point of the arc + * @param e1y E(eta2) y coordinate of the starting point of the arc + * @param theta The angle that the ellipse bounding rectangle makes with horizontal plane + * @param start The start angle of the arc on the ellipse + * @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse + */ + private static void arcToBezier(Path p, + double cx, + double cy, + double a, + double b, + double e1x, + double e1y, + double theta, + double start, + double sweep) { + // Taken from equations at: http://spaceroots.org/documents/ellipse/node8.html + // and http://www.spaceroots.org/documents/ellipse/node22.html + + // Maximum of 45 degrees per cubic Bezier segment + int numSegments = Math.abs((int) Math.ceil(sweep * 4 / Math.PI)); + + double eta1 = start; + double cosTheta = Math.cos(theta); + double sinTheta = Math.sin(theta); + double cosEta1 = Math.cos(eta1); + double sinEta1 = Math.sin(eta1); + double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1); + double ep1y = (-a * sinTheta * sinEta1) + (b * cosTheta * cosEta1); + + double anglePerSegment = sweep / numSegments; + for (int i = 0; i < numSegments; i++) { + double eta2 = eta1 + anglePerSegment; + double sinEta2 = Math.sin(eta2); + double cosEta2 = Math.cos(eta2); + double e2x = cx + (a * cosTheta * cosEta2) - (b * sinTheta * sinEta2); + double e2y = cy + (a * sinTheta * cosEta2) + (b * cosTheta * sinEta2); + double ep2x = -a * cosTheta * sinEta2 - b * sinTheta * cosEta2; + double ep2y = -a * sinTheta * sinEta2 + b * cosTheta * cosEta2; + double tanDiff2 = Math.tan((eta2 - eta1) / 2); + double alpha = + Math.sin(eta2 - eta1) * (Math.sqrt(4 + (3 * tanDiff2 * tanDiff2)) - 1) / 3; + double q1x = e1x + alpha * ep1x; + double q1y = e1y + alpha * ep1y; + double q2x = e2x - alpha * ep2x; + double q2y = e2y - alpha * ep2y; + + p.cubicTo((float) q1x, + (float) q1y, + (float) q2x, + (float) q2y, + (float) e2x, + (float) e2y); + eta1 = eta2; + e1x = e2x; + e1y = e2y; + ep1x = ep2x; + ep1y = ep2y; + } + } + + } +} diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 68e2146c821b..9fafc482e887 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -853,31 +853,7 @@ class GLES20Canvas extends HardwareCanvas { private static native void nDrawPoints(long renderer, float[] points, int offset, int count, long paint); - @SuppressWarnings("deprecation") - @Override - public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) { - if (index < 0 || index + count > text.length || count * 2 > pos.length) { - throw new IndexOutOfBoundsException(); - } - - nDrawPosText(mRenderer, text, index, count, pos, paint.mNativePaint); - } - - private static native void nDrawPosText(long renderer, char[] text, int index, int count, - float[] pos, long paint); - - @SuppressWarnings("deprecation") - @Override - public void drawPosText(String text, float[] pos, Paint paint) { - if (text.length() * 2 > pos.length) { - throw new ArrayIndexOutOfBoundsException(); - } - - nDrawPosText(mRenderer, text, 0, text.length(), pos, paint.mNativePaint); - } - - private static native void nDrawPosText(long renderer, String text, int start, int end, - float[] pos, long paint); + // Note: drawPosText just uses implementation in Canvas @Override public void drawRect(float left, float top, float right, float bottom, Paint paint) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 89c2f37e5b34..d25ef1655e7e 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -14240,6 +14240,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @return True if the view is attached to a window and the window is * hardware accelerated; false in any other case. */ + @ViewDebug.ExportedProperty(category = "drawing") public boolean isHardwareAccelerated() { return mAttachInfo != null && mAttachInfo.mHardwareAccelerated; } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index a02e76bbbfa5..1e72625afb5b 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -4386,7 +4386,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager // Make sure we do not set both flags at the same time int opaqueFlag = isOpaque ? PFLAG_DIRTY_OPAQUE : PFLAG_DIRTY; - if (child.mLayerType == LAYER_TYPE_SOFTWARE) { + if (child.mLayerType != LAYER_TYPE_NONE) { mPrivateFlags |= PFLAG_INVALIDATED; mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; } @@ -4497,7 +4497,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager location[CHILD_LEFT_INDEX] = left; location[CHILD_TOP_INDEX] = top; - if (mLayerType == LAYER_TYPE_SOFTWARE) { + if (mLayerType != LAYER_TYPE_NONE) { mPrivateFlags |= PFLAG_INVALIDATED; } @@ -4515,7 +4515,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager dirty.union(0, 0, mRight - mLeft, mBottom - mTop); } - if (mLayerType == LAYER_TYPE_SOFTWARE) { + if (mLayerType != LAYER_TYPE_NONE) { mPrivateFlags |= PFLAG_INVALIDATED; } diff --git a/core/java/android/view/animation/PathInterpolator.java b/core/java/android/view/animation/PathInterpolator.java index da12ffbc1bd6..945ecf00656a 100644 --- a/core/java/android/view/animation/PathInterpolator.java +++ b/core/java/android/view/animation/PathInterpolator.java @@ -21,6 +21,7 @@ import android.content.res.Resources.Theme; import android.content.res.TypedArray; import android.graphics.Path; import android.util.AttributeSet; +import android.util.PathParser; import android.view.InflateException; import com.android.internal.R; @@ -102,28 +103,40 @@ public class PathInterpolator implements Interpolator { } private void parseInterpolatorFromTypeArray(TypedArray a) { - if (!a.hasValue(R.styleable.PathInterpolator_controlX1)) { - throw new InflateException("pathInterpolator requires the controlX1 attribute"); - } else if (!a.hasValue(R.styleable.PathInterpolator_controlY1)) { - throw new InflateException("pathInterpolator requires the controlY1 attribute"); - } - float x1 = a.getFloat(R.styleable.PathInterpolator_controlX1, 0); - float y1 = a.getFloat(R.styleable.PathInterpolator_controlY1, 0); + // If there is pathData defined in the xml file, then the controls points + // will be all coming from pathData. + if (a.hasValue(R.styleable.PathInterpolator_pathData)) { + String pathData = a.getString(R.styleable.PathInterpolator_pathData); + Path path = PathParser.createPathFromPathData(pathData); + if (path == null) { + throw new InflateException("The path is null, which is created" + + " from " + pathData); + } + initPath(path); + } else { + if (!a.hasValue(R.styleable.PathInterpolator_controlX1)) { + throw new InflateException("pathInterpolator requires the controlX1 attribute"); + } else if (!a.hasValue(R.styleable.PathInterpolator_controlY1)) { + throw new InflateException("pathInterpolator requires the controlY1 attribute"); + } + float x1 = a.getFloat(R.styleable.PathInterpolator_controlX1, 0); + float y1 = a.getFloat(R.styleable.PathInterpolator_controlY1, 0); - boolean hasX2 = a.hasValue(R.styleable.PathInterpolator_controlX2); - boolean hasY2 = a.hasValue(R.styleable.PathInterpolator_controlY2); + boolean hasX2 = a.hasValue(R.styleable.PathInterpolator_controlX2); + boolean hasY2 = a.hasValue(R.styleable.PathInterpolator_controlY2); - if (hasX2 != hasY2) { - throw new InflateException( - "pathInterpolator requires both controlX2 and controlY2 for cubic Beziers."); - } + if (hasX2 != hasY2) { + throw new InflateException( + "pathInterpolator requires both controlX2 and controlY2 for cubic Beziers."); + } - if (!hasX2) { - initQuad(x1, y1); - } else { - float x2 = a.getFloat(R.styleable.PathInterpolator_controlX2, 0); - float y2 = a.getFloat(R.styleable.PathInterpolator_controlY2, 0); - initCubic(x1, y1, x2, y2); + if (!hasX2) { + initQuad(x1, y1); + } else { + float x2 = a.getFloat(R.styleable.PathInterpolator_controlX2, 0); + float y2 = a.getFloat(R.styleable.PathInterpolator_controlY2, 0); + initCubic(x1, y1, x2, y2); + } } } @@ -216,5 +229,4 @@ public class PathInterpolator implements Interpolator { float endY = mY[endIndex]; return startY + (fraction * (endY - startY)); } - } diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java index 04b18c1e873d..93810b3f6bf3 100644 --- a/core/java/android/widget/GridView.java +++ b/core/java/android/widget/GridView.java @@ -1326,12 +1326,28 @@ public class GridView extends AbsListView { if (sel != null) { positionSelector(INVALID_POSITION, sel); mSelectedTop = sel.getTop(); - } else if (mTouchMode > TOUCH_MODE_DOWN && mTouchMode < TOUCH_MODE_SCROLL) { - View child = getChildAt(mMotionPosition - mFirstPosition); - if (child != null) positionSelector(mMotionPosition, child); } else { - mSelectedTop = 0; - mSelectorRect.setEmpty(); + final boolean inTouchMode = mTouchMode > TOUCH_MODE_DOWN + && mTouchMode < TOUCH_MODE_SCROLL; + if (inTouchMode) { + // If the user's finger is down, select the motion position. + final View child = getChildAt(mMotionPosition - mFirstPosition); + if (child != null) { + positionSelector(mMotionPosition, child); + } + } else if (mSelectedPosition != INVALID_POSITION) { + // If we had previously positioned the selector somewhere, + // put it back there. It might not match up with the data, + // but it's transitioning out so it's not a big deal. + final View child = getChildAt(mSelectorPosition - mFirstPosition); + if (child != null) { + positionSelector(mSelectorPosition, child); + } + } else { + // Otherwise, clear selection. + mSelectedTop = 0; + mSelectorRect.setEmpty(); + } } // Attempt to restore accessibility focus, if necessary. diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index eeb80157fe3d..1baeca880e9a 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -1718,14 +1718,24 @@ public class ListView extends AbsListView { } mSelectedTop = sel.getTop(); } else { - // If the user's finger is down, select the motion position. - // Otherwise, clear selection. - if (mTouchMode == TOUCH_MODE_TAP || mTouchMode == TOUCH_MODE_DONE_WAITING) { + final boolean inTouchMode = mTouchMode == TOUCH_MODE_TAP + || mTouchMode == TOUCH_MODE_DONE_WAITING; + if (inTouchMode) { + // If the user's finger is down, select the motion position. final View child = getChildAt(mMotionPosition - mFirstPosition); - if (child != null) { + if (child != null) { positionSelector(mMotionPosition, child); } + } else if (mSelectorPosition != INVALID_POSITION) { + // If we had previously positioned the selector somewhere, + // put it back there. It might not match up with the data, + // but it's transitioning out so it's not a big deal. + final View child = getChildAt(mSelectorPosition - mFirstPosition); + if (child != null) { + positionSelector(mSelectorPosition, child); + } } else { + // Otherwise, clear selection. mSelectedTop = 0; mSelectorRect.setEmpty(); } diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index f7d20b532754..82637a19ff10 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -1781,7 +1781,9 @@ public class RemoteViews implements Parcelable, Filter { Parcel p = Parcel.obtain(); writeToParcel(p, 0); p.setDataPosition(0); - return new RemoteViews(p); + RemoteViews rv = new RemoteViews(p); + p.recycle(); + return rv; } public String getPackage() { diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java index cca29cf39db8..9a8380d70c28 100644 --- a/core/java/android/widget/Switch.java +++ b/core/java/android/widget/Switch.java @@ -90,6 +90,7 @@ public class Switch extends CompoundButton { private boolean mSplitTrack; private CharSequence mTextOn; private CharSequence mTextOff; + private boolean mShowText; private int mTouchMode; private int mTouchSlop; @@ -188,6 +189,7 @@ public class Switch extends CompoundButton { mTrackDrawable = a.getDrawable(com.android.internal.R.styleable.Switch_track); mTextOn = a.getText(com.android.internal.R.styleable.Switch_textOn); mTextOff = a.getText(com.android.internal.R.styleable.Switch_textOff); + mShowText = a.getBoolean(com.android.internal.R.styleable.Switch_showText, true); mThumbTextPadding = a.getDimensionPixelSize( com.android.internal.R.styleable.Switch_thumbTextPadding, 0); mSwitchMinWidth = a.getDimensionPixelSize( @@ -533,20 +535,43 @@ public class Switch extends CompoundButton { requestLayout(); } + /** + * Sets whether the on/off text should be displayed. + * + * @param showText {@code true} to display on/off text + * @hide + */ + public void setShowText(boolean showText) { + if (mShowText != showText) { + mShowText = showText; + requestLayout(); + } + } + + /** + * @return whether the on/off text should be displayed + * @hide + */ + public boolean getShowText() { + return mShowText; + } + @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - if (mOnLayout == null) { - mOnLayout = makeLayout(mTextOn); - } + if (mShowText) { + if (mOnLayout == null) { + mOnLayout = makeLayout(mTextOn); + } - if (mOffLayout == null) { - mOffLayout = makeLayout(mTextOff); + if (mOffLayout == null) { + mOffLayout = makeLayout(mTextOff); + } } mTrackDrawable.getPadding(mTempRect); - final int maxTextWidth = Math.max(mOnLayout.getWidth(), mOffLayout.getWidth()) - + mThumbTextPadding * 2; + final int maxTextWidth = mShowText ? Math.max(mOnLayout.getWidth(), mOffLayout.getWidth()) + + mThumbTextPadding * 2 : 0; mThumbWidth = Math.max(maxTextWidth, mThumbDrawable.getIntrinsicWidth()); final int switchWidth = Math.max(mSwitchMinWidth, @@ -568,9 +593,10 @@ public class Switch extends CompoundButton { @Override public void onPopulateAccessibilityEvent(AccessibilityEvent event) { super.onPopulateAccessibilityEvent(event); - Layout layout = isChecked() ? mOnLayout : mOffLayout; - if (layout != null && !TextUtils.isEmpty(layout.getText())) { - event.getText().add(layout.getText()); + + final CharSequence text = isChecked() ? mTextOn : mTextOff; + if (text != null) { + event.getText().add(text); } } diff --git a/core/java/com/android/internal/app/ProcessStats.java b/core/java/com/android/internal/app/ProcessStats.java index 7e1185031703..4995ea1d1e5b 100644 --- a/core/java/com/android/internal/app/ProcessStats.java +++ b/core/java/com/android/internal/app/ProcessStats.java @@ -28,7 +28,6 @@ import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; -import android.webkit.WebViewFactory; import com.android.internal.util.GrowingArrayUtils; @@ -55,6 +54,11 @@ public final class ProcessStats implements Parcelable { // that is done. public static long COMMIT_PERIOD = 3*60*60*1000; // Commit current stats every 3 hours + // Minimum uptime period before committing. If the COMMIT_PERIOD has elapsed but + // the total uptime has not exceeded this amount, then the commit will be held until + // it is reached. + public static long COMMIT_UPTIME_PERIOD = 60*60*1000; // Must have at least 1 hour elapsed + public static final int STATE_NOTHING = -1; public static final int STATE_PERSISTENT = 0; public static final int STATE_TOP = 1; @@ -81,6 +85,24 @@ public final class ProcessStats implements Parcelable { public static final int PSS_USS_MAXIMUM = 6; public static final int PSS_COUNT = PSS_USS_MAXIMUM+1; + public static final int SYS_MEM_USAGE_SAMPLE_COUNT = 0; + public static final int SYS_MEM_USAGE_CACHED_MINIMUM = 1; + public static final int SYS_MEM_USAGE_CACHED_AVERAGE = 2; + public static final int SYS_MEM_USAGE_CACHED_MAXIMUM = 3; + public static final int SYS_MEM_USAGE_FREE_MINIMUM = 4; + public static final int SYS_MEM_USAGE_FREE_AVERAGE = 5; + public static final int SYS_MEM_USAGE_FREE_MAXIMUM = 6; + public static final int SYS_MEM_USAGE_ZRAM_MINIMUM = 7; + public static final int SYS_MEM_USAGE_ZRAM_AVERAGE = 8; + public static final int SYS_MEM_USAGE_ZRAM_MAXIMUM = 9; + public static final int SYS_MEM_USAGE_KERNEL_MINIMUM = 10; + public static final int SYS_MEM_USAGE_KERNEL_AVERAGE = 11; + public static final int SYS_MEM_USAGE_KERNEL_MAXIMUM = 12; + public static final int SYS_MEM_USAGE_NATIVE_MINIMUM = 13; + public static final int SYS_MEM_USAGE_NATIVE_AVERAGE = 14; + public static final int SYS_MEM_USAGE_NATIVE_MAXIMUM = 15; + public static final int SYS_MEM_USAGE_COUNT = SYS_MEM_USAGE_NATIVE_MAXIMUM+1; + public static final int ADJ_NOTHING = -1; public static final int ADJ_MEM_FACTOR_NORMAL = 0; public static final int ADJ_MEM_FACTOR_MODERATE = 1; @@ -174,7 +196,7 @@ public final class ProcessStats implements Parcelable { static final String CSV_SEP = "\t"; // Current version of the parcel format. - private static final int PARCEL_VERSION = 14; + private static final int PARCEL_VERSION = 18; // In-memory Parcel magic number, used to detect attempts to unmarshall bad data private static final int MAGIC = 0x50535453; @@ -200,11 +222,16 @@ public final class ProcessStats implements Parcelable { public int mMemFactor = STATE_NOTHING; public long mStartTime; + public int[] mSysMemUsageTable = null; + public int mSysMemUsageTableSize = 0; + public final long[] mSysMemUsageArgs = new long[SYS_MEM_USAGE_COUNT]; + public long mTimePeriodStartClock; public long mTimePeriodStartRealtime; public long mTimePeriodEndRealtime; + public long mTimePeriodStartUptime; + public long mTimePeriodEndUptime; String mRuntime; - String mWebView; boolean mRunning; static final int LONGS_SIZE = 4096; @@ -304,11 +331,77 @@ public final class ProcessStats implements Parcelable { mMemFactorDurations[i] += other.mMemFactorDurations[i]; } + for (int i=0; i<other.mSysMemUsageTableSize; i++) { + int ent = other.mSysMemUsageTable[i]; + int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; + long[] longs = other.mLongs.get((ent>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK); + addSysMemUsage(state, longs, ((ent >> OFFSET_INDEX_SHIFT) & OFFSET_INDEX_MASK)); + } + if (other.mTimePeriodStartClock < mTimePeriodStartClock) { mTimePeriodStartClock = other.mTimePeriodStartClock; mTimePeriodStartClockStr = other.mTimePeriodStartClockStr; } mTimePeriodEndRealtime += other.mTimePeriodEndRealtime - other.mTimePeriodStartRealtime; + mTimePeriodEndUptime += other.mTimePeriodEndUptime - other.mTimePeriodStartUptime; + } + + public void addSysMemUsage(long cachedMem, long freeMem, long zramMem, long kernelMem, + long nativeMem) { + if (mMemFactor != STATE_NOTHING) { + int state = mMemFactor * STATE_COUNT; + mSysMemUsageArgs[SYS_MEM_USAGE_SAMPLE_COUNT] = 1; + for (int i=0; i<3; i++) { + mSysMemUsageArgs[SYS_MEM_USAGE_CACHED_MINIMUM + i] = cachedMem; + mSysMemUsageArgs[SYS_MEM_USAGE_FREE_MINIMUM + i] = freeMem; + mSysMemUsageArgs[SYS_MEM_USAGE_ZRAM_MINIMUM + i] = zramMem; + mSysMemUsageArgs[SYS_MEM_USAGE_KERNEL_MINIMUM + i] = kernelMem; + mSysMemUsageArgs[SYS_MEM_USAGE_NATIVE_MINIMUM + i] = nativeMem; + } + addSysMemUsage(state, mSysMemUsageArgs, 0); + } + } + + void addSysMemUsage(int state, long[] data, int dataOff) { + int idx = binarySearch(mSysMemUsageTable, mSysMemUsageTableSize, state); + int off; + if (idx >= 0) { + off = mSysMemUsageTable[idx]; + } else { + mAddLongTable = mSysMemUsageTable; + mAddLongTableSize = mSysMemUsageTableSize; + off = addLongData(~idx, state, SYS_MEM_USAGE_COUNT); + mSysMemUsageTable = mAddLongTable; + mSysMemUsageTableSize = mAddLongTableSize; + } + long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK); + idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK; + addSysMemUsage(longs, idx, data, dataOff); + } + + static void addSysMemUsage(long[] dstData, int dstOff, long[] addData, int addOff) { + final long dstCount = dstData[dstOff+SYS_MEM_USAGE_SAMPLE_COUNT]; + final long addCount = addData[addOff+SYS_MEM_USAGE_SAMPLE_COUNT]; + if (dstCount == 0) { + dstData[dstOff+SYS_MEM_USAGE_SAMPLE_COUNT] = addCount; + for (int i=SYS_MEM_USAGE_CACHED_MINIMUM; i<SYS_MEM_USAGE_COUNT; i++) { + dstData[dstOff+i] = addData[addOff+i]; + } + } else if (addCount > 0) { + dstData[dstOff+SYS_MEM_USAGE_SAMPLE_COUNT] = dstCount + addCount; + for (int i=SYS_MEM_USAGE_CACHED_MINIMUM; i<SYS_MEM_USAGE_COUNT; i+=3) { + if (dstData[dstOff+i] > addData[addOff+i]) { + dstData[dstOff+i] = addData[addOff+i]; + } + dstData[dstOff+i+1] = (long)( + ((dstData[dstOff+i+1]*(double)dstCount) + + (addData[addOff+i+1]*(double)addCount)) + / (dstCount+addCount) ); + if (dstData[dstOff+i+2] < addData[addOff+i+2]) { + dstData[dstOff+i+2] = addData[addOff+i+2]; + } + } + } } public static final Parcelable.Creator<ProcessStats> CREATOR @@ -564,6 +657,164 @@ public final class ProcessStats implements Parcelable { return totalTime; } + static class PssAggr { + long pss = 0; + long samples = 0; + + void add(long newPss, long newSamples) { + pss = (long)( (pss*(double)samples) + (newPss*(double)newSamples) ) + / (samples+newSamples); + samples += newSamples; + } + } + + public void computeTotalMemoryUse(TotalMemoryUseCollection data, long now) { + data.totalTime = 0; + for (int i=0; i<STATE_COUNT; i++) { + data.processStateWeight[i] = 0; + data.processStatePss[i] = 0; + data.processStateTime[i] = 0; + data.processStateSamples[i] = 0; + } + for (int i=0; i<SYS_MEM_USAGE_COUNT; i++) { + data.sysMemUsage[i] = 0; + } + data.sysMemCachedWeight = 0; + data.sysMemFreeWeight = 0; + data.sysMemZRamWeight = 0; + data.sysMemKernelWeight = 0; + data.sysMemNativeWeight = 0; + data.sysMemSamples = 0; + long[] totalMemUsage = new long[SYS_MEM_USAGE_COUNT]; + for (int i=0; i<mSysMemUsageTableSize; i++) { + int ent = mSysMemUsageTable[i]; + long[] longs = mLongs.get((ent>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK); + int idx = (ent >> OFFSET_INDEX_SHIFT) & OFFSET_INDEX_MASK; + addSysMemUsage(totalMemUsage, 0, longs, idx); + } + for (int is=0; is<data.screenStates.length; is++) { + for (int im=0; im<data.memStates.length; im++) { + int memBucket = data.screenStates[is] + data.memStates[im]; + int stateBucket = memBucket * STATE_COUNT; + long memTime = mMemFactorDurations[memBucket]; + if (mMemFactor == memBucket) { + memTime += now - mStartTime; + } + data.totalTime += memTime; + int sysIdx = binarySearch(mSysMemUsageTable, mSysMemUsageTableSize, stateBucket); + long[] longs = totalMemUsage; + int idx = 0; + if (sysIdx >= 0) { + int ent = mSysMemUsageTable[sysIdx]; + long[] tmpLongs = mLongs.get((ent>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK); + int tmpIdx = (ent >> OFFSET_INDEX_SHIFT) & OFFSET_INDEX_MASK; + if (tmpLongs[tmpIdx+SYS_MEM_USAGE_SAMPLE_COUNT] >= 3) { + addSysMemUsage(data.sysMemUsage, 0, longs, idx); + longs = tmpLongs; + idx = tmpIdx; + } + } + data.sysMemCachedWeight += longs[idx+SYS_MEM_USAGE_CACHED_AVERAGE] + * (double)memTime; + data.sysMemFreeWeight += longs[idx+SYS_MEM_USAGE_FREE_AVERAGE] + * (double)memTime; + data.sysMemZRamWeight += longs[idx+SYS_MEM_USAGE_ZRAM_AVERAGE] + * (double)memTime; + data.sysMemKernelWeight += longs[idx+SYS_MEM_USAGE_KERNEL_AVERAGE] + * (double)memTime; + data.sysMemNativeWeight += longs[idx+SYS_MEM_USAGE_NATIVE_AVERAGE] + * (double)memTime; + data.sysMemSamples += longs[idx+SYS_MEM_USAGE_SAMPLE_COUNT]; + } + } + ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); + for (int iproc=0; iproc<procMap.size(); iproc++) { + SparseArray<ProcessState> uids = procMap.valueAt(iproc); + for (int iu=0; iu<uids.size(); iu++) { + final ProcessState proc = uids.valueAt(iu); + final PssAggr fgPss = new PssAggr(); + final PssAggr bgPss = new PssAggr(); + final PssAggr cachedPss = new PssAggr(); + boolean havePss = false; + for (int i=0; i<proc.mDurationsTableSize; i++) { + int off = proc.mDurationsTable[i]; + int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; + int procState = type % STATE_COUNT; + long samples = proc.getPssSampleCount(type); + if (samples > 0) { + long avg = proc.getPssAverage(type); + havePss = true; + if (procState <= STATE_IMPORTANT_FOREGROUND) { + fgPss.add(avg, samples); + } else if (procState <= STATE_RECEIVER) { + bgPss.add(avg, samples); + } else { + cachedPss.add(avg, samples); + } + } + } + if (!havePss) { + continue; + } + boolean fgHasBg = false; + boolean fgHasCached = false; + boolean bgHasCached = false; + if (fgPss.samples < 3 && bgPss.samples > 0) { + fgHasBg = true; + fgPss.add(bgPss.pss, bgPss.samples); + } + if (fgPss.samples < 3 && cachedPss.samples > 0) { + fgHasCached = true; + fgPss.add(cachedPss.pss, cachedPss.samples); + } + if (bgPss.samples < 3 && cachedPss.samples > 0) { + bgHasCached = true; + bgPss.add(cachedPss.pss, cachedPss.samples); + } + if (bgPss.samples < 3 && !fgHasBg && fgPss.samples > 0) { + bgPss.add(fgPss.pss, fgPss.samples); + } + if (cachedPss.samples < 3 && !bgHasCached && bgPss.samples > 0) { + cachedPss.add(bgPss.pss, bgPss.samples); + } + if (cachedPss.samples < 3 && !fgHasCached && fgPss.samples > 0) { + cachedPss.add(fgPss.pss, fgPss.samples); + } + for (int i=0; i<proc.mDurationsTableSize; i++) { + final int off = proc.mDurationsTable[i]; + final int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; + long time = getLong(off, 0); + if (proc.mCurState == type) { + time += now - proc.mStartTime; + } + final int procState = type % STATE_COUNT; + data.processStateTime[procState] += time; + long samples = proc.getPssSampleCount(type); + long avg; + if (samples > 0) { + avg = proc.getPssAverage(type); + } else if (procState <= STATE_IMPORTANT_FOREGROUND) { + samples = fgPss.samples; + avg = fgPss.pss; + } else if (procState <= STATE_RECEIVER) { + samples = bgPss.samples; + avg = bgPss.pss; + } else { + samples = cachedPss.samples; + avg = cachedPss.pss; + } + double newAvg = ( (data.processStatePss[procState] + * (double)data.processStateSamples[procState]) + + (avg*(double)samples) + ) / (data.processStateSamples[procState]+samples); + data.processStatePss[procState] = (long)newAvg; + data.processStateSamples[procState] += samples; + data.processStateWeight[procState] += avg * (double)time; + } + } + } + } + static void dumpProcessState(PrintWriter pw, String prefix, ProcessState proc, int[] screenStates, int[] memStates, int[] procStates, long now) { long totalTime = 0; @@ -679,6 +930,62 @@ public final class ProcessStats implements Parcelable { } } + long getSysMemUsageValue(int state, int index) { + int idx = binarySearch(mSysMemUsageTable, mSysMemUsageTableSize, state); + return idx >= 0 ? getLong(mSysMemUsageTable[idx], index) : 0; + } + + void dumpSysMemUsageCategory(PrintWriter pw, String prefix, String label, + int bucket, int index) { + pw.print(prefix); pw.print(label); + pw.print(": "); + printSizeValue(pw, getSysMemUsageValue(bucket, index) * 1024); + pw.print(" min, "); + printSizeValue(pw, getSysMemUsageValue(bucket, index + 1) * 1024); + pw.print(" avg, "); + printSizeValue(pw, getSysMemUsageValue(bucket, index+2) * 1024); + pw.println(" max"); + } + + void dumpSysMemUsage(PrintWriter pw, String prefix, int[] screenStates, + int[] memStates) { + int printedScreen = -1; + for (int is=0; is<screenStates.length; is++) { + int printedMem = -1; + for (int im=0; im<memStates.length; im++) { + final int iscreen = screenStates[is]; + final int imem = memStates[im]; + final int bucket = ((iscreen + imem) * STATE_COUNT); + long count = getSysMemUsageValue(bucket, SYS_MEM_USAGE_SAMPLE_COUNT); + if (count > 0) { + pw.print(prefix); + if (screenStates.length > 1) { + printScreenLabel(pw, printedScreen != iscreen + ? iscreen : STATE_NOTHING); + printedScreen = iscreen; + } + if (memStates.length > 1) { + printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, '\0'); + printedMem = imem; + } + pw.print(": "); + pw.print(count); + pw.println(" samples:"); + dumpSysMemUsageCategory(pw, prefix, " Cached", bucket, + SYS_MEM_USAGE_CACHED_MINIMUM); + dumpSysMemUsageCategory(pw, prefix, " Free", bucket, + SYS_MEM_USAGE_FREE_MINIMUM); + dumpSysMemUsageCategory(pw, prefix, " ZRam", bucket, + SYS_MEM_USAGE_ZRAM_MINIMUM); + dumpSysMemUsageCategory(pw, prefix, " Kernel", bucket, + SYS_MEM_USAGE_KERNEL_MINIMUM); + dumpSysMemUsageCategory(pw, prefix, " Native", bucket, + SYS_MEM_USAGE_NATIVE_MINIMUM); + } + } + } + } + static void dumpStateHeadersCsv(PrintWriter pw, String sep, int[] screenStates, int[] memStates, int[] procStates) { final int NS = screenStates != null ? screenStates.length : 1; @@ -1088,10 +1395,13 @@ public final class ProcessStats implements Parcelable { mTimePeriodStartClock = System.currentTimeMillis(); buildTimePeriodStartClockStr(); mTimePeriodStartRealtime = mTimePeriodEndRealtime = SystemClock.elapsedRealtime(); + mTimePeriodStartUptime = mTimePeriodEndUptime = SystemClock.uptimeMillis(); mLongs.clear(); mLongs.add(new long[LONGS_SIZE]); mNextLong = 0; Arrays.fill(mMemFactorDurations, 0); + mSysMemUsageTable = null; + mSysMemUsageTableSize = 0; mStartTime = 0; mReadError = null; mFlags = 0; @@ -1220,12 +1530,17 @@ public final class ProcessStats implements Parcelable { @Override public void writeToParcel(Parcel out, int flags) { - long now = SystemClock.uptimeMillis(); + writeToParcel(out, SystemClock.uptimeMillis(), flags); + } + + /** @hide */ + public void writeToParcel(Parcel out, long now, int flags) { out.writeInt(MAGIC); out.writeInt(PARCEL_VERSION); out.writeInt(STATE_COUNT); out.writeInt(ADJ_COUNT); out.writeInt(PSS_COUNT); + out.writeInt(SYS_MEM_USAGE_COUNT); out.writeInt(LONGS_SIZE); mCommonStringToIndex = new ArrayMap<String, Integer>(mProcesses.mMap.size()); @@ -1268,8 +1583,9 @@ public final class ProcessStats implements Parcelable { out.writeLong(mTimePeriodStartClock); out.writeLong(mTimePeriodStartRealtime); out.writeLong(mTimePeriodEndRealtime); + out.writeLong(mTimePeriodStartUptime); + out.writeLong(mTimePeriodEndUptime); out.writeString(mRuntime); - out.writeString(mWebView); out.writeInt(mFlags); out.writeInt(mLongs.size()); @@ -1287,6 +1603,13 @@ public final class ProcessStats implements Parcelable { } writeCompactedLongArray(out, mMemFactorDurations, mMemFactorDurations.length); + out.writeInt(mSysMemUsageTableSize); + for (int i=0; i<mSysMemUsageTableSize; i++) { + if (DEBUG_PARCEL) Slog.i(TAG, "Writing sys mem usage #" + i + ": " + + printLongOffset(mSysMemUsageTable[i])); + out.writeInt(mSysMemUsageTable[i]); + } + out.writeInt(NPROC); for (int ip=0; ip<NPROC; ip++) { writeCommonString(out, procMap.keyAt(ip)); @@ -1417,6 +1740,9 @@ public final class ProcessStats implements Parcelable { if (!readCheckedInt(in, PSS_COUNT, "pss count")) { return; } + if (!readCheckedInt(in, SYS_MEM_USAGE_COUNT, "sys mem usage count")) { + return; + } if (!readCheckedInt(in, LONGS_SIZE, "longs size")) { return; } @@ -1427,8 +1753,9 @@ public final class ProcessStats implements Parcelable { buildTimePeriodStartClockStr(); mTimePeriodStartRealtime = in.readLong(); mTimePeriodEndRealtime = in.readLong(); + mTimePeriodStartUptime = in.readLong(); + mTimePeriodEndUptime = in.readLong(); mRuntime = in.readString(); - mWebView = in.readString(); mFlags = in.readInt(); final int NLONGS = in.readInt(); @@ -1447,6 +1774,12 @@ public final class ProcessStats implements Parcelable { readCompactedLongArray(in, version, mMemFactorDurations, mMemFactorDurations.length); + mSysMemUsageTable = readTableFromParcel(in, TAG, "sys mem usage"); + if (mSysMemUsageTable == BAD_TABLE) { + return; + } + mSysMemUsageTableSize = mSysMemUsageTable != null ? mSysMemUsageTable.length : 0; + int NPROC = in.readInt(); if (NPROC < 0) { mReadError = "bad process count: " + NPROC; @@ -1826,6 +2159,10 @@ public final class ProcessStats implements Parcelable { boolean dumpAll, boolean activeOnly) { long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor, mStartTime, now); + if (mSysMemUsageTable != null) { + pw.println("System memory usage:"); + dumpSysMemUsage(pw, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ); + } ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap(); boolean printedHeader = false; boolean sepNeeded = false; @@ -2089,10 +2426,57 @@ public final class ProcessStats implements Parcelable { dumpTotalsLocked(pw, now); } + long printMemoryCategory(PrintWriter pw, String prefix, String label, double memWeight, + long totalTime, long curTotalMem, int samples) { + if (memWeight != 0) { + long mem = (long)(memWeight * 1024 / totalTime); + pw.print(prefix); + pw.print(label); + pw.print(": "); + printSizeValue(pw, mem); + pw.print(" ("); + pw.print(samples); + pw.print(" samples)"); + pw.println(); + return curTotalMem + mem; + } + return curTotalMem; + } + void dumpTotalsLocked(PrintWriter pw, long now) { pw.println("Run time Stats:"); dumpSingleTime(pw, " ", mMemFactorDurations, mMemFactor, mStartTime, now); pw.println(); + pw.println("Memory usage:"); + TotalMemoryUseCollection totalMem = new TotalMemoryUseCollection(ALL_SCREEN_ADJ, + ALL_MEM_ADJ); + computeTotalMemoryUse(totalMem, now); + long totalPss = 0; + totalPss = printMemoryCategory(pw, " ", "Kernel ", totalMem.sysMemKernelWeight, + totalMem.totalTime, totalPss, totalMem.sysMemSamples); + totalPss = printMemoryCategory(pw, " ", "Native ", totalMem.sysMemNativeWeight, + totalMem.totalTime, totalPss, totalMem.sysMemSamples); + for (int i=0; i<STATE_COUNT; i++) { + // Skip restarting service state -- that is not actually a running process. + if (i != STATE_SERVICE_RESTARTING) { + totalPss = printMemoryCategory(pw, " ", STATE_NAMES[i], + totalMem.processStateWeight[i], totalMem.totalTime, totalPss, + totalMem.processStateSamples[i]); + } + } + totalPss = printMemoryCategory(pw, " ", "Cached ", totalMem.sysMemCachedWeight, + totalMem.totalTime, totalPss, totalMem.sysMemSamples); + totalPss = printMemoryCategory(pw, " ", "Free ", totalMem.sysMemFreeWeight, + totalMem.totalTime, totalPss, totalMem.sysMemSamples); + totalPss = printMemoryCategory(pw, " ", "Z-Ram ", totalMem.sysMemZRamWeight, + totalMem.totalTime, totalPss, totalMem.sysMemSamples); + pw.print(" TOTAL : "); + printSizeValue(pw, totalPss); + pw.println(); + printMemoryCategory(pw, " ", STATE_NAMES[STATE_SERVICE_RESTARTING], + totalMem.processStateWeight[STATE_SERVICE_RESTARTING], totalMem.totalTime, totalPss, + totalMem.processStateSamples[STATE_SERVICE_RESTARTING]); + pw.println(); pw.print(" Start time: "); pw.print(DateFormat.format("yyyy-MM-dd HH:mm:ss", mTimePeriodStartClock)); pw.println(); @@ -2118,8 +2502,6 @@ public final class ProcessStats implements Parcelable { } pw.print(' '); pw.print(mRuntime); - pw.print(' '); - pw.print(mWebView); pw.println(); } @@ -2208,7 +2590,7 @@ public final class ProcessStats implements Parcelable { public void dumpCheckinLocked(PrintWriter pw, String reqPackage) { final long now = SystemClock.uptimeMillis(); final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap(); - pw.println("vers,4"); + pw.println("vers,5"); pw.print("period,"); pw.print(mTimePeriodStartClockStr); pw.print(","); pw.print(mTimePeriodStartRealtime); pw.print(","); pw.print(mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime); @@ -2229,7 +2611,7 @@ public final class ProcessStats implements Parcelable { pw.print(",partial"); } pw.println(); - pw.print("config,"); pw.print(mRuntime); pw.print(','); pw.println(mWebView); + pw.print("config,"); pw.println(mRuntime); for (int ip=0; ip<pkgMap.size(); ip++) { final String pkgName = pkgMap.keyAt(ip); if (reqPackage != null && !reqPackage.equals(pkgName)) { @@ -2362,6 +2744,53 @@ public final class ProcessStats implements Parcelable { pw.print("total"); dumpAdjTimesCheckin(pw, ",", mMemFactorDurations, mMemFactor, mStartTime, now); + if (mSysMemUsageTable != null) { + pw.print("sysmemusage"); + for (int i=0; i<mSysMemUsageTableSize; i++) { + int off = mSysMemUsageTable[i]; + int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; + pw.print(","); + printProcStateTag(pw, type); + for (int j=SYS_MEM_USAGE_SAMPLE_COUNT; j<SYS_MEM_USAGE_COUNT; j++) { + if (j > SYS_MEM_USAGE_CACHED_MINIMUM) { + pw.print(":"); + } + pw.print(getLong(off, j)); + } + } + } + pw.println(); + TotalMemoryUseCollection totalMem = new TotalMemoryUseCollection(ALL_SCREEN_ADJ, + ALL_MEM_ADJ); + computeTotalMemoryUse(totalMem, now); + pw.print("weights,"); + pw.print(totalMem.totalTime); + pw.print(","); + pw.print(totalMem.sysMemCachedWeight); + pw.print(":"); + pw.print(totalMem.sysMemSamples); + pw.print(","); + pw.print(totalMem.sysMemFreeWeight); + pw.print(":"); + pw.print(totalMem.sysMemSamples); + pw.print(","); + pw.print(totalMem.sysMemZRamWeight); + pw.print(":"); + pw.print(totalMem.sysMemSamples); + pw.print(","); + pw.print(totalMem.sysMemKernelWeight); + pw.print(":"); + pw.print(totalMem.sysMemSamples); + pw.print(","); + pw.print(totalMem.sysMemNativeWeight); + pw.print(":"); + pw.print(totalMem.sysMemSamples); + for (int i=0; i<STATE_COUNT; i++) { + pw.print(","); + pw.print(totalMem.processStateWeight[i]); + pw.print(":"); + pw.print(totalMem.processStateSamples[i]); + } pw.println(); } @@ -2452,6 +2881,15 @@ public final class ProcessStats implements Parcelable { } } + final public static class ProcessStateHolder { + public final int appVersion; + public ProcessStats.ProcessState state; + + public ProcessStateHolder(int _appVersion) { + appVersion = _appVersion; + } + } + public static final class ProcessState extends DurationsTable { public ProcessState mCommonProcess; public final String mPackage; @@ -2660,7 +3098,7 @@ public final class ProcessStats implements Parcelable { * @param pkgList Processes to update. */ public void setState(int state, int memFactor, long now, - ArrayMap<String, ProcessState> pkgList) { + ArrayMap<String, ProcessStateHolder> pkgList) { if (state < 0) { state = mNumStartedServices > 0 ? (STATE_SERVICE_RESTARTING+(memFactor*STATE_COUNT)) : STATE_NOTHING; @@ -2770,7 +3208,7 @@ public final class ProcessStats implements Parcelable { } public void addPss(long pss, long uss, boolean always, - ArrayMap<String, ProcessState> pkgList) { + ArrayMap<String, ProcessStateHolder> pkgList) { ensureNotDead(); if (!always) { if (mLastPssState == mCurState && SystemClock.uptimeMillis() @@ -2845,7 +3283,7 @@ public final class ProcessStats implements Parcelable { } } - public void reportExcessiveWake(ArrayMap<String, ProcessState> pkgList) { + public void reportExcessiveWake(ArrayMap<String, ProcessStateHolder> pkgList) { ensureNotDead(); mCommonProcess.mNumExcessiveWake++; if (!mCommonProcess.mMultiPackage) { @@ -2857,7 +3295,7 @@ public final class ProcessStats implements Parcelable { } } - public void reportExcessiveCpu(ArrayMap<String, ProcessState> pkgList) { + public void reportExcessiveCpu(ArrayMap<String, ProcessStateHolder> pkgList) { ensureNotDead(); mCommonProcess.mNumExcessiveCpu++; if (!mCommonProcess.mMultiPackage) { @@ -2888,7 +3326,7 @@ public final class ProcessStats implements Parcelable { } } - public void reportCachedKill(ArrayMap<String, ProcessState> pkgList, long pss) { + public void reportCachedKill(ArrayMap<String, ProcessStateHolder> pkgList, long pss) { ensureNotDead(); mCommonProcess.addCachedKill(1, pss, pss, pss); if (!mCommonProcess.mMultiPackage) { @@ -2925,8 +3363,10 @@ public final class ProcessStats implements Parcelable { return this; } - private ProcessState pullFixedProc(ArrayMap<String, ProcessState> pkgList, int index) { - ProcessState proc = pkgList.valueAt(index); + private ProcessState pullFixedProc(ArrayMap<String, ProcessStateHolder> pkgList, + int index) { + ProcessStateHolder holder = pkgList.valueAt(index); + ProcessState proc = holder.state; if (mDead && proc.mCommonProcess != proc) { // Somehow we are contining to use a process state that is dead, because // it was not being told it was active during the last commit. We can recover @@ -2959,7 +3399,7 @@ public final class ProcessStats implements Parcelable { throw new IllegalStateException("Didn't create per-package process " + proc.mName + " in pkg " + pkg.mPackageName + "/" + pkg.mUid); } - pkgList.setValueAt(index, proc); + holder.state = proc; } return proc; } @@ -3351,4 +3791,27 @@ public final class ProcessStats implements Parcelable { } } } + + public static class TotalMemoryUseCollection { + final int[] screenStates; + final int[] memStates; + + public TotalMemoryUseCollection(int[] _screenStates, int[] _memStates) { + screenStates = _screenStates; + memStates = _memStates; + } + + public long totalTime; + public long[] processStatePss = new long[STATE_COUNT]; + public double[] processStateWeight = new double[STATE_COUNT]; + public long[] processStateTime = new long[STATE_COUNT]; + public int[] processStateSamples = new int[STATE_COUNT]; + public long[] sysMemUsage = new long[SYS_MEM_USAGE_COUNT]; + public double sysMemCachedWeight; + public double sysMemFreeWeight; + public double sysMemZRamWeight; + public double sysMemKernelWeight; + public double sysMemNativeWeight; + public int sysMemSamples; + } } diff --git a/core/java/com/android/internal/app/WindowDecorActionBar.java b/core/java/com/android/internal/app/WindowDecorActionBar.java index 87a80ace347f..7bd316f31519 100644 --- a/core/java/com/android/internal/app/WindowDecorActionBar.java +++ b/core/java/com/android/internal/app/WindowDecorActionBar.java @@ -830,7 +830,9 @@ public class WindowDecorActionBar extends ActionBar implements } public boolean isShowing() { - return mNowShowing && getHideOffset() < getHeight(); + final int height = getHeight(); + // Take into account the case where the bar has a 0 height due to not being measured yet. + return mNowShowing && (height == 0 || getHideOffset() < height); } void animateToMode(boolean toActionMode) { diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java index ff0ee65c911d..b098de820ce7 100644 --- a/core/java/com/android/internal/backup/LocalTransport.java +++ b/core/java/com/android/internal/backup/LocalTransport.java @@ -93,6 +93,9 @@ public class LocalTransport extends BackupTransport { private File mFullRestoreSetDir; private HashSet<String> mFullRestorePackages; + private FileInputStream mCurFullRestoreStream; + private FileOutputStream mFullRestoreSocketStream; + private byte[] mFullRestoreBuffer; public LocalTransport(Context context) { mContext = context; @@ -104,34 +107,41 @@ public class LocalTransport extends BackupTransport { } } + @Override public String name() { return new ComponentName(mContext, this.getClass()).flattenToShortString(); } + @Override public Intent configurationIntent() { // The local transport is not user-configurable return null; } + @Override public String currentDestinationString() { return TRANSPORT_DESTINATION_STRING; } + @Override public String transportDirName() { return TRANSPORT_DIR_NAME; } + @Override public long requestBackupTime() { // any time is a good time for local backup return 0; } + @Override public int initializeDevice() { if (DEBUG) Log.v(TAG, "wiping all data"); deleteContents(mCurrentSetDir); - return BackupTransport.TRANSPORT_OK; + return TRANSPORT_OK; } + @Override public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor data) { if (DEBUG) { try { @@ -191,7 +201,7 @@ public class LocalTransport extends BackupTransport { entity.write(buf, 0, dataSize); } catch (IOException e) { Log.e(TAG, "Unable to update key file " + entityFile.getAbsolutePath()); - return BackupTransport.TRANSPORT_ERROR; + return TRANSPORT_ERROR; } finally { entity.close(); } @@ -199,11 +209,11 @@ public class LocalTransport extends BackupTransport { entityFile.delete(); } } - return BackupTransport.TRANSPORT_OK; + return TRANSPORT_OK; } catch (IOException e) { // oops, something went wrong. abort the operation and return error. Log.v(TAG, "Exception reading backup input:", e); - return BackupTransport.TRANSPORT_ERROR; + return TRANSPORT_ERROR; } } @@ -222,6 +232,7 @@ public class LocalTransport extends BackupTransport { } } + @Override public int clearBackupData(PackageInfo packageInfo) { if (DEBUG) Log.v(TAG, "clearBackupData() pkg=" + packageInfo.packageName); @@ -243,9 +254,10 @@ public class LocalTransport extends BackupTransport { packageDir.delete(); } - return BackupTransport.TRANSPORT_OK; + return TRANSPORT_OK; } + @Override public int finishBackup() { if (DEBUG) Log.v(TAG, "finishBackup()"); if (mSocket != null) { @@ -259,24 +271,27 @@ public class LocalTransport extends BackupTransport { mFullTargetPackage = null; mSocket.close(); } catch (IOException e) { - return BackupTransport.TRANSPORT_ERROR; + return TRANSPORT_ERROR; } finally { mSocket = null; } } - return BackupTransport.TRANSPORT_OK; + return TRANSPORT_OK; } // ------------------------------------------------------------------------------------ // Full backup handling + + @Override public long requestFullBackupTime() { return 0; } + @Override public int performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket) { if (mSocket != null) { Log.e(TAG, "Attempt to initiate full backup while one is in progress"); - return BackupTransport.TRANSPORT_ERROR; + return TRANSPORT_ERROR; } if (DEBUG) { @@ -291,7 +306,7 @@ public class LocalTransport extends BackupTransport { mSocketInputStream = new FileInputStream(mSocket.getFileDescriptor()); } catch (IOException e) { Log.e(TAG, "Unable to process socket for full backup"); - return BackupTransport.TRANSPORT_ERROR; + return TRANSPORT_ERROR; } mFullTargetPackage = targetPackage.packageName; @@ -300,18 +315,19 @@ public class LocalTransport extends BackupTransport { File tarball = new File(mCurrentSetFullDir, mFullTargetPackage); tarstream = new FileOutputStream(tarball); } catch (FileNotFoundException e) { - return BackupTransport.TRANSPORT_ERROR; + return TRANSPORT_ERROR; } mFullBackupOutputStream = new BufferedOutputStream(tarstream); mFullBackupBuffer = new byte[4096]; - return BackupTransport.TRANSPORT_OK; + return TRANSPORT_OK; } + @Override public int sendBackupData(int numBytes) { if (mFullBackupBuffer == null) { Log.w(TAG, "Attempted sendBackupData before performFullBackup"); - return BackupTransport.TRANSPORT_ERROR; + return TRANSPORT_ERROR; } if (numBytes > mFullBackupBuffer.length) { @@ -323,21 +339,23 @@ public class LocalTransport extends BackupTransport { if (nRead < 0) { // Something went wrong if we expect data but saw EOD Log.w(TAG, "Unexpected EOD; failing backup"); - return BackupTransport.TRANSPORT_ERROR; + return TRANSPORT_ERROR; } mFullBackupOutputStream.write(mFullBackupBuffer, 0, nRead); numBytes -= nRead; } catch (IOException e) { Log.e(TAG, "Error handling backup data for " + mFullTargetPackage); - return BackupTransport.TRANSPORT_ERROR; + return TRANSPORT_ERROR; } } - return BackupTransport.TRANSPORT_OK; + return TRANSPORT_OK; } // ------------------------------------------------------------------------------------ // Restore handling static final long[] POSSIBLE_SETS = { 2, 3, 4, 5, 6, 7, 8, 9 }; + + @Override public RestoreSet[] getAvailableRestoreSets() { long[] existing = new long[POSSIBLE_SETS.length + 1]; int num = 0; @@ -358,11 +376,13 @@ public class LocalTransport extends BackupTransport { return available; } + @Override public long getCurrentRestoreSet() { // The current restore set always has the same token return CURRENT_SET_TOKEN; } + @Override public int startRestore(long token, PackageInfo[] packages) { if (DEBUG) Log.v(TAG, "start restore " + token); mRestorePackages = packages; @@ -371,7 +391,7 @@ public class LocalTransport extends BackupTransport { mRestoreSetDir = new File(mDataDir, Long.toString(token)); mRestoreSetIncrementalDir = new File(mRestoreSetDir, INCREMENTAL_DIR); mRestoreSetFullDir = new File(mRestoreSetDir, FULL_DATA_DIR); - return BackupTransport.TRANSPORT_OK; + return TRANSPORT_OK; } @Override @@ -397,6 +417,7 @@ public class LocalTransport extends BackupTransport { if (maybeFullData.length() > 0) { if (DEBUG) Log.v(TAG, " nextRestorePackage(TYPE_FULL_STREAM) = " + name); mRestoreType = RestoreDescription.TYPE_FULL_STREAM; + mCurFullRestoreStream = null; // ensure starting from the ground state found = true; } } @@ -410,6 +431,7 @@ public class LocalTransport extends BackupTransport { return RestoreDescription.NO_MORE_PACKAGES; } + @Override public int getRestoreData(ParcelFileDescriptor outFd) { if (mRestorePackages == null) throw new IllegalStateException("startRestore not called"); if (mRestorePackage < 0) throw new IllegalStateException("nextRestorePackage not called"); @@ -426,7 +448,7 @@ public class LocalTransport extends BackupTransport { ArrayList<DecodedFilename> blobs = contentsByKey(packageDir); if (blobs == null) { // nextRestorePackage() ensures the dir exists, so this is an error Log.e(TAG, "No keys for package: " + packageDir); - return BackupTransport.TRANSPORT_ERROR; + return TRANSPORT_ERROR; } // We expect at least some data if the directory exists in the first place @@ -447,10 +469,10 @@ public class LocalTransport extends BackupTransport { in.close(); } } - return BackupTransport.TRANSPORT_OK; + return TRANSPORT_OK; } catch (IOException e) { Log.e(TAG, "Unable to read backup records", e); - return BackupTransport.TRANSPORT_ERROR; + return TRANSPORT_ERROR; } } @@ -487,38 +509,27 @@ public class LocalTransport extends BackupTransport { return contents; } + @Override public void finishRestore() { if (DEBUG) Log.v(TAG, "finishRestore()"); + if (mRestoreType == RestoreDescription.TYPE_FULL_STREAM) { + resetFullRestoreState(); + } + mRestoreType = 0; } // ------------------------------------------------------------------------------------ // Full restore handling - public int prepareFullRestore(long token, String[] targetPackages) { - mRestoreSetDir = new File(mDataDir, Long.toString(token)); - mFullRestoreSetDir = new File(mRestoreSetDir, FULL_DATA_DIR); - mFullRestorePackages = new HashSet<String>(); - if (mFullRestoreSetDir.exists()) { - List<String> pkgs = Arrays.asList(mFullRestoreSetDir.list()); - HashSet<String> available = new HashSet<String>(pkgs); - - for (int i = 0; i < targetPackages.length; i++) { - if (available.contains(targetPackages[i])) { - mFullRestorePackages.add(targetPackages[i]); - } - } + private void resetFullRestoreState() { + try { + mCurFullRestoreStream.close(); + } catch (IOException e) { + Log.w(TAG, "Unable to close full restore input stream"); } - return BackupTransport.TRANSPORT_OK; - } - - /** - * Ask the transport what package's full data will be restored next. When all apps' - * data has been delivered, the transport should return {@code null} here. - * @return The package name of the next application whose data will be restored, or - * {@code null} if all available package has been delivered. - */ - public String getNextFullRestorePackage() { - return null; + mCurFullRestoreStream = null; + mFullRestoreSocketStream = null; + mFullRestoreBuffer = null; } /** @@ -543,7 +554,79 @@ public class LocalTransport extends BackupTransport { * indicating a fatal error condition that precludes further restore operations * on the current dataset. */ + @Override public int getNextFullRestoreDataChunk(ParcelFileDescriptor socket) { - return 0; + if (mRestoreType != RestoreDescription.TYPE_FULL_STREAM) { + throw new IllegalStateException("Asked for full restore data for non-stream package"); + } + + // first chunk? + if (mCurFullRestoreStream == null) { + final String name = mRestorePackages[mRestorePackage].packageName; + if (DEBUG) Log.i(TAG, "Starting full restore of " + name); + File dataset = new File(mRestoreSetFullDir, name); + try { + mCurFullRestoreStream = new FileInputStream(dataset); + } catch (IOException e) { + // If we can't open the target package's tarball, we return the single-package + // error code and let the caller go on to the next package. + Log.e(TAG, "Unable to read archive for " + name); + return TRANSPORT_PACKAGE_REJECTED; + } + mFullRestoreSocketStream = new FileOutputStream(socket.getFileDescriptor()); + mFullRestoreBuffer = new byte[32*1024]; + } + + int nRead; + try { + nRead = mCurFullRestoreStream.read(mFullRestoreBuffer); + if (nRead < 0) { + // EOF: tell the caller we're done + nRead = NO_MORE_DATA; + } else if (nRead == 0) { + // This shouldn't happen when reading a FileInputStream; we should always + // get either a positive nonzero byte count or -1. Log the situation and + // treat it as EOF. + Log.w(TAG, "read() of archive file returned 0; treating as EOF"); + nRead = NO_MORE_DATA; + } else { + if (DEBUG) { + Log.i(TAG, " delivering restore chunk: " + nRead); + } + mFullRestoreSocketStream.write(mFullRestoreBuffer, 0, nRead); + } + } catch (IOException e) { + return TRANSPORT_ERROR; // Hard error accessing the file; shouldn't happen + } finally { + // Most transports will need to explicitly close 'socket' here, but this transport + // is in the same process as the caller so it can leave it up to the backup manager + // to manage both socket fds. + } + + return nRead; } + + /** + * If the OS encounters an error while processing {@link RestoreDescription#TYPE_FULL_STREAM} + * data for restore, it will invoke this method to tell the transport that it should + * abandon the data download for the current package. The OS will then either call + * {@link #nextRestorePackage()} again to move on to restoring the next package in the + * set being iterated over, or will call {@link #finishRestore()} to shut down the restore + * operation. + * + * @return {@link #TRANSPORT_OK} if the transport was successful in shutting down the + * current stream cleanly, or {@link #TRANSPORT_ERROR} to indicate a serious + * transport-level failure. If the transport reports an error here, the entire restore + * operation will immediately be finished with no further attempts to restore app data. + */ + @Override + public int abortFullRestore() { + if (mRestoreType != RestoreDescription.TYPE_FULL_STREAM) { + throw new IllegalStateException("abortFullRestore() but not currently restoring"); + } + resetFullRestoreState(); + mRestoreType = 0; + return TRANSPORT_OK; + } + } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 240d520c066d..1ccaa0f35d0d 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -291,6 +291,7 @@ public final class BatteryStatsImpl extends BatteryStats { final StopwatchTimer[] mBluetoothStateTimer = new StopwatchTimer[NUM_BLUETOOTH_STATES]; int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW; + long mMobileRadioActiveStartTime; StopwatchTimer mMobileRadioActiveTimer; StopwatchTimer mMobileRadioActivePerAppTimer; LongSamplingCounter mMobileRadioActiveAdjustedTime; @@ -1425,10 +1426,6 @@ public final class BatteryStatsImpl extends BatteryStats { return 0; } - long getLastUpdateTimeMs() { - return mUpdateTime; - } - void stopRunningLocked(long elapsedRealtimeMs) { // Ignore attempt to stop a timer that isn't running if (mNesting == 0) { @@ -2790,11 +2787,11 @@ public final class BatteryStatsImpl extends BatteryStats { powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH; if (active) { - realElapsedRealtimeMs = elapsedRealtime; + mMobileRadioActiveStartTime = realElapsedRealtimeMs = elapsedRealtime; mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG; } else { realElapsedRealtimeMs = timestampNs / (1000*1000); - long lastUpdateTimeMs = mMobileRadioActiveTimer.getLastUpdateTimeMs(); + long lastUpdateTimeMs = mMobileRadioActiveStartTime; if (realElapsedRealtimeMs < lastUpdateTimeMs) { Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs + " is before start time " + lastUpdateTimeMs); diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp index 69e149e94974..935e3a020d75 100644 --- a/core/jni/android/graphics/Canvas.cpp +++ b/core/jni/android/graphics/Canvas.cpp @@ -1320,10 +1320,6 @@ static JNINativeMethod gCanvasMethods[] = { (void*) SkCanvasGlue::drawTextRun___CIIIIFFZPaintTypeface}, {"native_drawTextRun","(JLjava/lang/String;IIIIFFZJJ)V", (void*) SkCanvasGlue::drawTextRun__StringIIIIFFZPaintTypeface}, - {"native_drawPosText","(J[CII[FJ)V", - (void*) SkCanvasGlue::drawPosText___CII_FPaint}, - {"native_drawPosText","(JLjava/lang/String;[FJ)V", - (void*) SkCanvasGlue::drawPosText__String_FPaint}, {"native_drawTextOnPath","(J[CIIJFFIJJ)V", (void*) SkCanvasGlue::drawTextOnPath___CIIPathFFPaint}, {"native_drawTextOnPath","(JLjava/lang/String;JFFIJJ)V", diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp index d07b154291fb..dc308143b2db 100644 --- a/core/jni/android/graphics/Paint.cpp +++ b/core/jni/android/graphics/Paint.cpp @@ -37,6 +37,7 @@ #include "TextLayout.h" #ifdef USE_MINIKIN +#include <minikin/GraphemeBreak.h> #include <minikin/Layout.h> #include "MinikinSkia.h" #include "MinikinUtils.h" @@ -778,6 +779,11 @@ public: static jint doTextRunCursor(JNIEnv *env, SkPaint* paint, const jchar *text, jint start, jint count, jint flags, jint offset, jint opt) { +#ifdef USE_MINIKIN + GraphemeBreak::MoveOpt moveOpt = GraphemeBreak::MoveOpt(opt); + size_t result = GraphemeBreak::getTextRunCursor(text, start, count, offset, moveOpt); + return static_cast<jint>(result); +#else jfloat scalarArray[count]; TextLayout::getTextRunAdvances(paint, text, start, count, start + count, flags, @@ -818,6 +824,7 @@ public: } return pos; +#endif } static jint getTextRunCursor___C(JNIEnv* env, jobject clazz, jlong paintHandle, jcharArray text, diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index 3a533310ea99..4c9feca6e719 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -466,7 +466,7 @@ static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz, // connect to camera service static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, - jobject weak_this, jint cameraId, jstring clientPackageName) + jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName) { // Convert jstring to String16 const char16_t *rawClientName = env->GetStringChars(clientPackageName, NULL); @@ -474,8 +474,18 @@ static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, String16 clientName(rawClientName, rawClientNameLen); env->ReleaseStringChars(clientPackageName, rawClientName); - sp<Camera> camera = Camera::connect(cameraId, clientName, - Camera::USE_CALLING_UID); + sp<Camera> camera; + if (halVersion == ICameraService::CAMERA_HAL_API_VERSION_UNSPECIFIED) { + // Default path: hal version is unspecified, do normal camera open. + camera = Camera::connect(cameraId, clientName, + Camera::USE_CALLING_UID); + } else { + jint status = Camera::connectLegacy(cameraId, halVersion, clientName, + Camera::USE_CALLING_UID, camera); + if (status != NO_ERROR) { + return status; + } + } if (camera == NULL) { return -EACCES; @@ -510,7 +520,6 @@ static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, // finalizer is invoked later. static void android_hardware_Camera_release(JNIEnv *env, jobject thiz) { - // TODO: Change to ALOGV ALOGV("release camera"); JNICameraContext* context = NULL; sp<Camera> camera; @@ -891,7 +900,7 @@ static JNINativeMethod camMethods[] = { "(ILandroid/hardware/Camera$CameraInfo;)V", (void*)android_hardware_Camera_getCameraInfo }, { "native_setup", - "(Ljava/lang/Object;ILjava/lang/String;)I", + "(Ljava/lang/Object;IILjava/lang/String;)I", (void*)android_hardware_Camera_native_setup }, { "native_release", "()V", diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h index a2b1ed9aa7bc..807dd32762bb 100644 --- a/core/jni/android_media_AudioFormat.h +++ b/core/jni/android_media_AudioFormat.h @@ -20,11 +20,15 @@ #include <system/audio.h> // keep these values in sync with AudioFormat.java -#define ENCODING_PCM_16BIT 2 -#define ENCODING_PCM_8BIT 3 -#define ENCODING_PCM_FLOAT 4 -#define ENCODING_INVALID 0 -#define ENCODING_DEFAULT 1 +#define ENCODING_PCM_16BIT 2 +#define ENCODING_PCM_8BIT 3 +#define ENCODING_PCM_FLOAT 4 +#define ENCODING_AC3 5 +#define ENCODING_E_AC3 6 +#define ENCODING_INVALID 0 +#define ENCODING_DEFAULT 1 + + #define CHANNEL_INVALID 0 #define CHANNEL_OUT_DEFAULT 1 @@ -38,6 +42,10 @@ static inline audio_format_t audioFormatToNative(int audioFormat) return AUDIO_FORMAT_PCM_8_BIT; case ENCODING_PCM_FLOAT: return AUDIO_FORMAT_PCM_FLOAT; + case ENCODING_AC3: + return AUDIO_FORMAT_AC3; + case ENCODING_E_AC3: + return AUDIO_FORMAT_E_AC3; case ENCODING_DEFAULT: return AUDIO_FORMAT_DEFAULT; default: @@ -54,6 +62,10 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat) return ENCODING_PCM_8BIT; case AUDIO_FORMAT_PCM_FLOAT: return ENCODING_PCM_FLOAT; + case AUDIO_FORMAT_AC3: + return ENCODING_AC3; + case AUDIO_FORMAT_E_AC3: + return ENCODING_E_AC3; case AUDIO_FORMAT_DEFAULT: return ENCODING_DEFAULT; default: diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp index e548e913f66f..264a9ae6a9bd 100644 --- a/core/jni/android_media_AudioTrack.cpp +++ b/core/jni/android_media_AudioTrack.cpp @@ -220,8 +220,13 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, } // compute the frame count - const size_t bytesPerSample = audio_bytes_per_sample(format); - size_t frameCount = buffSizeInBytes / (channelCount * bytesPerSample); + size_t frameCount; + if (audio_is_linear_pcm(format)) { + const size_t bytesPerSample = audio_bytes_per_sample(format); + frameCount = buffSizeInBytes / (channelCount * bytesPerSample); + } else { + frameCount = buffSizeInBytes; + } jclass clazz = env->GetObjectClass(thiz); if (clazz == NULL) { @@ -266,7 +271,7 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, format,// word length, PCM nativeChannelMask, frameCount, - AUDIO_OUTPUT_FLAG_NONE, + audio_is_linear_pcm(format) ? AUDIO_OUTPUT_FLAG_NONE : AUDIO_OUTPUT_FLAG_DIRECT, audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user) 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack 0,// shared mem @@ -478,14 +483,6 @@ jint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, const jbyte* da switch (format) { default: - // TODO Currently the only possible values for format are AUDIO_FORMAT_PCM_16_BIT, - // AUDIO_FORMAT_PCM_8_BIT, and AUDIO_FORMAT_PCM_FLOAT, - // due to the limited set of values for audioFormat. - // The next section of the switch will probably work for more formats, but it has only - // been tested for AUDIO_FORMAT_PCM_16_BIT and AUDIO_FORMAT_PCM_FLOAT, - // so that's why the "default" case fails. - break; - case AUDIO_FORMAT_PCM_FLOAT: case AUDIO_FORMAT_PCM_16_BIT: { // writing to shared memory, check for capacity @@ -904,8 +901,12 @@ static jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env, jobject thi return -1; } const audio_format_t format = audioFormatToNative(audioFormat); - const size_t bytesPerSample = audio_bytes_per_sample(format); - return frameCount * channelCount * bytesPerSample; + if (audio_is_linear_pcm(format)) { + const size_t bytesPerSample = audio_bytes_per_sample(format); + return frameCount * channelCount * bytesPerSample; + } else { + return frameCount; + } } // ---------------------------------------------------------------------------- diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index de00e594ccda..dc1ea066b2bc 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -840,49 +840,6 @@ static void android_view_GLES20Canvas_drawTextRun(JNIEnv* env, jobject clazz, env->ReleaseStringChars(text, textArray); } -static void renderPosText(OpenGLRenderer* renderer, const jchar* text, int count, - const jfloat* positions, jint bidiFlags, SkPaint* paint) { - sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint, - text, 0, count, count, bidiFlags); - if (value == NULL) { - return; - } - const jchar* glyphs = value->getGlyphs(); - size_t glyphsCount = value->getGlyphsCount(); - if (count < int(glyphsCount)) glyphsCount = count; - int bytesCount = glyphsCount * sizeof(jchar); - - renderer->drawPosText((const char*) glyphs, bytesCount, glyphsCount, positions, paint); -} - -static void android_view_GLES20Canvas_drawPosTextArray(JNIEnv* env, jobject clazz, - jlong rendererPtr, jcharArray text, jint index, jint count, - jfloatArray pos, jlong paintPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); - jchar* textArray = env->GetCharArrayElements(text, NULL); - jfloat* positions = env->GetFloatArrayElements(pos, NULL); - SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); - - renderPosText(renderer, textArray + index, count, positions, kBidi_LTR, paint); - - env->ReleaseFloatArrayElements(pos, positions, JNI_ABORT); - env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); -} - -static void android_view_GLES20Canvas_drawPosText(JNIEnv* env, jobject clazz, - jlong rendererPtr, jstring text, jint start, jint end, - jfloatArray pos, jlong paintPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); - const jchar* textArray = env->GetStringChars(text, NULL); - jfloat* positions = env->GetFloatArrayElements(pos, NULL); - SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); - - renderPosText(renderer, textArray + start, end - start, positions, kBidi_LTR, paint); - - env->ReleaseFloatArrayElements(pos, positions, JNI_ABORT); - env->ReleaseStringChars(text, textArray); -} - // ---------------------------------------------------------------------------- // Display lists // ---------------------------------------------------------------------------- @@ -1039,10 +996,6 @@ static JNINativeMethod gMethods[] = { { "nDrawTextRun", "(JLjava/lang/String;IIIIFFZJJ)V", (void*) android_view_GLES20Canvas_drawTextRun }, - { "nDrawPosText", "(J[CII[FJ)V", (void*) android_view_GLES20Canvas_drawPosTextArray }, - { "nDrawPosText", "(JLjava/lang/String;II[FJ)V", - (void*) android_view_GLES20Canvas_drawPosText }, - { "nGetClipBounds", "(JLandroid/graphics/Rect;)Z", (void*) android_view_GLES20Canvas_getClipBounds }, diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 8b5dff014e19..fa1a563e43b9 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2742,7 +2742,8 @@ android:finishOnCloseSystemDialogs="true" android:excludeFromRecents="true" android:multiprocess="true" - android:documentLaunchMode="never"> + android:documentLaunchMode="never" + android:relinquishTaskIdentity="true"> <intent-filter> <action android:name="android.intent.action.CHOOSER" /> <category android:name="android.intent.category.DEFAULT" /> diff --git a/core/res/res/anim/lock_screen_behind_enter.xml b/core/res/res/anim/lock_screen_behind_enter.xml index 7e212bee416a..ace17ae3d585 100644 --- a/core/res/res/anim/lock_screen_behind_enter.xml +++ b/core/res/res/anim/lock_screen_behind_enter.xml @@ -18,7 +18,7 @@ --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:detachWallpaper="true" android:shareInterpolator="false" android:startOffset="60"> + android:detachWallpaper="true" android:shareInterpolator="false" android:startOffset="100"> <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:fillEnabled="true" android:fillBefore="true" diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index 72b09093d3bc..cb93530e70a7 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Laat die program toe om \'n alarm in \'n geïnstalleerde wekkerprogram te stel. Sommige wekkerprogramme werk dalk nie met hierdie funksie nie."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"voeg stemboodskap by"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Laat die program toe om boodskappe by te voeg by jou stempos-inkassie."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"lees alle stempos"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Laat die program toe om al jou stemposse te lees."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"verander blaaier se geoligging-toestemmings"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Laat die program toe om die blaaier se geoligging-toestemmings te verander. Kwaadwillige programme kan dit gebruik om hulle toe te laat om ligginginligting aan enige webwerf te stuur."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"verifieer pakkies"</string> @@ -1362,10 +1364,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"Laat \'n program toe om vir veranderinge in vertrouenstaat te luister."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Voorsien \'n vertroude agent."</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Laat \'n program toe om \'n vertroude agent te voorsien."</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Begin vertrouensagente se instellingskieslys."</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Laat \'n program toe om \'n aktiwiteit te begin wat die vertrouensagent se gedrag verander."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Verbind met \'n vertrouensagentdiens"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Laat \'n program toe om met \'n vertrouensagentdiens te verbind."</string> <string name="permlab_recovery" msgid="3157024487744125846">"Tree in wisselwerking met opdatering- en terugstellingstelsel"</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index da891368585b..66faf613c45d 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"በተጫነው የማንቂያ ሰዓት መተግበሪያ ውስጥ ማንቅያን ለማደራጀት ለመተግበሪያው ይፈቅዳሉ፡፡አንዳንድ የማንቂያ ሰዓት መተግበሪያዎች ይሄንን ባህሪ ላይፈፅሙ ይችላሉ፡፡"</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"የድምፅ መልዕክት አክል"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"ወደ ድምፅ መልዕክት የገቢ መልዕክትህ መልዕክቶች ለማከል ለመተግበሪያው ይፈቅዳሉ።"</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"ሁሉንም የድምጽ መልዕክት ያነብባል"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"መተግበሪያው ሁሉንም የድምጽ መልዕክቶችዎ እንዲያነባቸው ያስችለዋል።"</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"የአሳሽ ገፀ ሥፍራ ፍቃዶችን ቀይር"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"የአሳሹን የጂኦ-አካባቢ ፍቃዶችን እንዲለውጥ ለመተግበሪያው ይፈቅዳል፡፡ተንኮል አዘል መተግበሪያዎች የመላኪያ አከባቢን መረጃ ወደ አጠራጣሪ የድር ጣቢያዎች ለመፍቀድ ይሄንን ሊጠቀሙበት ይችላሉ፡፡"</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"ፓኬጆችን አረጋግጥ"</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index 626858fd360a..7d1117b9e768 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"للسماح للتطبيق بضبط المنبه في تطبيق المنبه المثبّت. ربما لا تنفذ بعض تطبيقات المنبه هذه الميزة."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"إضافة بريد صوتي"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"للسماح للتطبيق بإضافة رسائل إلى صندوق البريد الصوتي."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"قراءة جميع رسائل البريد الصوتي"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"للسماح للتطبيق بقراءة جميع رسائل البريد الصوتي."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"تعديل أذونات الموقع الجغرافي للمتصفح"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"للسماح لأحد التطبيقات بتعديل أذونات الموقع الجغرافي للمتصفح. يمكن أن تستخدم التطبيقات الضارة هذا للسماح بإرسال معلومات الموقع إلى مواقع ويب عشوائية."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"التحقق من الحزم"</string> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index ca71ce35bb01..b9c4f468273c 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -189,7 +189,7 @@ <string name="safeMode" msgid="2788228061547930246">"Безопасен режим"</string> <string name="android_system_label" msgid="6577375335728551336">"Системно от Android"</string> <string name="user_owner_label" msgid="6465364741001216388">"Лични приложения"</string> - <string name="managed_profile_label" msgid="4287077106125758391">"Служебен под Android"</string> + <string name="managed_profile_label" msgid="4287077106125758391">"Android Work"</string> <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Услуги, които ви струват пари"</string> <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Извършват неща, които могат да ви струват пари."</string> <string name="permgrouplab_messages" msgid="7521249148445456662">"Вашите съобщения"</string> @@ -1001,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Разрешава на приложението да навие инсталирано приложение будилник. Някои будилници може да не изпълнят тази функция."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"добавяне на гласова поща"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Разрешава на приложението да добавя съобщения към входящата ви гласова поща."</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"промяна на разрешенията за местоположение в браузъра"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Разрешава на приложението да променя разрешенията на браузъра за местоположение. Злонамерените приложения могат да използват това, за да изпращат информация за местоположението до произволни уебсайтове."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"проверка на пакетите"</string> @@ -1362,10 +1366,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"Разрешава на приложението да следи за промени в състоянието на надеждност."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Предоставяне на trust agent."</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Разрешава на приложението да предоставя trust agent."</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Стартиране на менюто за настройки за trust agent."</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Разрешава на приложението да стартира активност, която променя поведението на trust agent."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Обвързване с услуга за trust agents"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Разрешава на приложението да се обвърже с услуга за trust agents."</string> <string name="permlab_recovery" msgid="3157024487744125846">"Взаимодействие със системата за актуализации и възстановяване"</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index e1eed49aae1b..18389b6afc10 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -265,8 +265,8 @@ <string name="permdesc_statusBar" msgid="8434669549504290975">"Permet que l\'aplicació desactivi la barra d\'estat o afegeixi i elimini icones del sistema."</string> <string name="permlab_statusBarService" msgid="7247281911387931485">"barra d\'estat"</string> <string name="permdesc_statusBarService" msgid="716113660795976060">"Permet que l\'aplicació sigui la barra d\'estat."</string> - <string name="permlab_expandStatusBar" msgid="1148198785937489264">"ampliar/reduir la barra d\'estat"</string> - <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"Permet que l\'aplicació ampliï o redueixi la barra d\'estat."</string> + <string name="permlab_expandStatusBar" msgid="1148198785937489264">"desplega/contrau la barra d\'estat"</string> + <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"Permet que l\'aplicació desplegui o replegui la barra d\'estat."</string> <string name="permlab_install_shortcut" msgid="4279070216371564234">"instal·la dreceres"</string> <string name="permdesc_install_shortcut" msgid="8341295916286736996">"Permet que una aplicació afegeixi dreceres a la pantalla d\'inici sense la intervenció de l\'usuari."</string> <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"desinstal·la dreceres"</string> @@ -945,7 +945,7 @@ <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"S\'ha iniciat la reorganització del widget."</string> <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Ha finalitzat la reorganització del widget."</string> <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"S\'ha suprimit el widget de <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string> - <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Amplia l\'àrea de desbloqueig."</string> + <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Desplega l\'àrea de desbloqueig."</string> <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Desbloqueig lliscant el dit"</string> <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueig mitjançant patró"</string> <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Desbloqueig facial"</string> @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Permet que l\'aplicació defineixi una alarma en una aplicació de despertador instal·lada. És possible que algunes aplicacions de despertador no incorporin aquesta funció."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"afegeix bústia de veu"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permet que l\'aplicació afegeixi missatges a la safata d\'entrada de la bústia de veu."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"accedir a tots els correus de veu"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Permet que l\'aplicació accedeixi a tots els teus correus de veu."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Modifica els permisos d\'ubicació geogràfica del navegador"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permet que l\'aplicació modifiqui els permisos d\'ubicació geogràfica del navegador. Les aplicacions malicioses poden utilitzar-ho per enviar la informació d\'ubicació a llocs web arbitraris."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"verifica paquets"</string> @@ -1362,10 +1364,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permet que una aplicació escolti els canvis en l\'estat de confiança."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Proporcionar un agent de confiança"</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Permet que una aplicació proporcioni un agent de confiança."</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Inicia el menú de configuració de l\'agent de confiança."</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Permet que una aplicació iniciï una activitat que canviï el comportament de l\'agent de confiança."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Enllaçar amb el servei d\'un agent de confiança"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permet que una aplicació es vinculi amb el servei d\'un agent de confiança."</string> <string name="permlab_recovery" msgid="3157024487744125846">"Interacciona amb el sistema de recuperació i amb les actualitzacions"</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index cf06dc1aed5e..aeb19d0c444e 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Umožňuje aplikaci nastavit budík v nainstalované aplikaci budík. Některé aplikace budík tuto funkci nemusí obsahovat."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"přidat hlasovou zprávu"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Umožňuje aplikaci přidávat zprávy do hlasové schránky."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"číst všechny hlasové zprávy"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Umožňuje aplikaci číst všechny vaše hlasové zprávy."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"změna oprávnění prohlížeče poskytovat informace o zeměpisné poloze"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Umožňuje aplikaci upravit oprávnění funkce geolokace v prohlížeči. Škodlivé aplikace toho mohou využít k odeslání údajů o poloze na libovolné webové stránky."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"ověřit balíčky"</string> @@ -1362,10 +1364,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"Umožňuje aplikaci naslouchat změnám ve stavu důvěryhodnosti."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Poskytování zástupce důvěryhodnosti"</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Umožňuje aplikaci poskytnout zástupce důvěryhodnosti."</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Spustit nabídku nastavení agenta důvěryhodnosti"</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Umožňuje aplikaci spustit aktivitu, která změní chování agenta důvěryhodnosti."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Vázat se na službu zástupce důvěryhodnosti"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Umožňuje aplikaci vázat se na službu zástupce důvěryhodnosti."</string> <string name="permlab_recovery" msgid="3157024487744125846">"Interakce se systémem aktualizací a obnovení"</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 0aa2a36939e5..2996f75d49fc 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Tillader, at appen kan indstille en alarm i en installeret alarmapp. Nogle alarmapps har muligvis ikke denne funktion."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"tilføje telefonsvarer"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Tillader, at appen kan tilføje beskeder på din telefonsvarer."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"læs alle talebeskeder"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Tillader, at appen kan læse alle dine talebeskeder"</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"skifte tilladelser til geografisk placering i Browser"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Tillader, at appen kan ændre browserens tilladelser angående geografisk placering. Ondsindede apps kan benytte dette til at sende oplysninger om placering til vilkårlige websites."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"bekræft pakker"</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index d557d373a5fa..fe5c1390fe66 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Ermöglicht der App, einen Alarm in einer installierten Wecker-App einzurichten. Einige Wecker-Apps implementieren diese Funktion möglicherweise nicht."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"Mailbox-Nachrichten hinzufügen"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Ermöglicht der App, Nachrichten zu Ihrem Mailbox-Posteingang hinzuzufügen"</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"Alle Mailboxnachrichten abrufen"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Ermöglicht der App das Abrufen aller Ihrer Mailboxnachrichten"</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Geolokalisierungsberechtigungen des Browsers ändern"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Ermöglicht der App, die Geolokalisierungsberechtigungen des Browsers zu ändern. Schädliche Apps können so Standortinformationen an beliebige Websites senden."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"Pakete überprüfen"</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 8205c6061579..1a70d190bfc4 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Επιτρέπει στην εφαρμογή τη ρύθμιση μιας ειδοποίησης σε μια εγκατεστημένη εφαρμογή ξυπνητηριού. Ορισμένες εφαρμογές ξυπνητηριού ενδέχεται να μην μπορούν να ενσωματώσουν αυτήν τη λειτουργία."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"προσθήκη τηλεφωνητή"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Επιτρέπει στην εφαρμογή να προσθέτει μηνύματα στα εισερχόμενα του αυτόματου τηλεφωνητή σας."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"ανάγνωση όλων των μηνυμάτων του αυτόματου τηλεφωνητή"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Επιτρέπει στην εφαρμογή να διαβάσει όλα τα μηνύματα του αυτόματου τηλεφωνητή σας."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"τροποποίηση δικαιωμάτων γεωγραφικής θέσης του Προγράμματος περιήγησης"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Επιτρέπει στην εφαρμογή την τροποποίηση των αδειών γεωτοποθεσίας του Προγράμματος περιήγησης. Τυχόν κακόβουλες εφαρμογές ενδέχεται να το χρησιμοποιήσουν για να επιτρέψουν την αποστολή πληροφοριών τοποθεσίας σε αυθαίρετους ιστότοπους."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"επαλήθευση πακέτων"</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index a0c35c82a12b..c6599990e230 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Allows the app to set an alarm in an installed alarm clock app. Some alarm clock apps may not implement this feature."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"add voicemail"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Allows the app to add messages to your voicemail inbox."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"read all voicemail"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Allows the app to read all your voicemails."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Modify Browser geo-location permissions"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Allows the app to modify the Browser\'s geo-location permissions. Malicious apps may use this to allow sending location information to arbitrary websites."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"verify packages"</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index a0c35c82a12b..c6599990e230 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Allows the app to set an alarm in an installed alarm clock app. Some alarm clock apps may not implement this feature."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"add voicemail"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Allows the app to add messages to your voicemail inbox."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"read all voicemail"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Allows the app to read all your voicemails."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Modify Browser geo-location permissions"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Allows the app to modify the Browser\'s geo-location permissions. Malicious apps may use this to allow sending location information to arbitrary websites."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"verify packages"</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index b6a7667c96b6..b1108bf27305 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -1001,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Permite que la aplicación establezca una alarma en una aplicación de alarma instalada. Es posible que algunas aplicaciones de alarma no incluyan esta función."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"agregar correo de voz"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite que la aplicación agregue mensajes a la bandeja de entrada de tu buzón de voz."</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Modificar los permisos de ubicación geográfica del navegador"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permite que la aplicación modifique los permisos de ubicación geográfica del navegador. Las aplicaciones maliciosas pueden utilizar esto para permitir el envío de información de ubicación a sitios web arbitrarios."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"Verificar paquetes"</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 1dcbf62a44a0..f47f5c0b7b7f 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Permite que la aplicación establezca una alarma en una aplicación de reloj instalada. Es posible que algunas aplicaciones de reloj no incluyan esta función."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"añadir buzón de voz"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite que la aplicación añada mensajes a la bandeja de entrada del buzón de voz."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"consultar todos los mensajes de voz"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Permite que la aplicación consulte todos tus mensajes de voz."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"modificar los permisos de ubicación geográfica del navegador"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permite que la aplicación modifique los permisos de ubicación geográfica del navegador. Las aplicaciones malintencionadas pueden usar este permiso para autorizar el envío de información sobre la ubicación a sitios web arbitrarios."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"verificar paquetes"</string> diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml index 60d036e13aa4..0df3aca1a895 100644 --- a/core/res/res/values-et-rEE/strings.xml +++ b/core/res/res/values-et-rEE/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Võimaldab rakendusel seada installitud äratuskellarakenduses äratuse. Mõned äratuskellarakendused ei pruugi seda funktsiooni juurutada."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"lisa kõneposti"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Võimaldab rakendusel lisada sõnumeid teie kõneposti postkasti."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"kogu kõneposti lugemine"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Võimaldab rakendusel kogu kõneposti lugeda."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Brauseri geolokatsiooniõiguste muutmine"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Võimaldab rakendusel muuta brauseri geolokatsiooniõigusi. Pahatahtlikud rakendused võivad seda kasutada asukohateabe saatmise lubamiseks suvalistele veebisaitidele."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"pakettide kinnitamine"</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index b4727bbe081f..d652544e4f04 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"به برنامه اجازه میدهد تا هشداری را در برنامه ساعت زنگدار نصب شده تنظیم کند. برخی از برنامههای ساعت زنگدار نمیتوانند این ویژگی را اعمال کنند."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"افزودن پست صوتی"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"به برنامه اجازه میدهد تا پیامها را به صندوق دریافت پست صوتی شما اضافه کند."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"خواندن کل پست صوتی"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"به برنامه اجازه میدهد همه پستهای صوتیتان را بخواند."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"تغییر مجوزهای مکان جغرافیایی مرورگر"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"به برنامه اجازه میدهد تا مجوزهای جغرافیایی مرورگر را تغییر دهد. برنامههای مخرب میتوانند از آن استفاده کنند تا اطلاعات موقعیت مکانی را به سایتهای وب کتابخانه بفرستند."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"تأیید بستهها"</string> @@ -1362,10 +1364,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"به یک برنامه کاربردی برای گوش دادن به تغییرات در trust اجازه میدهد."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"یک عامل مورد اعتماد فراهم میآورد."</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"به برنامه امکان میدهد یک عامل مورد اعتماد فراهم آورد."</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"منوی تنظیمات نماینده امانی را راهاندازی کنید."</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"به برنامه اجازه میدهد تا فعالیتی را راهاندازی کند که رفتار نماینده امانی را تغییر میدهد."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"اتصال به یک سرویس trust agent"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"به یک برنامه کاربردی برای اتصال به یک سرویس trust agent اجازه میدهد."</string> <string name="permlab_recovery" msgid="3157024487744125846">"تعامل با سیستم بهروزرسانی و بازیابی"</string> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 02c6da4d444c..802fb24da457 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -189,8 +189,7 @@ <string name="safeMode" msgid="2788228061547930246">"Suojattu tila"</string> <string name="android_system_label" msgid="6577375335728551336">"Android-järjestelmä"</string> <string name="user_owner_label" msgid="6465364741001216388">"Omat sovellukset"</string> - <!-- no translation found for managed_profile_label (4287077106125758391) --> - <skip /> + <string name="managed_profile_label" msgid="4287077106125758391">"Android Work"</string> <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Maksulliset palvelut"</string> <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Suorita mahdollisesti maksullisia toimintoja."</string> <string name="permgrouplab_messages" msgid="7521249148445456662">"Omat viestit"</string> @@ -1002,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Antaa sovelluksen asettaa hälytyksen sisäiseen herätyskellosovellukseen. Jotkin herätyskellosovellukset eivät välttämättä käytä tätä ominaisuutta."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"lisää vastaajaviesti"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Antaa sovelluksen lisätä viestejä saapuneisiin vastaajaviesteihin."</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"selaimen maantieteellisen sijainnin lupien muokkaaminen"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Antaa sovelluksen muokata Selaimen maantieteellisen sijainnin lupia. Haitalliset sovellukset voivat sallia tällä sijaintitietojen lähettämisen mielivaltaisiin sivustoihin."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"vahvista paketteja"</string> @@ -1363,10 +1366,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"Antaa sovelluksen seurata luottamuksen tilamuutoksia."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Luotettavan tahon tarjoaminen"</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Antaa sovelluksen tarjota luotettavan tahon."</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Käynnistä luotettavan tahon asetusvalikko."</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Sallii sovelluksen käynnistää toiminnon, joka muuttaa luotettavan tahon toimintaa."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Luotettavaan tahoon sitoutuminen"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Antaa sovelluksen sitoutua luotettavaan tahoon."</string> <string name="permlab_recovery" msgid="3157024487744125846">"Vuorovaikutus päivitys- ja palautusjärjestelmän kanssa"</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index b1292b32a000..ec4c2d6bb107 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -1001,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Permet à l\'application de régler la sonnerie d\'une fonction de réveil installée sur votre appareil. Cette fonctionnalité n\'est pas compatible avec toutes les applications de réveils."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"ajouter des messages vocaux"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permet à l\'application d\'ajouter des messages à votre messagerie vocale."</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"modifier les autorisations de géolocalisation du navigateur"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permet à l\'application de modifier les autorisations de géolocalisation du navigateur. Des applications malveillantes peuvent exploiter cette fonctionnalité pour permettre l\'envoi de données de localisation à des sites Web arbitraires."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"vérifier les paquets"</string> @@ -1362,10 +1366,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permet à une application de détecter les modifications de l\'état de confiance."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Fournir un agent de confiance."</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Permet à une application de fournir un agent de confiance."</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Lancer le menu des paramètres de l\'agent de confiance."</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Permet à une application de lancer une activité qui modifie le comportement de l\'agent de confiance."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Lier à un service d\'agent de confiance"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permet à une application de se lier à un service d\'agent de confiance."</string> <string name="permlab_recovery" msgid="3157024487744125846">"Interagir avec le système de récupération et de mise à jour"</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index f511df0aad02..57ee762ee14d 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Permet à l\'application de régler la sonnerie d\'un réveil installé. Cette fonctionnalité n\'est pas disponible sur tous les réveils."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"ajouter un message vocal"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permet à l\'application d\'ajouter des messages à votre messagerie vocale."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"accéder à tous les messages vocaux"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Permet à l\'application d\'accéder à tous vos messages vocaux."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"modifier les autorisations de géolocalisation du navigateur"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permet à l\'application de modifier les autorisations de géolocalisation du navigateur. Des applications malveillantes peuvent exploiter cette fonctionnalité pour permettre l\'envoi de données de localisation à des sites Web arbitraires."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"vérifier les packages"</string> @@ -1362,10 +1364,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permettre à une application de détecter les modifications de l\'état de confiance."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Fournir un agent de confiance"</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Permettre à une application de fournir un agent de confiance"</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Lancer le menu des paramètres de l\'agent de confiance"</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Permet à une application de lancer une activité qui modifie le comportement de l\'agent de confiance."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"S\'associer à un service d\'agent de confiance"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permettre à une application de s\'associer à un service d\'agent de confiance."</string> <string name="permlab_recovery" msgid="3157024487744125846">"Interagir avec le système de récupération et de mise à jour"</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 470ec4110266..8c2c025849e3 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -1001,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"ऐप्स को इंस्टॉल किए गए अलार्म घड़ी ऐप्स में अलार्म सेट करने देता है. हो सकता है कुछ अलार्म घड़ी ऐप्स में यह सुविधा न हो."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"ध्वनिमेल जोड़ें"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"ऐप्स को आपके ध्वनिमेल इनबॉक्स में संदेश जोड़ने देता है."</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ब्राउज़र भौगोलिक-स्थान अनुमतियों को बदलें"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ऐप्स को ब्राउज़र के भौगोलिक-स्थान की अनुमतियां संशोधित करने देता है. दुर्भावनापूर्ण ऐप्स इसका उपयोग एकपक्षीय वेबसाइट को स्थान जानकारी भेजने में कर सकते हैं."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"पैकेज सत्यापित करें"</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index 7dc8e191a5ba..65e64ecb6a3d 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Omogućuje aplikaciji postavljanje alarma na instaliranoj aplikaciji budilici. Neke aplikacije budilice možda neće primijeniti tu značajku."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"dodaj govornu poštu"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Omogućuje aplikaciji da doda poruke u vašu govornu poštu."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"čitanje svih poruka u govornoj pošti"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Aplikaciji omogućuje čitanje svih vaših poruka u govornoj pošti."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"izmjena dozvola za geolociranje u pregledniku"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Omogućuje aplikaciji promjenu geolokacijskih dozvola preglednika. Zlonamjerne aplikacije mogu to upotrijebiti da bi dopustile slanje podataka o lokaciji nasumičnim web-lokacijama."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"provjeri pakete"</string> @@ -1362,10 +1364,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"Omogućuje aplikaciji praćenje promjena pouzdanog stanja."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Pružanje agenta za pouzdanost."</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Omogućuje aplikaciji pružanje agenta za pouzdanost."</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Pokretanje izbornika postavki pouzdanog agenta."</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Aplikaciji omogućuje pokretanje aktivnosti koja mijenja ponašanje pouzdanog agenta."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Povezivanje s uslugom pouzdanog predstavnika"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Omogućuje aplikaciji povezivanje s uslugom pouzdanog predstavnika."</string> <string name="permlab_recovery" msgid="3157024487744125846">"Interakcija s ažuriranjem i sustavom za oporavak"</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index 2582737d54a4..498e28a44f17 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -401,7 +401,7 @@ <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"csatlakozás egy hangvezérlőhöz"</string> <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Lehetővé teszi a használó számára, hogy csatlakozzon egy hangvezérlő szolgáltatás legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string> <string name="permlab_manageVoiceKeyphrases" msgid="1252285102392793548">"hangalapú kulcskifejezések kezelése"</string> - <string name="permdesc_manageVoiceKeyphrases" msgid="8476560722907530008">"A használó kezelheti a hangalapú hotwordök felismerésére szolgáló kulcskifejezéseket. Az átlagos alkalmazásoknak nem lehet rá szükségük."</string> + <string name="permdesc_manageVoiceKeyphrases" msgid="8476560722907530008">"Az engedély birtokosa kezelheti a hangalapú hotwordök felismerésére szolgáló kulcskifejezéseket. Az átlagos alkalmazásoknak nem lehet rá szükségük."</string> <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"csatlakozás egy távoli kijelzőhöz"</string> <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Lehetővé teszi a használó számára, hogy csatlakozzon egy távoli kijelző legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"csatlakozás modulszolgáltatáshoz"</string> @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Lehetővé teszi az alkalmazás számára, hogy ébresztőt állítson be egy telepített ébresztőóra alkalmazásban. Egyes ilyen alkalmazásokban lehet, hogy nem működik ez a funkció."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"hangposta hozzáadása"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Lehetővé teszi az alkalmazás számára, hogy üzeneteket adjon hozzá bejövő hangpostájához."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"az összes hangüzenet olvasása"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Engedélyezi az alkalmazásnak az összes hangüzenet olvasását."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"a böngésző helymeghatározási engedélyeinek módosítása"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Lehetővé teszi az alkalmazás számára, hogy módosítsa a böngésző helymeghatározási engedélyeit. Rosszindulatú alkalmazások ezt arra használhatják, hogy a helyére vonatkozó információkat küldjenek tetszőleges webhelyeknek."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"csomagok ellenőrzése"</string> diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml index f0bee2b310b4..97e9ffc11c9c 100644 --- a/core/res/res/values-hy-rAM/strings.xml +++ b/core/res/res/values-hy-rAM/strings.xml @@ -1001,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Թույլ է տալիս հավելվածին սահմանել զարթուցիչի ծրագրում տեղադրված ազդանշանը: Զարթուցիչի որոշ հավելվածներ չեն կարող կիրառել այս հատկությունը:"</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"ավելացնել ձայնային փոստ"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Թույլ է տալիս հավելվածին ավելացնել հաղորդագրություններ ձեր ձայնային փոստի արկղում:"</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"փոփոխել դիտարկչի աշխարհագրական տեղանքի թույլտվությունները"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Թույլ է տալիս հավելվածին փոփոխել զննարկչի աշխարհագրական դիրքի թույլտվությունները: Վնասարար հավելվածները կարող են օգտագործել սա` թույլատրելու ուղարկել տեղադրության վերաբերյալ տեղեկությունները կամայական վեբ կայքերին:"</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"հաստատել փաթեթները"</string> @@ -1362,10 +1366,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"Ծրագրին թույլ է տալիս լսել վստահության կարգավիճակի փոփոխությունները:"</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Տրամադրել վստահելի գործակալ:"</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Ծրագրին թույլ է տալիս տրամադրել վստահելի գործակալ:"</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Գործարկել վստահելի գործակալի կարգավորումների ցանկը:"</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Ծրագրին թույլ է տալիս իրականացնել այնպիսի գործունեություն, որը փոխում է վստահելի գործակալի վարքագիծը:"</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Կապվել վստահելի գործակալի ծառայությանը"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Ծրագրին թույլ է տալիս կապվել վստահելի գործակալի ծառայությանը:"</string> <string name="permlab_recovery" msgid="3157024487744125846">"Փոխազդել թարմացման և վերականգնման համակարգի հետ"</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 9dca8a5771d2..1c804306dc00 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Mengizinkan apl menyetel alarm di apl jam alarm yang terpasang. Beberapa apl jam alarm mungkin tidak menerapkan fitur ini."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"tambahkan kotak pesan"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Mengizinkan apl menambahkan pesan ke kotak masuk untuk pesan suara Anda."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"baca semua kotak pesan"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Mengizinkan aplikasi membaca semua kotak pesan Anda."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"memodifikasi izin geolokasi Browser"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Mengizinkan apl memodifikasi izin geolokasi Browser. Apl berbahaya dapat menggunakan izin ini untuk memungkinkan pengiriman informasi lokasi ke sembarang situs web."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"verifikasi paket"</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 0ea6f6ee15ab..d7b7748bb444 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Consente all\'applicazione di impostare un allarme in un\'applicazione sveglia installata. È possibile che alcune applicazioni sveglia non possano implementare questa funzione."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"aggiunta di un messaggio vocale"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Consente all\'applicazione di aggiungere messaggi alla casella della segreteria."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"accesso alla segreteria"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Consente all\'app di accedere alla segreteria."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"modifica delle autorizzazioni di localizzazione geografica del browser"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Consente all\'applicazione di modificare le autorizzazioni di geolocalizzazione del Browser. Le applicazioni dannose potrebbero farne uso per consentire l\'invio di informazioni sulla posizione a siti web arbitrari."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"verifica dei pacchetti"</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 19fb05aea8b4..8b33339bdaf4 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"מאפשר לאפליקציה להגדיר התראה באפליקציה מותקנת של שעון מעורר. אפליקציות מסוימות של שעון מעורר אינן מיישמות תכונה זו."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"הוסף דואר קולי"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"מאפשר לאפליקציה להוסיף הודעות לתיבת הדואר הקולי."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"קריאת כל הדואר הקולי"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"מאפשרת לאפליקציה לקרוא את כל הודעות הדואר הקולי שלך."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"שינוי הרשאות המיקום הגיאוגרפי של הדפדפן"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"מאפשר לאפליקציה לשנות את הרשאות המיקום הגיאוגרפי של הדפדפן. אפליקציות זדוניות עלולות להשתמש בכך כדי לאפשר משלוח של פרטי מיקום לאתרים זדוניים אחרים."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"אימות חבילות"</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 6ba99bfbdc20..a4b95a6b87f6 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -1001,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"インストール済みアラームアプリのアラームを設定することをアプリに許可します。この機能が実装されていないアラームアプリもあります。"</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"ボイスメールの追加"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"ボイスメール受信トレイにメッセージを追加することをアプリに許可します。"</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ブラウザの現在地情報に対する権限の変更"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ブラウザの現在地情報に対する権限の変更をアプリに許可します。この許可を悪意のあるアプリに利用されると、任意のウェブサイトに現在地情報が送信される恐れがあります。"</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"パッケージのベリファイ"</string> diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml index 879d00fc9ba9..694e1c79a53b 100644 --- a/core/res/res/values-ka-rGE/strings.xml +++ b/core/res/res/values-ka-rGE/strings.xml @@ -401,7 +401,7 @@ <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"ხმის ინტერაქტორთან შეკავშირება"</string> <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"მფლობელს შეეძლება შეკავშირდეს ხმის ინტერაქციის სერვისების ზედა დონის ინტერფეისთან. ჩვეულებრივ აპს ეს წესით არასოდეს უნდა დასჭირდეს."</string> <string name="permlab_manageVoiceKeyphrases" msgid="1252285102392793548">"ხმოვანი საიდუმლო ფრაზების მართვა"</string> - <string name="permdesc_manageVoiceKeyphrases" msgid="8476560722907530008">"საშუალებას აძლევს მფლობელს მართოს საიდუმლო ფრაზები ხმოვანი ჯადოსნური სიტყვის ამოცნობისათვის. ეს ჩვეულებრივ აპებს არ უნდა დაჭირდეს."</string> + <string name="permdesc_manageVoiceKeyphrases" msgid="8476560722907530008">"საშუალებას აძლევს მფლობელს მართოს საიდუმლო ფრაზები ხმოვანი ჯადოსნური სიტყვის ამოცნობისათვის. ეს ჩვეულებრივ აპებს არ უნდა დასჭირდეს."</string> <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"დისტანციურ მონიტორზე მიბმა"</string> <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"მფლობელს შეეძლება მიებას დისტანციურ მონიტორის ზედა დონის ინტერფეისს. ჩვეულებრივ აპს ეს წესით არასოდეს უნდა დაჭირდეს."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ვიჯეტ სერვისთან დაკავშირება"</string> @@ -1001,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"აპს შეეძლება მაღვიძარას დაყენება დაინსტალირებული მაღვიძარას აპლიკაციაში. ამ ფუნქციას მაღვიძარას ზოგიერთი აპი არ იყენებს."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"ხმოვანი ფოსტის დამატება"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"აპს შეეძლება დაამატოს შეტყობინებები თქვენი ხმოვანი ფოსტის შემოსულებში."</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ბრაუზერის გეოლოკაციის უფლებების შეცვლა"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"აპს შეეძლება ბრაუზერის გეოლოკაციის უფლებების შეცვლა. მავნე აპებმა ეს შესაძლოა გამოიყენონ ნებისმიერი ვებსაიტისთვის მდებარეობის შესახებ ინფორმაციის გასაგზავნად."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"პაკეტების გადამოწმება"</string> @@ -1362,10 +1366,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"საშუალებას აძლევს აპლიკაციას მოუსმინოს ცვლილებებს სანდო მდგომარეობაში."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"სანდო აგენტის წარმოდგენა."</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"საშუალებას აძლევს აპლიკაციას წარმოადგინოს სანდო აგენტი."</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"ნდობის აგენტის პარამეტრების მენიუს გამოძახება."</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"საშუალებას აძლევს აპლიკაციას გამოიძახოს აქტივობა, რაც ნდობის აგენტის ქცევას ცვლის."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"სანდო აგენტის სერვისზე მიმაგრება."</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"საშუალებას აძლევს აპლიკაციას მიემაგროს სანდო აგენტის სერვისს."</string> <string name="permlab_recovery" msgid="3157024487744125846">"განახლებასთან და აღდგენის სისტემასთან ინტერაქცია"</string> diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml index daf004c5006e..421ff1035f1f 100644 --- a/core/res/res/values-km-rKH/strings.xml +++ b/core/res/res/values-km-rKH/strings.xml @@ -68,7 +68,7 @@ </plurals> <string name="imei" msgid="2625429890869005782">"IMEI"</string> <string name="meid" msgid="4841221237681254195">"MEID"</string> - <string name="ClipMmi" msgid="6952821216480289285">"លេខសម្គាល់អ្នកហៅចូល"</string> + <string name="ClipMmi" msgid="6952821216480289285">"លេខសម្គាល់អ្នកហៅចូល"</string> <string name="ClirMmi" msgid="7784673673446833091">"លេខសម្គាល់អ្នកហៅចេញ"</string> <string name="CfMmi" msgid="5123218989141573515">"បញ្ជូនការហៅបន្ត"</string> <string name="CwMmi" msgid="9129678056795016867">"រង់ចាំការហៅ"</string> @@ -125,7 +125,7 @@ <string name="cfTemplateRegisteredTime" msgid="6781621964320635172">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> ៖ មិនបានបញ្ជូនបន្ត"</string> <string name="fcComplete" msgid="3118848230966886575">"កូដលក្ខណៈពេញលេញ។"</string> <string name="fcError" msgid="3327560126588500777">"បញ្ហាការតភ្ជាប់ ឬកូដលក្ខណៈមិនត្រឹមត្រូវ។"</string> - <string name="httpErrorOk" msgid="1191919378083472204">"យល់ព្រម"</string> + <string name="httpErrorOk" msgid="1191919378083472204">"យល់ព្រម"</string> <string name="httpError" msgid="7956392511146698522">"មានកំហុសបណ្ដាញ។"</string> <string name="httpErrorLookup" msgid="4711687456111963163">"រកមិនឃើញ URL ។"</string> <string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"គ្រោងការណ៍ផ្ទៀងផ្ទាត់តំបន់បណ្ដាញមិនត្រូវបានគាំទ្រ។"</string> @@ -183,7 +183,7 @@ <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"បើកសំឡេង"</string> <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"ពេលជិះយន្តហោះ"</string> <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"បានបើករបៀបពេលជិះយន្តហោះ"</string> - <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"បានបិទរបៀបពេលជិះយន្តហោះ"</string> + <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"បានបិទរបៀបពេលជិះយន្តហោះ"</string> <string name="global_action_settings" msgid="1756531602592545966">"ការកំណត់"</string> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string> <string name="safeMode" msgid="2788228061547930246">"របៀបសុវត្ថិភាព"</string> @@ -195,7 +195,7 @@ <string name="permgrouplab_messages" msgid="7521249148445456662">"សាររបស់អ្នក"</string> <string name="permgroupdesc_messages" msgid="7821999071003699236">"អាន និងសរសេរសារ SMS, អ៊ីមែល និងសារផ្សេងៗទៀតរបស់អ្នក។"</string> <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"ព័ត៌មានផ្ទាល់ខ្លួនរបស់អ្នក"</string> - <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"ចូលដំណើរការព័ត៌មានដោយផ្ទាល់អំពីអ្នក ដែលបានរក្សាទុកក្នុងកាតទំនាក់ទំនងរបស់អ្នក។"</string> + <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"ចូលដំណើរការព័ត៌មានដោយផ្ទាល់អំពីអ្នក ដែលបានរក្សាទុកក្នុងកាតទំនាក់ទំនងរបស់អ្នក។"</string> <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"ព័ត៌មានសង្គមរបស់អ្នក"</string> <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"ចូលដំណើរការព័ត៌មានដោយផ្ទាល់អំពីទំនាក់ទំនង និងការភ្ជាប់សង្គមរបស់អ្នក។"</string> <string name="permgrouplab_location" msgid="635149742436692049">"ទីតាំងរបស់អ្នក"</string> @@ -384,7 +384,7 @@ <string name="permdesc_readInputState" msgid="8387754901688728043">"ឲ្យកម្មវិធីមើលគ្រាប់ចុចដែលអ្នកចុចពេលមានអន្តរកម្មជាមួយកម្មវិធីផ្សេង (ដូចជា បញ្ចូលពាក្យសម្ងាត់)។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string> <string name="permlab_bindInputMethod" msgid="3360064620230515776">"ចងទៅវិធីសាស្ត្របញ្ចូល"</string> <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"ឲ្យម្ចាស់ចងចំណុចប្រទាក់កម្រិតកំពូលនៃវិធីសាស្ត្របញ្ចូល។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string> - <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"ចងសេវាកម្មភាពមធ្យោបាយងាយស្រួល"</string> + <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"ចងសេវាកម្មភាពមធ្យោបាយងាយស្រួល"</string> <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"ឲ្យម្ចាស់ចងចំណុចប្រទាក់កម្រិតកំពូលនៃសេវាកម្មភាពងាយស្រួល។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string> <string name="permlab_bindPrintService" msgid="8462815179572748761">"ចងសេវាកម្មបោះពុម្ព"</string> <string name="permdesc_bindPrintService" msgid="7960067623209111135">"ឲ្យម្ចាស់ចងចំណុចប្រទាក់កម្រិតកំពូលនៃសេវាកម្មធាតុក្រាហ្វិក។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string> @@ -404,7 +404,7 @@ <string name="permdesc_manageVoiceKeyphrases" msgid="8476560722907530008">"អនុញ្ញាតឲ្យម្ចាស់គ្រប់គ្រងឃ្លាសម្រាប់ការរកឃើញពាក្យជាសំឡេង។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string> <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"ភ្ជាប់ទៅការបង្ហាញពីចម្ងាយ"</string> <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"អនុញ្ញាតឲ្យម្ចាស់ភ្ជាប់ទៅចំណុចប្រទាក់កម្រិតកំពូលនៃការបង្ហាញពីចម្ងាយ។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string> - <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ចងសេវាកម្មធាតុក្រាហ្វិក"</string> + <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ចងសេវាកម្មធាតុក្រាហ្វិក"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ឲ្យម្ចាស់ចងចំណុចប្រទាក់កម្រិតកំពូលនៃសេវាកម្មធាតុក្រាហ្វិក។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string> <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"ភ្ជាប់ទៅសេវាកម្មក្រុមហ៊ុនផ្ដល់ច្រក"</string> <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"អនុញ្ញាតឲ្យម្ចាស់ភ្ជាប់ទៅក្រុមហ៊ុនផ្ដល់ច្រកដែលបានចុះឈ្មោះ។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string> @@ -412,7 +412,7 @@ <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"ឲ្យម្ចាស់ផ្ញើគោលបំណងទៅអ្នកគ្រប់គ្រងឧបករណ៍។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string> <string name="permlab_bindTvInput" msgid="5601264742478168987">"ភ្ជាប់ទៅការបញ្ចូលទូរទស្សន៍"</string> <string name="permdesc_bindTvInput" msgid="2371008331852001924">"អនុញ្ញាតឲ្យម្ចាស់ភ្ជាប់ទៅចំណុចប្រទាក់កម្រិតខ្ពស់នៃការបញ្ចូលទូរទស្សន៍។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string> - <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"បន្ថែម ឬលុបកម្មវិធីគ្រប់គ្រងឧបករណ៍"</string> + <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"បន្ថែម ឬលុបកម្មវិធីគ្រប់គ្រងឧបករណ៍"</string> <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"អនុញ្ញាតឲ្យម្ចាស់បន្ថែម ឬលុបកម្មវិធីគ្រប់គ្រងឧបករណ៍សកម្មចេញ។ មិនគួរប្រើសម្រាប់កម្មវិធីធម្មតាទេ។"</string> <string name="permlab_setOrientation" msgid="3365947717163866844">"ប្ដូរទិសអេក្រង់"</string> <string name="permdesc_setOrientation" msgid="3046126619316671476">"ឲ្យកម្មវិធីប្ដូរការបង្វិលអេក្រង់នៅពេលណាមួយ។ មិនចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string> @@ -424,9 +424,9 @@ <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"ឲ្យកម្មវិធីស្នើសញ្ញាដែលបានផ្ដល់ត្រូវផ្ញើទៅដំណើរការស្ថិតស្ថេរទាំងអស់។"</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"ធ្វើឲ្យកម្មវិធីដំណើរការជានិច្ច"</string> <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"ឲ្យកម្មវិធីធ្វើជាផ្នែកស្ថិតស្ថេរដោយខ្លួនឯងក្នុងអង្គចងចាំ។ វាអាចកំណត់អង្គចងចាំដែលអាចប្រើបានចំពោះកម្មវិធីផ្សេងៗ ដោយធ្វើឲ្យកុំព្យូទ័របន្ទះយឺត។"</string> - <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"ឲ្យកម្មវិធី ធ្វើជាផ្នែកអចិន្ត្រៃយ៍នៃខ្លួនក្នុងអង្គចងចាំ។ វាអាចកម្រិតអង្គចងចាំអាចប្រើបាន ដើម្បីធ្វើឲ្យកម្មវិធីផ្សេងធ្វើឲ្យទូរស័ព្ទរបស់អ្នកយឺត។"</string> + <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"ឲ្យកម្មវិធី ធ្វើជាផ្នែកអចិន្ត្រៃយ៍នៃខ្លួនក្នុងអង្គចងចាំ។ វាអាចកម្រិតអង្គចងចាំអាចប្រើបាន ដើម្បីធ្វើឲ្យកម្មវិធីផ្សេងធ្វើឲ្យទូរស័ព្ទរបស់អ្នកយឺត។"</string> <string name="permlab_deletePackages" msgid="184385129537705938">"លុបកម្មវិធី"</string> - <string name="permdesc_deletePackages" msgid="7411480275167205081">"ឲ្យកម្មវិធីលុបកញ្ចប់ Android ។ កម្មវិធីព្យាបាទអាចប្រើវា ដើម្បីលុបកម្មវិធីសំខាន់ៗ។ "</string> + <string name="permdesc_deletePackages" msgid="7411480275167205081">"ឲ្យកម្មវិធីលុបកញ្ចប់ Android ។ កម្មវិធីព្យាបាទអាចប្រើវា ដើម្បីលុបកម្មវិធីសំខាន់ៗ។"</string> <string name="permlab_clearAppUserData" msgid="274109191845842756">"លុបទិន្នន័យរបស់កម្មវិធីផ្សេង"</string> <string name="permdesc_clearAppUserData" msgid="4625323684125459488">"ឲ្យកម្មវិធីសម្អាតទិន្នន័យអ្នកប្រើ។"</string> <string name="permlab_deleteCacheFiles" msgid="3128665571837408675">"លុបឃ្លាំងសម្ងាត់កម្មវិធីផ្សេងៗ"</string> @@ -477,7 +477,7 @@ <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"ឲ្យកម្មវិធីកែទិន្នន័យអំពីទំនាក់ទំនងរបស់អ្នកដែលបានរក្សាទុកក្នុងកុំព្យូទ័របន្ទះ រួមមានប្រេកង់ដែលអ្នកបានហៅ អ៊ីមែល ឬទាក់ទងតាមវិធីផ្សេងៗជាមួយទំនាក់ទំនងជាក់លាក់។ សិទ្ធិនេះអនុញ្ញាតឲ្យកម្មវិធីលុបទិន្នន័យទំនាក់ទំនងរបស់អ្នក។"</string> <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"ឲ្យកម្មវិធីកែទិន្នន័យអំពីទំនាក់ទំនងរបស់អ្នកដែលបានរក្សាទុកក្នុងទូរស័ព្ទរបស់អ្នក រួមមានប្រេកង់ដែលអ្នកបានហៅ អ៊ីមែល ឬបានទាក់ទងតាមវិធីផ្សេងៗជាមួយទំនាក់ទំនាក់ជាក់លាក់។ សិទ្ធិនេះឲ្យកម្មវិធីលុបទិន្នន័យទំនាក់ទំនង។"</string> <string name="permlab_readCallLog" msgid="3478133184624102739">"អានកំណត់ហេតុហៅ"</string> - <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"ឲ្យកម្មវិធីអានបញ្ជីហៅកុំព្យូទ័របន្ទះរបស់អ្នក រួមមានទិន្នន័យអំពីការហៅចូល និងចេញ។ សិទ្ធិនេះអនុញ្ញាតឲ្យកម្មវិធីរក្សាទុកទិន្នន័យបញ្ជីហៅរបស់អ្នក ហើយកម្មវិធីព្យាបាទអាចចែករំលែកទិន្នន័យបញ្ជីហៅដោយមិនឲ្យអ្នកដឹង។"</string> + <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"ឲ្យកម្មវិធីអានបញ្ជីហៅកុំព្យូទ័របន្ទះរបស់អ្នក រួមមានទិន្នន័យអំពីការហៅចូល និងចេញ។ សិទ្ធិនេះអនុញ្ញាតឲ្យកម្មវិធីរក្សាទុកទិន្នន័យបញ្ជីហៅរបស់អ្នក ហើយកម្មវិធីព្យាបាទអាចចែករំលែកទិន្នន័យបញ្ជីហៅដោយមិនឲ្យអ្នកដឹង។"</string> <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"ឲ្យកម្មវិធីអានបញ្ជីហៅទូរស័ព្ទរបស់អ្នក រួមមានទិន្នន័យអំពីការហៅចូល និងចេញ។ សិទ្ធិនេះអនុញ្ញាតឲ្យកម្មវិធីរក្សាទុកទិន្នន័យបញ្ជីហៅរបស់អ្នក ហើយកម្មវិធីព្យាបាទអាចចែករំលែកទិន្នន័យបញ្ជីហៅដោយមិនឲ្យអ្នកដឹង។"</string> <string name="permlab_writeCallLog" msgid="8552045664743499354">"សរសេរបញ្ជីហៅ"</string> <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"ឲ្យកម្មវិធីកែបញ្ជីហៅកុំព្យូទ័របន្ទះរបស់អ្នករួមមានទិន្នន័យអំពីការហៅចូល និងចេញ។កម្មវិធីព្យាបាទអាចប្រើវា ដើម្បីលុប ឬកែបញ្ជីហៅរបស់អ្នក។"</string> @@ -613,7 +613,7 @@ <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"ឲ្យកម្មវិធីកំណត់ជំនួយទំហំផ្ទាំងរូបភាពប្រព័ន្ធ។"</string> <string name="permlab_masterClear" msgid="2315750423139697397">"កំណត់ប្រព័ន្ធទៅលំនាំដើមរោងចក្រឡើងវិញ"</string> <string name="permdesc_masterClear" msgid="3665380492633910226">"ឲ្យកម្មវិធីកំណត់ប្រព័ន្ធដូចការកំណត់ចេញពីរោងចក្រឡើងវិញពេញលេញ ដោយលុបទិន្នន័យ ការកំណត់រចនាសម្ព័ន្ធ និងកម្មវិធីបានដំឡើង។"</string> - <string name="permlab_setTime" msgid="2021614829591775646">"កំណត់ម៉ោង"</string> + <string name="permlab_setTime" msgid="2021614829591775646">"កំណត់ម៉ោង"</string> <string name="permdesc_setTime" product="tablet" msgid="1896341438151152881">"ឲ្យកម្មវិធីប្ដូរម៉ោងកុំព្យូទ័របន្ទះ។"</string> <string name="permdesc_setTime" product="default" msgid="1855702730738020">"ឲ្យកម្មវិធីប្ដូរម៉ោងទូរស័ព្ទ។"</string> <string name="permlab_setTimeZone" msgid="2945079801013077340">"កំណត់តំបន់ពេលវេលា"</string> @@ -779,7 +779,7 @@ <string-array name="organizationTypes"> <item msgid="7546335612189115615">"កន្លែងធ្វើការ"</item> <item msgid="4378074129049520373">"ផ្សេងៗ"</item> - <item msgid="3455047468583965104">"តាមតម្រូវការ"</item> + <item msgid="3455047468583965104">"តាមតម្រូវការ"</item> </string-array> <string-array name="imProtocols"> <item msgid="8595261363518459565">"AIM"</item> @@ -795,7 +795,7 @@ <string name="phoneTypeHome" msgid="2570923463033985887">"ផ្ទះ"</string> <string name="phoneTypeMobile" msgid="6501463557754751037">"ចល័ត"</string> <string name="phoneTypeWork" msgid="8863939667059911633">"កន្លែងធ្វើការ"</string> - <string name="phoneTypeFaxWork" msgid="3517792160008890912">"ទូរសារកន្លែងធ្វើការ"</string> + <string name="phoneTypeFaxWork" msgid="3517792160008890912">"ទូរសារកន្លែងធ្វើការ"</string> <string name="phoneTypeFaxHome" msgid="2067265972322971467">"ទូរសារផ្ទះ"</string> <string name="phoneTypePager" msgid="7582359955394921732">"ភេយ័រ"</string> <string name="phoneTypeOther" msgid="1544425847868765990">"ផ្សេងៗ"</string> @@ -920,7 +920,7 @@ <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"ព្យាយាមលំនាំច្រើនពេក"</string> <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"ដើម្បីដោះសោ ចូលគណនី Google របស់អ្នក។"</string> <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"ឈ្មោះអ្នកប្រើ (អ៊ីមែល)"</string> - <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"ពាក្យសម្ងាត់"</string> + <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"ពាក្យសម្ងាត់"</string> <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"ចូល"</string> <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"ឈ្មោះអ្នកប្រើ ឬពាក្យសម្ងាត់មិនត្រឹមត្រូវ។"</string> <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"ភ្លេចឈ្មោះអ្នកប្រើ ឬពាក្យសម្ងាត់របស់អ្នក?\nមើល "<b>"google.com/accounts/recovery"</b>" ។"</string> @@ -965,7 +965,7 @@ <string name="factorytest_failed" msgid="5410270329114212041">"បានបរាជ័យក្នុងការសាកល្បងរោងចក្រ"</string> <string name="factorytest_not_system" msgid="4435201656767276723">"សកម្មភាព FACTORY_TEST ត្រូវបានគាំទ្រសម្រាប់តែកញ្ចប់បានដំឡើងក្នុង /system/app."</string> <string name="factorytest_no_action" msgid="872991874799998561">"រកមិនឃើញកញ្ចប់ដែលផ្ដល់សកម្មភាព FACTORY_TEST ។"</string> - <string name="factorytest_reboot" msgid="6320168203050791643">"ចាប់ផ្ដើមឡើងវិញ"</string> + <string name="factorytest_reboot" msgid="6320168203050791643">"ចាប់ផ្ដើមឡើងវិញ"</string> <string name="js_dialog_title" msgid="1987483977834603872">"ទំព័រមានចំណងជើង \"<xliff:g id="TITLE">%s</xliff:g>\" សរសេរ៖"</string> <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string> <string name="js_dialog_before_unload_title" msgid="2619376555525116593">"បញ្ជាក់ការរុករក"</string> @@ -1001,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"ឲ្យកម្មវិធីកំណត់សំឡេងរោទ៍ក្នុងកម្មវិធីនាឡិការោទ៍បានដំឡើង។ កម្មវិធីនាឡិការោទ៍មួយចំនួនអាចមិនអនុវត្តលក្ខណៈនេះ។"</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"បន្ថែមសារជាសំឡេង"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"ឲ្យកម្មវិធីបន្ថែមសារទៅប្រអប់ទទួលសារជាសំឡេងរបស់អ្នក។"</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"កែសិទ្ធិទីតាំងភូមិសាស្ត្ររបស់កម្មវិធីអ៊ីនធឺណិត"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ឲ្យកម្មវិធីកែសិទ្ធិទីតាំងភូមិសាស្ត្ររបស់កម្មវិធីអ៊ីនធឺណិត។ កម្មវិធីព្យាបាទអាចប្រើវា ដើម្បីឲ្យផ្ញើព័ត៌មានទីតាំងទៅតំបន់បណ្ដាញដោយបំពាន។"</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"ផ្ទៀងផ្ទាត់កញ្ចប់"</string> @@ -1023,7 +1027,7 @@ <string name="prepend_shortcut_label" msgid="2572214461676015642">"ម៉ឺនុយ +"</string> <string name="menu_space_shortcut_label" msgid="2410328639272162537">"ដកឃ្លា"</string> <string name="menu_enter_shortcut_label" msgid="2743362785111309668">"enter"</string> - <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"លុប"</string> + <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"លុប"</string> <string name="search_go" msgid="8298016669822141719">"ស្វែងរក"</string> <string name="searchview_description_search" msgid="6749826639098512120">"ស្វែងរក"</string> <string name="searchview_description_query" msgid="5911778593125355124">"ស្វែងរកសំណួរ"</string> @@ -1107,18 +1111,18 @@ <string name="preposition_for_date" msgid="9093949757757445117">"នៅ <xliff:g id="DATE">%s</xliff:g>"</string> <string name="preposition_for_time" msgid="5506831244263083793">"នៅម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string> <string name="preposition_for_year" msgid="5040395640711867177">"ក្នុងឆ្នាំ <xliff:g id="YEAR">%s</xliff:g>"</string> - <string name="day" msgid="8144195776058119424">"ថ្ងៃ"</string> + <string name="day" msgid="8144195776058119424">"ថ្ងៃ"</string> <string name="days" msgid="4774547661021344602">"ថ្ងៃ"</string> <string name="hour" msgid="2126771916426189481">"ម៉ោង"</string> <string name="hours" msgid="894424005266852993">"ម៉ោង"</string> - <string name="minute" msgid="9148878657703769868">"នាទី"</string> + <string name="minute" msgid="9148878657703769868">"នាទី"</string> <string name="minutes" msgid="5646001005827034509">"នាទី"</string> - <string name="second" msgid="3184235808021478">"វិនាទី"</string> + <string name="second" msgid="3184235808021478">"វិនាទី"</string> <string name="seconds" msgid="3161515347216589235">"វិនាទី"</string> - <string name="week" msgid="5617961537173061583">"សប្ដាហ៍"</string> - <string name="weeks" msgid="6509623834583944518">"សប្ដាហ៍"</string> - <string name="year" msgid="4001118221013892076">"ឆ្នាំ"</string> - <string name="years" msgid="6881577717993213522">"ឆ្នាំ"</string> + <string name="week" msgid="5617961537173061583">"សប្ដាហ៍"</string> + <string name="weeks" msgid="6509623834583944518">"សប្ដាហ៍"</string> + <string name="year" msgid="4001118221013892076">"ឆ្នាំ"</string> + <string name="years" msgid="6881577717993213522">"ឆ្នាំ"</string> <plurals name="duration_seconds"> <item quantity="one" msgid="6962015528372969481">"1 វិនាទី"</item> <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> វិនាទី"</item> @@ -1134,12 +1138,12 @@ <string name="VideoView_error_title" msgid="3534509135438353077">"បញ្ហាវីដេអូ"</string> <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"វីដេអូនេះមិនត្រឹមត្រូវសម្រាប់ចរន្តចូលឧបករណ៍នេះ។"</string> <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"មិនអាចចាក់វីដេអូនេះ។"</string> - <string name="VideoView_error_button" msgid="2822238215100679592">"យល់ព្រម"</string> + <string name="VideoView_error_button" msgid="2822238215100679592">"យល់ព្រម"</string> <string name="relative_time" msgid="1818557177829411417">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="noon" msgid="7245353528818587908">"រសៀល"</string> <string name="Noon" msgid="3342127745230013127">"រសៀល"</string> <string name="midnight" msgid="7166259508850457595">"កណ្ដាលអធ្រាត្រ"</string> - <string name="Midnight" msgid="5630806906897892201">"កណ្ដាលអធ្រាត្រ"</string> + <string name="Midnight" msgid="5630806906897892201">"កណ្ដាលអធ្រាត្រ"</string> <string name="elapsed_time_short_format_mm_ss" msgid="4431555943828711473">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string> <string name="elapsed_time_short_format_h_mm_ss" msgid="1846071997616654124">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string> <string name="selectAll" msgid="6876518925844129331">"ជ្រើសទាំងអស់"</string> @@ -1156,13 +1160,13 @@ <string name="inputMethod" msgid="1653630062304567879">"វិធីសាស្ត្របញ្ចូល"</string> <string name="editTextMenuTitle" msgid="4909135564941815494">"សកម្មភាពអត្ថបទ"</string> <string name="low_internal_storage_view_title" msgid="5576272496365684834">"អស់ទំហំផ្ទុក"</string> - <string name="low_internal_storage_view_text" msgid="6640505817617414371">"មុខងារប្រព័ន្ធមួយចំនួនអាចមិនដំណើរការ"</string> + <string name="low_internal_storage_view_text" msgid="6640505817617414371">"មុខងារប្រព័ន្ធមួយចំនួនអាចមិនដំណើរការ"</string> <string name="app_running_notification_title" msgid="8718335121060787914">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងដំណើរការ"</string> <string name="app_running_notification_text" msgid="4653586947747330058">"ប៉ះ ដើម្បីមើលព័ត៌មានបន្ថែម ឬបញ្ឈប់កម្មវិធី។"</string> - <string name="ok" msgid="5970060430562524910">"យល់ព្រម"</string> - <string name="cancel" msgid="6442560571259935130">"បោះបង់"</string> - <string name="yes" msgid="5362982303337969312">"យល់ព្រម"</string> - <string name="no" msgid="5141531044935541497">"បោះបង់"</string> + <string name="ok" msgid="5970060430562524910">"យល់ព្រម"</string> + <string name="cancel" msgid="6442560571259935130">"បោះបង់"</string> + <string name="yes" msgid="5362982303337969312">"យល់ព្រម"</string> + <string name="no" msgid="5141531044935541497">"បោះបង់"</string> <string name="dialog_alert_title" msgid="2049658708609043103">"ប្រយ័ត្ន"</string> <string name="loading" msgid="7933681260296021180">"កំពុងផ្ទុក..."</string> <string name="capital_on" msgid="1544682755514494298">"បើក"</string> @@ -1171,7 +1175,7 @@ <string name="whichHomeApplication" msgid="4616420172727326782">"ជ្រើសកម្មវិធីដើម"</string> <string name="alwaysUse" msgid="4583018368000610438">"ប្រើតាមលំនាំដើមសម្រាប់សកម្មភាពនេះ។"</string> <string name="clearDefaultHintMsg" msgid="3252584689512077257">"សម្អាតលំនាំដើមក្នុងការកំណត់ប្រព័ន្ធ > កម្មវិធី > ទាញយក។"</string> - <string name="chooseActivity" msgid="7486876147751803333">"ជ្រើសសកម្មភាព"</string> + <string name="chooseActivity" msgid="7486876147751803333">"ជ្រើសសកម្មភាព"</string> <string name="chooseUsbActivity" msgid="6894748416073583509">"ជ្រើសកម្មវិធីសម្រាប់ឧបករណ៍យូអេសប៊ី"</string> <string name="noApplications" msgid="2991814273936504689">"គ្មានកម្មវិធីអាចអនុវត្តសកម្មភាពនេះ។"</string> <string name="aerr_title" msgid="1905800560317137752"></string> @@ -1182,7 +1186,7 @@ <string name="anr_activity_process" msgid="5776209883299089767">"សកម្មភាព <xliff:g id="ACTIVITY">%1$s</xliff:g> មិនឆ្លើយតប។\n\nតើអ្នកចង់បិទវា?"</string> <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> មិនឆ្លើយតប។ តើអ្នកចង់បិទវា?"</string> <string name="anr_process" msgid="6513209874880517125">"ដំណើរការ <xliff:g id="PROCESS">%1$s</xliff:g> មិនឆ្លើយតប។ \n\nតើអ្នកចង់បិទវាឬ?"</string> - <string name="force_close" msgid="8346072094521265605">"យល់ព្រម"</string> + <string name="force_close" msgid="8346072094521265605">"យល់ព្រម"</string> <string name="report" msgid="4060218260984795706">"រាយការណ៍"</string> <string name="wait" msgid="7147118217226317732">"រង់ចាំ"</string> <string name="webpage_unresponsive" msgid="3272758351138122503">"ទំព័រក្លាយជាមិនឆ្លើយតប។\n\nតើអ្នកចង់បិទវា?"</string> @@ -1264,19 +1268,19 @@ <string name="sms_short_code_details" msgid="3492025719868078457"><font fgcolor="#ffffb060">"នេះអាចកាត់លុយ"</font>" លើគណនីចល័តរបស់អ្នក។"</string> <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"វានឹងគិតថ្លៃសេវាកម្មលើគណនីចល័តរបស់អ្នក។"</font></string> <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"ផ្ញើ"</string> - <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"បោះបង់"</string> + <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"បោះបង់"</string> <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"ចងចាំជម្រើសរបស់ខ្ញុំ"</string> <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"អ្នកអាចប្ដូរវាពេលក្រោយក្នុងការកំណត់ > កម្មវិធី"</string> <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"អនុញ្ញាតជានិច្ច"</string> <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"កុំអនុញ្ញាត"</string> <string name="sim_removed_title" msgid="6227712319223226185">"បានដកស៊ីមកាតចេញ"</string> - <string name="sim_removed_message" msgid="2333164559970958645">"បណ្ដាញចល័តនឹងប្រើលែងបានរហូតដល់អ្នកចាប់ផ្ដើមជាមួយស៊ីមកាតដែលបាបញ្ចូលត្រឹមត្រូវ។"</string> + <string name="sim_removed_message" msgid="2333164559970958645">"បណ្ដាញចល័តនឹងប្រើលែងបានរហូតដល់អ្នកចាប់ផ្ដើមជាមួយស៊ីមកាតដែលបាបញ្ចូលត្រឹមត្រូវ។"</string> <string name="sim_done_button" msgid="827949989369963775">"រួចរាល់"</string> <string name="sim_added_title" msgid="3719670512889674693">"បានបន្ថែមស៊ីមកាត"</string> <string name="sim_added_message" msgid="6599945301141050216">"ចាប់ផ្ដើមឧបករណ៍របស់អ្នកឡើងវិញ ដើម្បីចូលដំណើរការបណ្ដាញចល័ត។"</string> <string name="sim_restart_button" msgid="4722407842815232347">"ចាប់ផ្ដើមឡើងវិញ"</string> - <string name="time_picker_dialog_title" msgid="8349362623068819295">"កំណត់ម៉ោង"</string> - <string name="date_picker_dialog_title" msgid="5879450659453782278">"កំណត់កាលបរិច្ឆេទ"</string> + <string name="time_picker_dialog_title" msgid="8349362623068819295">"កំណត់ម៉ោង"</string> + <string name="date_picker_dialog_title" msgid="5879450659453782278">"កំណត់កាលបរិច្ឆេទ"</string> <string name="date_time_set" msgid="5777075614321087758">"កំណត់"</string> <string name="date_time_done" msgid="2507683751759308828">"រួចរាល់"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"ថ្មី៖ "</font></string> @@ -1354,7 +1358,7 @@ <string name="permdesc_copyProtectedData" msgid="4390697124288317831">"ឲ្យកម្មវិធីដកសេវាកម្មនៃកម្មវិធីផ្ទុកលំនាំដើម ដើម្បីចម្លងមាតិកា។ មិនសម្រាប់ប្រើដោយកម្មវិធីលំនាំដើម។"</string> <string name="permlab_route_media_output" msgid="1642024455750414694">"នាំផ្លូវលទ្ធផលមេឌៀ"</string> <string name="permdesc_route_media_output" msgid="4932818749547244346">"ឲ្យកម្មវិធីនាំផ្លូវលទ្ធផលមេឌៀទៅឧបករណ៍ខាងក្រៅផ្សេង។"</string> - <string name="permlab_access_keyguard_secure_storage" msgid="7565552237977815047">"ចូលដំណើរការឧបករណ៍ផ្ទុកសុវត្ថិភាព"</string> + <string name="permlab_access_keyguard_secure_storage" msgid="7565552237977815047">"ចូលដំណើរការឧបករណ៍ផ្ទុកសុវត្ថិភាព"</string> <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"ឲ្យកម្មវិធីចូលការផ្ទុកមានសុវត្ថិភាព keguard ។"</string> <string name="permlab_control_keyguard" msgid="172195184207828387">"ពិនិត្យការបង្ហាញ និងលាក់ការការពារ"</string> <string name="permdesc_control_keyguard" msgid="3043732290518629061">"ឲ្យកម្មវិធីគ្រប់គ្រង keguard ។"</string> @@ -1373,7 +1377,7 @@ <string name="ime_action_go" msgid="8320845651737369027">"ទៅ"</string> <string name="ime_action_search" msgid="658110271822807811">"ស្វែងរក"</string> <string name="ime_action_send" msgid="2316166556349314424">"ផ្ញើ"</string> - <string name="ime_action_next" msgid="3138843904009813834">"បន្ទាប់"</string> + <string name="ime_action_next" msgid="3138843904009813834">"បន្ទាប់"</string> <string name="ime_action_done" msgid="8971516117910934605">"រួចរាល់"</string> <string name="ime_action_previous" msgid="1443550039250105948">"មុន"</string> <string name="ime_action_default" msgid="2840921885558045721">"អនុវត្ត"</string> @@ -1382,7 +1386,7 @@ <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"កម្មវិធីមួយ ឬច្រើនដូចខាងក្រោមស្នើសិទ្ធិ ដើម្បីចូលគណនីរបស់អ្នកឥឡូវ និងពេលអនាគត។"</string> <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"តើអ្នកចង់អនុញ្ញាតសំណើនេះ?"</string> <string name="grant_permissions_header_text" msgid="6874497408201826708">"ស្នើចូល"</string> - <string name="allow" msgid="7225948811296386551">"អនុញ្ញាត"</string> + <string name="allow" msgid="7225948811296386551">"អនុញ្ញាត"</string> <string name="deny" msgid="2081879885755434506">"បដិសេធ"</string> <string name="permission_request_notification_title" msgid="6486759795926237907">"បានស្នើសិទ្ធិ"</string> <string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">"បានស្នើសិទ្ធិ\nសម្រាប់គណនី <xliff:g id="ACCOUNT">%s</xliff:g> ។"</string> @@ -1405,12 +1409,12 @@ <string name="no_file_chosen" msgid="6363648562170759465">"គ្មានឯកសារបានជ្រើស"</string> <string name="reset" msgid="2448168080964209908">"កំណត់ឡើងវិញ"</string> <string name="submit" msgid="1602335572089911941">"ដាក់ស្នើ"</string> - <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"បានបើករបៀបរថយន្ត"</string> + <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"បានបើករបៀបរថយន្ត"</string> <string name="car_mode_disable_notification_message" msgid="8035230537563503262">"ប៉ះ ដើម្បីចេញពីរបៀបរថយន្ត។"</string> <string name="tethered_notification_title" msgid="3146694234398202601">"ភ្ជាប់ ឬហតស្ពតសកម្ម"</string> <string name="tethered_notification_message" msgid="6857031760103062982">"ប៉ះ ដើម្បីរៀបចំ។"</string> <string name="back_button_label" msgid="2300470004503343439">"ថយក្រោយ"</string> - <string name="next_button_label" msgid="1080555104677992408">"បន្ទាប់"</string> + <string name="next_button_label" msgid="1080555104677992408">"បន្ទាប់"</string> <string name="skip_button_label" msgid="1275362299471631819">"រំលង"</string> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"ការប្រើទិន្នន័យចល័តខ្ពស់"</string> <string name="throttle_warning_notification_message" msgid="3340822228599337743">"ប៉ះ ដើម្បីស្វែងយល់បន្ថែមអំពីការប្រើទិន្នន័យចល័ត។"</string> @@ -1436,7 +1440,7 @@ <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"ឧបករណ៍ផ្ទុកយូអេសប៊ីបច្ចុប្បន្នកំពុងប្រើដោយកុំព្យូទ័រ។"</string> <string name="media_shared" product="default" msgid="5706130568133540435">"បច្ចុប្បន្នកាតអេសឌីកំពុងប្រើដោយកុំព្យូទ័រ"</string> <string name="media_unknown_state" msgid="729192782197290385">"មិនស្គាល់ស្ថានភាពមេឌៀខាងក្រៅ។"</string> - <string name="share" msgid="1778686618230011964">"ចែករំលែក"</string> + <string name="share" msgid="1778686618230011964">"ចែករំលែក"</string> <string name="find" msgid="4808270900322985960">"រក"</string> <string name="websearch" msgid="4337157977400211589">"ស្វែងរកតាមបណ្ដាញ"</string> <string name="find_next" msgid="5742124618942193978">"រកបន្ទាប់"</string> @@ -1452,7 +1456,7 @@ <string name="sync_undo_deletes" msgid="2941317360600338602">"មិនធ្វើការលុបវិញ"</string> <string name="sync_do_nothing" msgid="3743764740430821845">"មិនធ្វើអ្វីទេឥឡូវ"</string> <string name="choose_account_label" msgid="5655203089746423927">"ជ្រើសគណនី"</string> - <string name="add_account_label" msgid="2935267344849993553">"បន្ថែមគណនីថ្មី"</string> + <string name="add_account_label" msgid="2935267344849993553">"បន្ថែមគណនីថ្មី"</string> <string name="add_account_button_label" msgid="3611982894853435874">"បន្ថែមគណនី"</string> <string name="number_picker_increment_button" msgid="2412072272832284313">"បង្កើន"</string> <string name="number_picker_decrement_button" msgid="476050778386779067">"បន្ថយ"</string> @@ -1471,15 +1475,15 @@ <string name="date_picker_increment_year_button" msgid="6318697384310808899">"បង្កើនឆ្នាំ"</string> <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"បន្ថយឆ្នាំ"</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">"ប្ដូររបៀប"</string> <string name="keyboardview_keycode_shift" msgid="2270748814315147690">"Shift"</string> <string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Enter"</string> - <string name="activitychooserview_choose_application" msgid="2125168057199941199">"ជ្រើសកម្មវិធី"</string> + <string name="activitychooserview_choose_application" msgid="2125168057199941199">"ជ្រើសកម្មវិធី"</string> <string name="activitychooserview_choose_application_error" msgid="8624618365481126668">"មិនអាចចាប់ផ្ដើម <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> - <string name="shareactionprovider_share_with" msgid="806688056141131819">"ចែករំលែកជាមួយ"</string> + <string name="shareactionprovider_share_with" msgid="806688056141131819">"ចែករំលែកជាមួយ"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"ចែករំលែកជាមួយ <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"គ្រប់គ្រងការរុញ។ ប៉ះ & សង្កត់។"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"អូស ដើម្បីដោះសោ។"</string> @@ -1493,7 +1497,7 @@ <string name="storage_internal" msgid="4891916833657929263">"ឧបករណ៍ផ្ទុកខាងក្នុង"</string> <string name="storage_sd_card" msgid="3282948861378286745">"កាតអេសឌី"</string> <string name="storage_usb" msgid="3017954059538517278">"ឧបករណ៍ផ្ទុកយូអេសប៊ី"</string> - <string name="extract_edit_menu_button" msgid="8940478730496610137">"កែសម្រួល"</string> + <string name="extract_edit_menu_button" msgid="8940478730496610137">"កែសម្រួល"</string> <string name="data_usage_warning_title" msgid="1955638862122232342">"ការព្រមានប្រើទិន្នន័យ"</string> <string name="data_usage_warning_body" msgid="2814673551471969954">"ប៉ះ ដើម្បីមើលការប្រើ និងការកំណត់។"</string> <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"បានបិទទិន្នន័យ 2G-3G"</string> @@ -1550,7 +1554,7 @@ <string name="media_route_status_available" msgid="6983258067194649391">"ទំនេរ"</string> <string name="media_route_status_not_available" msgid="6739899962681886401">"មិនទំនេរ"</string> <string name="media_route_status_in_use" msgid="4533786031090198063">"កំពុងប្រើ"</string> - <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"អេក្រង់ជាប់"</string> + <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"អេក្រង់ជាប់"</string> <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"អេក្រង់ HDMI"</string> <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"#<xliff:g id="ID">%1$d</xliff:g> ត្រួតគ្នា"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> @@ -1582,7 +1586,7 @@ <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_password_hint" msgid="9057289103827298549">"ពាក្យសម្ងាត់"</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> @@ -1691,7 +1695,7 @@ <string name="mediasize_japanese_you4" msgid="2091777168747058008">"You4"</string> <string name="mediasize_unknown_portrait" msgid="3088043641616409762">"មិនស្គាល់បញ្ឈរ"</string> <string name="mediasize_unknown_landscape" msgid="4876995327029361552">"មិនស្គាល់ទេសភាព"</string> - <string name="write_fail_reason_cancelled" msgid="7091258378121627624">"បានបោះបង់"</string> + <string name="write_fail_reason_cancelled" msgid="7091258378121627624">"បានបោះបង់"</string> <string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"កំហុសក្នុងការសរសេរមាតិកា"</string> <string name="reason_unknown" msgid="6048913880184628119">"មិនស្គាល់"</string> <string name="reason_service_unavailable" msgid="7824008732243903268">"មិនបានបើកសេវាកម្មបោះពុម្ព"</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 43d1b25d0956..cffe6bb36599 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -1001,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"앱이 설치된 알람 시계 앱에서 알람을 설정할 수 있도록 허용합니다. 일부 알람 시계 앱에는 이 기능이 구현되지 않을 수 있습니다."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"음성사서함 추가"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"앱이 음성사서함에 메시지를 추가할 수 있도록 허용합니다."</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"브라우저 위치 정보 권한 수정"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"앱이 브라우저의 위치 정보 권한을 수정할 수 있도록 허용합니다. 이 경우 악성 앱이 이 기능을 이용하여 임의의 웹사이트에 위치 정보를 보낼 수 있습니다."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"패키지 확인"</string> @@ -1362,10 +1366,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"애플리케이션이 Trust 상태에서의 변경사항을 수신할 수 있도록 허용합니다."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Trust Agent 제공"</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"애플리케이션이 Trust Agent를 제공할 수 있도록 허용합니다."</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Trust Agent 설정 메뉴를 실행합니다."</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"애플리케이션에서 Trust Agent의 동작을 변경하는 활동을 실행하도록 허용합니다."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Trust Agent 서비스에 연결"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"애플리케이션이 Trust Agent 서비스에 바인딩할 수 있도록 허용합니다."</string> <string name="permlab_recovery" msgid="3157024487744125846">"업데이트 및 복구 시스템과 상호작용"</string> diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml index e386a247facf..b44c9e09f684 100644 --- a/core/res/res/values-lo-rLA/strings.xml +++ b/core/res/res/values-lo-rLA/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"ອະນຸຍາດໃຫ້ແອັບຯຕັ້ງໂມງປຸກໃນແອັບຯໂມງປຸກທີ່ຕິດຕັ້ງໄວ້. ບາງແອັບຯໂມງປຸກອາດບໍ່ມີຄຸນສົມບັດແບບນີ້ເທື່ອ."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"ເພີ່ມຂໍ້ຄວາມສຽງ"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"ອະນຸຍາດໃຫ້ແອັບຯ ສາມາດເພີ່ມຂໍ້ຄວາມໃສ່ອິນບັອກຂໍ້ຄວາມສຽງຂອງທ່ານໄດ້."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"ອ່ານຂໍ້ຄວາມສຽງທັງໝົດ"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"ອະນຸຍາດໃຫ້ແອັບຯອ່ານຂໍ້ຄວາມສຽງທັງໝົດຂອງທ່ານ."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ແກ້ໄຂສິດທາງສະຖານທີ່ພູມສາດຂອງໂປຣແກຣມທ່ອງເວັບ"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ອະນຸຍາດໃຫ້ແອັບຯແກ້ໄຂ ການອະນຸຍາດຕຳແໜ່ງທາງພູມສາດ ຂອງໂປຣແກຣມທ່ອງເວັບ. ແອັບຯທີ່ເປັນອັນຕະລາຍອາດໃຊ້ຄຸນສົມບັດນີ້ ເພື່ອສົ່ງຂໍ້ມູນສະຖານທີ່ໄປໃຫ້ເວັບໄຊຕ່າງໆໄດ້."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"ຢັ້ງຢືນແພັກເກດ"</string> @@ -1703,7 +1705,7 @@ <string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"PIN ປະຈຸບັນ"</string> <string name="restr_pin_enter_new_pin" msgid="5959606691619959184">"ລະຫັດ PIN ໃໝ່"</string> <string name="restr_pin_confirm_pin" msgid="8501523829633146239">"ຢືນຢັນລະຫັດ PIN ໃໝ່"</string> - <string name="restr_pin_create_pin" msgid="8017600000263450337">"ສ້າງ PIN ສໍາລັບການປັບປຸງຂໍ້ຈໍາກັດ"</string> + <string name="restr_pin_create_pin" msgid="8017600000263450337">"ສ້າງ PIN ສໍາລັບການປັບປຸງຂໍ້ຈໍາກັດ"</string> <string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN ບໍ່ກົງກັນ. ລອງໃໝ່ອີກຄັ້ງ."</string> <string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN ສັ້ນເກີນໄປ. ຕ້ອງມີຢ່າງໜ້ອຍ 4 ຫຼັກ."</string> <plurals name="restr_pin_countdown"> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index be7e571f7460..82548a0f676a 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Leidžiama programai nustatyti signalą įdiegtoje žadintuvo programoje. Kai kuriose žadintuvo programose ši funkcija gali nebūti nevykdoma."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"pridėti balso pašto pranešimų"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Leidžia programai pridėti pranešimų prie jūsų balso pašto gautųjų."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"skaityti visus balso pašto pranešimus"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Programai leidžiama skaityti visus balso pašto pranešimus."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"keisti naršyklės geografinės vietos leidimus"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Leidžiama programai keisti naršyklės geografinės vietos leidimus. Kenkėjiškos programos gali tai naudoti, kad leistų siųsti vietos informaciją abejotinoms svetainėms."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"patikrinti paketus"</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index b421da49366b..798a39dd431c 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -1001,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Ļauj lietotnei iestatīt signālu instalētajā modinātājpulksteņa lietotnē. Dažās modinātājpulksteņu lietotnēs šo funkciju, iespējams, nevar ieviest."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"pievienot balss pastu"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Ļauj lietotnei pievienot ziņojumus jūsu balss pasta iesūtnei."</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"pārveidot pārlūkprogrammas ģeogrāfiskās atrašanās vietas atļaujas"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Ļauj lietotnei modificēt pārlūkprogrammas ģeogrāfiskās atrašanās vietas atļaujas. Ļaunprātīgas lietotnes to var izmantot, lai atļautu atrašanās vietas informācijas sūtīšanu uz citām vietnēm."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"pakotņu verificēšana"</string> diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml index 803128fa1ba3..d19d60714262 100644 --- a/core/res/res/values-mn-rMN/strings.xml +++ b/core/res/res/values-mn-rMN/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Апп нь суулгагдсан сэрүүлэгний апп дээр сэрүүлэг тохируулах боломжтой. Зарим сэрүүлэгний апп нь энэ функцийг дэмжихгүй байж болзошгүй."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"дуут шуудан нэмэх"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Таны дуут шуудангийн ирсэн мэйлд зурвас нэмэхийг апп-д зөвшөөрөх."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"бүх дуут шууданг унших"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Апп-д таны бүх дуут шууданг унших боломж олгоно."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Хөтчийн геобайршлын зөвшөөрлийг өөрчлөх"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Апп нь Хөтчийн гео байршлын зөвшөөрлийг өөрчлөх боломжтой. Хортой апп нь энийг ашиглан дурын веб хуудасруу байршлын мэдээллийг илгээх боломжтой."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"багцийг тулгах"</string> diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml index 1d1a75b83121..49347a764b18 100644 --- a/core/res/res/values-ms-rMY/strings.xml +++ b/core/res/res/values-ms-rMY/strings.xml @@ -189,8 +189,7 @@ <string name="safeMode" msgid="2788228061547930246">"Mod selamat"</string> <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string> <string name="user_owner_label" msgid="6465364741001216388">"Apl peribadi"</string> - <!-- no translation found for managed_profile_label (4287077106125758391) --> - <skip /> + <string name="managed_profile_label" msgid="4287077106125758391">"Kerja Android"</string> <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Perkhidmatan yang anda perlu bayar"</string> <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Melakukan perkara yang boleh mengenakan bayaran kepada anda."</string> <string name="permgrouplab_messages" msgid="7521249148445456662">"Mesej anda"</string> @@ -402,7 +401,7 @@ <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"terikat kepada interaksi suara"</string> <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan interaksi suara. Tidak sekali-kali diperlukan untuk apl biasa."</string> <string name="permlab_manageVoiceKeyphrases" msgid="1252285102392793548">"urus frasa kunci suara"</string> - <string name="permdesc_manageVoiceKeyphrases" msgid="8476560722907530008">"Membenarkan pemegang menguruskan frasa kunci untuk pengesahan sebutan laluan. Tidak sekali-kali diperlukan untuk apl biasa."</string> + <string name="permdesc_manageVoiceKeyphrases" msgid="8476560722907530008">"Membenarkan pemegang mengurus frasa kunci untuk pengesahan sebutan laluan suara. Tidak sekali-kali diperlukan untuk apl biasa."</string> <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"terikat kepada paparan jauh"</string> <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi paparan jauh. Tidak sekali-kali diperlukan untuk apl biasa."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"terikat kepada perkhidmatan widget"</string> @@ -1002,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Membenarkan apl untuk menetapkan penggera dalam apl penggera jam yang dipasang. Sesetengah applikasi jam penggera tidak boleh melaksanakan ciri ini."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"tambah mel suara"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Membenarkan apl untuk menambahkan mesej pada peti masuk mel suara anda."</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ubah suai kebenaran geolokasi Penyemak Imbas"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Membenarkan apl untuk mengubah suai kebenaran geolokasi Penyemak Imbas. Apl hasad boleh menggunakannya untuk membenarkan menghantar maklumat lokasi kepada laman web sembarangan."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"sahkan pakej"</string> @@ -1363,10 +1366,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"Membenarkan aplikasi mendengar perubahan dalam keadaan amanah."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Sediakan ejen amanah."</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Membenarkan aplikasi menyediakan ejen amanah."</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Lancarkan menu tetapan ejen amanah."</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Membenarkan aplikasi melancarkan aktiviti yang mengubah tingkah laku ejen amanah."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Mengikat kepada perkhidmatan ejen amanah"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Membenarkan aplikasi terikat kepada perkhidmatan ejen amanah."</string> <string name="permlab_recovery" msgid="3157024487744125846">"Berinteraksi dengan kemas kini dan sistem pemulihan"</string> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 31fa11d8a0ea..40764c7c7383 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -401,7 +401,7 @@ <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"binde seg til en tjeneste for talehandlinger"</string> <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Gir innehaveren tillatelse til å binde til toppnivået av brukergrensesnittet for en tjeneste for talehandlinger. Dette skal ikke være nødvendig for vanlige apper."</string> <string name="permlab_manageVoiceKeyphrases" msgid="1252285102392793548">"administrer nøkkelfraser for stemmebruk"</string> - <string name="permdesc_manageVoiceKeyphrases" msgid="8476560722907530008">"Tillater innehaveren å administrere nøkkelfraser for gjenkjennelse av talekommandoord. Skal aldri være nødvendig for normale apper."</string> + <string name="permdesc_manageVoiceKeyphrases" msgid="8476560722907530008">"Tillater eieren å administrere nøkkelfraser for gjenkjennelse av talekommandoord. Skal aldri være nødvendig for normale apper."</string> <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"binde til ekstern skjerm"</string> <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Lar innehaveren binde seg til det øverste grensesnittnivået for ekstern skjerm. Skal aldri være nødvendig for vanlige apper."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"binde til modultjenste"</string> @@ -1001,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Lar appen stille inn alarmen for en installert alarmklokke-app. Enkelte alarmklokke-apper implementerer kanskje ikke denne funksjonen."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"legge til talepost"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Lar appen legge til meldinger i talepostkassen din."</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"endre nettleserens tillatelser for geoposisjonering"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Lar appen endre nettleserens tillatelser for geoposisjonering. Ondsinnede apper kan bruke dette for å tillate sending av posisjonsinformasjon til vilkårlige nettsteder."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"bekrefte pakker"</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index a655f36c535d..37c25947e97d 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Hiermee kan de app een alarm instellen in een geïnstalleerde wekkerapp. Deze functie wordt door sommige wekkerapps niet geïmplementeerd."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"voicemail toevoegen"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Hiermee kan de app berichten toevoegen aan de inbox van uw voicemail."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"alle voicemails lezen"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Hiermee kan de app al uw voicemails lezen."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"geolocatierechten voor browser aanpassen"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Hiermee kan de app de geolocatierechten van de browser aanpassen. Schadelijke apps kunnen dit gebruiken om locatiegegevens te verzenden naar willekeurige websites."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"pakketten controleren"</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index c30ad74c1a5b..a3282e91808a 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Pozwala aplikacji na ustawienie alarmu w zainstalowanej aplikacji budzika. Funkcja ta może nie być zaimplementowana w niektórych aplikacjach tego typu."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"dodawanie poczty głosowej"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Pozwala aplikacji na dodawanie wiadomości do skrzynki odbiorczej poczty głosowej."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"odczyt całej poczty głosowej"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Zezwala aplikacji na odczyt całej Twojej poczty głosowej."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"modyfikowanie pozwoleń przeglądarki dotyczących lokalizacji geograficznej"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Pozwala aplikacji na modyfikowanie uprawnień przeglądarki dotyczących lokalizacji geograficznej. Złośliwe aplikacje mogą używać tej opcji do wysyłania informacji o lokalizacji do dowolnych witryn."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"weryfikowanie pakietów"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 2e4e42364523..e85d902f58be 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Permite que a aplicação defina um alarme numa aplicação de despertador instalada. Algumas aplicações de despertador podem não integrar esta funcionalidade."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"adicionar correio de voz"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite que a aplicação adicione mensagens à sua caixa de entrada de correio de voz."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"ler todo o correio de voz"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Permite que a aplicação leia todo o correio de voz."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"modificar permissões de geolocalização do Navegador"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permite que a aplicação modifique as permissões de geolocalização do navegador. As aplicações maliciosas podem usar isto para permitir o envio de informações de localização para Web sites arbitrárias."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"verificar pacotes"</string> @@ -1362,10 +1364,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permite que uma aplicação registe alterações no trust state."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Fornecer um agente fidedigno."</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Permite que uma aplicação forneça um agente fidedigno."</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Inicie o menu de definições do agente de fidedignidade."</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Permite que uma aplicação inicie uma atividade que altere o comportamento do agente de fidedignidade."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Vincular a um serviço de trust agent"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permite que uma aplicação fique vinculada a um serviço de trust agent."</string> <string name="permlab_recovery" msgid="3157024487744125846">"Interagir com o sistema de recuperação e de atualização"</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 3df7ecb7bab1..59328f558c0c 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -1001,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Permite que o aplicativo defina um alarme em um aplicativo despertador instalado. Alguns aplicativos despertador podem não implementar este recurso."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"adicionar correio de voz"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite que o aplicativo adicione mensagens a sua caixa de entrada do correio de voz."</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Modifique as permissões de geolocalização de seu navegador"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permite que o aplicativo modifique as permissões de geolocalização do navegador. Aplicativos maliciosos podem usar isso para permitir o envio de informações locais para sites arbitrários."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"verificar pacotes"</string> @@ -1362,10 +1366,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permite que o aplicativo detecte alterações no estado de confiança."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Fornecer um agente de confiança."</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Permite que um aplicativo forneça um agente de confiança."</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Abra o menu de configurações do agente de confiança."</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Permite que um aplicativo inicie uma atividade que altera o comportamento do agente de confiança."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Associar a um serviço de agente de confiança"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permite que o aplicativo se associe a um serviço de agente de confiança."</string> <string name="permlab_recovery" msgid="3157024487744125846">"Interagir com o sistema de atualizações e recuperação"</string> diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml index ff26d8fe3e44..83ba3a642fc7 100644 --- a/core/res/res/values-rm/strings.xml +++ b/core/res/res/values-rm/strings.xml @@ -1666,6 +1666,10 @@ <skip /> <!-- no translation found for permdesc_addVoicemail (6604508651428252437) --> <skip /> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <!-- no translation found for permlab_writeGeolocationPermissions (5962224158955273932) --> <skip /> <!-- no translation found for permdesc_writeGeolocationPermissions (1083743234522638747) --> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 110b24380964..11236b563fca 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -189,8 +189,7 @@ <string name="safeMode" msgid="2788228061547930246">"Mod sigur"</string> <string name="android_system_label" msgid="6577375335728551336">"Sistemul Android"</string> <string name="user_owner_label" msgid="6465364741001216388">"Aplicații personale"</string> - <!-- no translation found for managed_profile_label (4287077106125758391) --> - <skip /> + <string name="managed_profile_label" msgid="4287077106125758391">"Android pentru serviciu"</string> <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servicii cu plată"</string> <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Efectuează acţiuni care sunt cu plată."</string> <string name="permgrouplab_messages" msgid="7521249148445456662">"Mesajele dvs."</string> @@ -1002,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Permite aplicaţiei să seteze o alarmă într-o aplicaţie de ceas cu alarmă instalată. Este posibil ca unele aplicaţii de ceas cu alarmă să nu implementeze această funcţie."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"adăugare mesagerie vocală"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite aplicaţiei să adauge mesaje în Mesaje primite în mesageria vocală."</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"modificare permisiuni pentru locaţia geografică a browserului"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permite aplicaţiei să modifice permisiunile privind locaţia geografică a browserului. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a permite trimiterea informaţiilor privind locaţia către site-uri web arbitrare."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"verificare pachete"</string> @@ -1363,10 +1366,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permite unei aplicații să detecteze modificările în starea de încredere."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Indicați un agent de încredere."</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Permite unei aplicații să indice un agent de încredere."</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Lansați meniul de setări pentru agentul de încredere."</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Permite unei aplicații să lanseze o activitate care schimbă comportamentul agentului de încredere."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Asocierea la un serviciu „agenți de încredere”."</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permite unei aplicații să se asocieze la un serviciu „agent de încredere”."</string> <string name="permlab_recovery" msgid="3157024487744125846">"Interacțiune cu sistemul de recuperare și de actualizare"</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 12d1895f180a..c5f4c13eabe6 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Приложение сможет настраивать будильник. Функция поддерживается не во всех программах."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"Добавление голосовых сообщений"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Приложение сможет добавлять голосовые сообщения в папку \"Входящие\"."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"Доступ к голосовой почте"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Чтение голосовых сообщений."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Изменение прав доступа к геоданным в браузере"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Приложение сможет изменять настройки доступа к геоданным в браузере. Вредоносные программы смогут таким образом отправлять информацию о местоположении на любые веб-сайты."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"Проверка пакетов"</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index ab596c5fa096..eb685baf33d6 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -1001,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Umožňuje aplikácii nastaviť budík v nainštalovanej aplikácii budík. Niektoré aplikácie budíka nemusia túto funkciu implementovať."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"pridať hlasovú schránku"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Umožní aplikácii pridávať správy do doručenej pošty hlasovej schránky."</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"zmeniť povolenia prehliadača poskytovať informácie o zemepisnej polohe"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Umožňuje aplikácii zmeniť povolenia prehliadača na poskytovanie údajov o zemepisnej polohe. Škodlivé aplikácie to môžu použiť na odosielanie informácií o polohe ľubovoľným webovým stránkam."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"overiť balíky"</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index cc06fd326cd2..47568d67c1f6 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -1001,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Programu omogoča nastavitev alarma v nameščenem programu budilke. Nekateri programi budilke morda nimajo te funkcije."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"dodajanje odzivnika"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Programu omogoča dodajanje sporočil prejetim sporočilom odzivnika."</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Spreminjanje dovoljenj za geolokacijo brskalnika"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Programu omogoča spreminjanje geolokacijskih dovoljenj v brskalniku. Zlonamerni programi lahko to izkoristijo za pošiljanje podatkov o lokaciji poljubnim spletnim mestom."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"preveri pakete"</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index 099e6ef970e2..4758c94cc1cf 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -189,7 +189,7 @@ <string name="safeMode" msgid="2788228061547930246">"Безбедни режим"</string> <string name="android_system_label" msgid="6577375335728551336">"Android систем"</string> <string name="user_owner_label" msgid="6465364741001216388">"Личне апликације"</string> - <string name="managed_profile_label" msgid="4287077106125758391">"Android за посао"</string> + <string name="managed_profile_label" msgid="4287077106125758391">"Android Work"</string> <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Услуге које се плаћају"</string> <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Покреће радње које могу да се плаћају."</string> <string name="permgrouplab_messages" msgid="7521249148445456662">"Поруке"</string> @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Дозвољава апликацији да подеси аларм у инсталираној апликацији будилника. Неке апликације будилника можда не примењују ову функцију."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"додавање говорне поште"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Дозвољава апликацији да додаје поруке у пријемно сандуче говорне поште."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"читај сву говорну пошту"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Дозвољава апликацији да чита говорну пошту."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"измена дозвола за географске локације Прегледача"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Дозвољава апликацији да измени дозволе Прегледача за утврђивање географске локације. Злонамерне апликације то могу да злоупотребе и искористе за слање информација о локацији насумичним веб сајтовима."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"верификовање пакета"</string> @@ -1362,10 +1364,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"Дозвољава апликацији да прати промене Trust стања."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Обезбеђивање поузданог агента."</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Дозвољава апликацији да обезбеди поузданог агента."</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Покрени мени подешавања поузданог агента."</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Дозвољава апликацији да покреће активност која мења понашање поузданог агента."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Везивање за услугу Trust agents"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Дозвољава апликацији да се веже за услугу Trust agents."</string> <string name="permlab_recovery" msgid="3157024487744125846">"Интеракција са системом за ажурирање и опоравак"</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index 46bb5636aee4..af85340a1d24 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Tillåter att appen ställer in ett alarm i en befintlig alarmapp. Vissa alarmappar har inte den här funktionen."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"lägg till röstbrevlåda"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Gör att appen lägger till meddelanden i röstbrevlådans inkorg."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"läsa alla röstmeddelanden"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Tillåter att appen läser alla dina röstmeddelanden."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Ändra geografisk plats för webbläsaren"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Tillåter att appen ändrar webbläsarens behörigheter för geografisk plats. Skadliga appar kan använda detta för att tillåta att platsinformation skickas till godtyckliga webbplatser."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"kontrollera paket"</string> @@ -1362,10 +1364,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"Tillåter att en app lyssnar efter ändringar i den betrodda agentens status."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Tillhandahåll en betrodd agent."</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Tillåter att en app tillhandahåller en betrodd agent."</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Öppna inställningsmenyn för betrodda agenter."</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Tillåter att en app startar en aktivitet som ändrar den betrodda agentens beteende."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Bind till en tjänst från en betrodd agent"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Tillåter att en app binds vid en tjänst från en betrodd agent."</string> <string name="permlab_recovery" msgid="3157024487744125846">"Interagera med uppdaterings- och återställningssystemet"</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 595c80784ca0..755b9d281c4f 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Inaruhusu programu kuweka kengele katika programu iliyosakinishwa ya kengele. Programu zingine za kengele zinawezakosa kutekeleza kipengee hiki."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"ongeza barua ya sauti"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Huruhusu programu kuongeza mawasiliano kwenye kikasha cha ujumbe wa sauti."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"soma ujumbe wote wa sauti"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Huruhusu programu isome ujumbe wako wote wa sauti."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Rekebisha vibali vya Kivinjari cha eneo la jio"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Inaruhusu programu kurekebisha ruhusa za eneo la jio za kivinjari. Programu hasidi zinaweza tumia hii kuruhusu kutuma taarifa ya eneo kwa wavuti holela."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"thibitisha furushi"</string> @@ -1362,10 +1364,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"Huruhusu programu kusikiliza mabadiliko katika hali ya kuaminiwa."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Toa wakala wa uaminifu."</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Huruhusu programu kutoa wakala wa uaminifu."</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Fungua menyu ya mipangilio ya madalali wa kuaminiwa."</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Huruhusu programu kufungua kitendo ambacho hubadilisha tabia ya madalali wa kuaminiwa."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Funga kwenye huduma ya dalali wa kuaminiwa"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Huruhusu programu kufungamanisha kwenye huduma ya dalali wa kuaminiwa."</string> <string name="permlab_recovery" msgid="3157024487744125846">"Ingiliana na sasisho na mfumo wa kurejesha"</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index feabf4ff9d7b..b03221d47302 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -401,7 +401,7 @@ <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"เชื่อมโยงกับโปรแกรมโต้ตอบด้วยเสียง"</string> <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"อนุญาตให้ผู้ใช้อุปกรณ์เชื่อมโยงกับอินเทอร์เฟซระดับบนสุดของบริการโต้ตอบด้วยเสียง ไม่จำเป็นสำหรับแอปทั่วไป"</string> <string name="permlab_manageVoiceKeyphrases" msgid="1252285102392793548">"จัดการเสียงพูดวลีคำหลัก"</string> - <string name="permdesc_manageVoiceKeyphrases" msgid="8476560722907530008">"ให้ผู้ใช้อุปกรณ์สามารถจัดการวลีคำหลักสำหรับการตรวจหาเสียงพูดคำที่นิยม ไม่จำเป็นสำหรับแอปทั่วไป"</string> + <string name="permdesc_manageVoiceKeyphrases" msgid="8476560722907530008">"ให้แอปสามารถจัดการวลีคำหลักสำหรับการตรวจหาเสียงพูดคำที่นิยม ไม่จำเป็นสำหรับแอปทั่วไป"</string> <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"ผูกกับจอแสดงผลระยะไกล"</string> <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"อนุญาตให้ผู้ใช้ผูกกับอินเทอร์เฟซระดับสูงสุดของจอแสดงผลระยะไกล ซึ่งแอปพลิเคชันทั่วไปไม่จำเป็นต้องใช้"</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"เชื่อมโยงกับบริการวิดเจ็ต"</string> @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"อนุญาตให้แอปพลิเคชันตั้งเวลาปลุกในแอปพลิเคชันนาฬิกาปลุกที่ติดตั้ง แอปพลิเคชันนาฬิกาปลุกบางรายการอาจไม่ใช้คุณลักษณะนี้"</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"เพิ่มข้อวามเสียง"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"อนุญาตให้แอปพลิเคชันเพิ่มข้อความลงในกล่องข้อความเสียงของคุณ"</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"อ่านข้อความเสียงทั้งหมด"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"อนุญาตให้แอปอ่านข้อความเสียงทั้งหมดของคุณ"</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"แก้ไขการอนุญาตเกี่ยวกับการระบุตำแหน่งทางภูมิศาสตร์ของเบราว์เซอร์"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"อนุญาตให้แอปพลิเคชันแก้ไขการอนุญาตตำแหน่งทางภูมิศาสตร์ของเบราว์เซอร์ แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ในการส่งข้อมูลตำแหน่งไปยังเว็บไซต์ต่างๆ ได้ตามต้องการ"</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"ยืนยันแพ็กเกจ"</string> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index 13b629e6b268..af88c3c4e8e6 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -1001,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Pinapayagan ang app na magtakda ng alarm sa isang naka-install na app ng alarm clock. Maaaring hindi ipatupad ng ilang apps ng alarm clock ang tampok na ito."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"magdagdag ng voicemail"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Pinapayagan ang app na magdagdag ng mga mensahe sa iyong inbox ng voicemail."</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"baguhin ang mga pahintulot ng geolocation ng Browser"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Pinapayagan ang app na baguhin ang mga pahintulot sa geolocation ng Browser. Maaari itong gamitin ng nakakahamak na apps upang payagan ang pagpapadala ng impormasyon ng lokasyon sa mga hindi tukoy na web site."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"i-verify ang mga package"</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 0c19b03c5008..ee8c4648d34f 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -1001,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Uygulamaya, çalar saat uygulamasının alarmını ayarlama izni verir. Bazı çalar saat uygulamaları bu özelliği uygulayamayabilir."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"sesli mesaj ekle"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Uygulamaya, sesli mesaj gelen kutunuza mesaj ekleme izni verir."</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Tarayıcı\'nın coğrafi konum izinlerini değiştir"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Uygulamaya, Tarayıcı\'nın coğrafi konum izinlerini değiştirme izni verir. Kötü amaçlı uygulamalar keyfi web sitelerine konum bilgisi gönderilmesini sağlamak için bunu kullanabilirler."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"paketleri doğrula"</string> @@ -1362,10 +1366,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"Bir uygulamanın, güven durumundaki değişiklikleri dinlemesine izin verir."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Güven aracısı sağlama."</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Bir uygulamanın güven aracısı sağlamasına izin verir."</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Güven aracısı ayarlar menüsünü başlat."</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Bir uygulamanın güven aracısının çalışma biçimini değiştiren bir etkinlik başlatmasına izin verir."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Güven aracı hizmetine bağlan"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Bir uygulamanın, güven aracı hizmetine bağlanmasına izin verir."</string> <string name="permlab_recovery" msgid="3157024487744125846">"Güncelleme ve kurtarma sistemiyle etkileşim kur"</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index 0d56975bba93..b85fc996af8a 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Дозволяє програмі налаштовувати сигнал у встановленій програмі будильника. У деяких програмах будильника ця функція може не застосовуватися."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"додавати голосову пошту"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Дозволяє програмі додавати повідомлення в папку \"Вхідні\" голосової пошти."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"читати всі голосові повідомлення"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Додаток може читати всі голосові повідомлення."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"змінювати дозволи географічного місцезнаходження у веб-переглядачі"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Дозволяє програмі змінювати дозволи географічного місцезнаходження у веб-переглядачі. Шкідливі програми можуть використовувати це, щоб дозволяти надсилати інформацію про місцезнаходження довільним веб-сайтам."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"перевіряти пакети"</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index dd13b4556483..b38fb87df810 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Cho phép ứng dụng đặt báo thức trong ứng dụng đồng hồ báo thức được cài đặt. Một số ứng dụng đồng hồ báo thức có thể không thực thi tính năng này."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"thêm thư thoại"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Cho phép ứng dụng thêm thông báo vào hộp thư thoại đến của bạn."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"đọc tất cả các thư thoại"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Cho phép ứng dụng này đọc tất cả các thư thoại của bạn."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"sửa đổi các quyền về vị trí địa lý của Trình duyệt"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Cho phép ứng dụng sửa đổi cấp phép vị trí địa lý của Trình duyệt. Ứng dụng độc hại có thể lợi dụng quyền này để cho phép gửi thông tin vị trí tới các trang web tùy ý."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"xác minh gói"</string> @@ -1362,10 +1364,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"Cho phép ứng dụng quan sát các thay đổi ở trạng thái đáng tin cậy."</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Cung cấp tác nhân đáng tin cậy."</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Cho phép ứng dụng cung cấp tác nhân đáng tin cậy."</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Khởi chạy trình đơn cài đặt đại lý đáng tin cậy."</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Cho phép ứng dụng khởi chạy hoạt động thay đổi hoạt động của đại lý đáng tin cậy."</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Liên kết với một dịch vụ của đại lý đáng tin cậy"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Cho phép ứng dụng liên kết với một dịch vụ của đại lý đáng tin cậy."</string> <string name="permlab_recovery" msgid="3157024487744125846">"Tương tác với hệ thống khôi phục và bản cập nhật"</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 3a073661b2a7..d730c49f6ae8 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -189,8 +189,7 @@ <string name="safeMode" msgid="2788228061547930246">"安全模式"</string> <string name="android_system_label" msgid="6577375335728551336">"Android 系统"</string> <string name="user_owner_label" msgid="6465364741001216388">"个人应用"</string> - <!-- no translation found for managed_profile_label (4287077106125758391) --> - <skip /> + <string name="managed_profile_label" msgid="4287077106125758391">"Android Work"</string> <string name="permgrouplab_costMoney" msgid="5429808217861460401">"需要您付费的服务"</string> <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"执行可能需要您付费的操作。"</string> <string name="permgrouplab_messages" msgid="7521249148445456662">"您的信息"</string> @@ -1002,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"允许应用在已安装的闹钟应用中设置闹钟。有些闹钟应用可能无法实现此功能。"</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"添加语音邮件"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"允许应用向您的语音信箱收件箱添加邮件。"</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"修改“浏览器”地理位置的权限"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"允许应用修改“浏览器”的地理位置权限。恶意应用可能借此向任意网站发送位置信息。"</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"验证软件包"</string> @@ -1363,10 +1366,8 @@ <string name="permdesc_trust_listener" msgid="8233895334214716864">"允许应用检测信任状态的变化。"</string> <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"提供信任的代理。"</string> <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"允许应用提供信任的代理。"</string> - <!-- no translation found for permlab_launch_trust_agent_settings (7494179366945389098) --> - <skip /> - <!-- no translation found for permdesc_launch_trust_agent_settings (985453787420853278) --> - <skip /> + <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"启动信任的代理设置菜单。"</string> + <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"允许应用启动可变更信任的代理行为的活动。"</string> <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"绑定至信任的代理服务"</string> <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"允许应用绑定至信任的代理服务。"</string> <string name="permlab_recovery" msgid="3157024487744125846">"与更新和恢复系统互动"</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index 8e290b52be7b..43a487b7ae91 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -1001,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"允許應用程式在安裝的鬧鐘應用程式中設定鬧鐘,某些鬧鐘應用程式可能沒有這項功能。"</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"新增留言"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"允許應用程式將訊息加到您的留言信箱收件箱。"</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"修改瀏覽器地理資訊的權限"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"允許應用程式修改瀏覽器的地理資訊權限。惡意應用程式可能會藉此允許將您的位置資訊任意傳送給某些網站。"</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"驗證套件"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 6ab2b48ad0f1..6658689d56fd 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -448,7 +448,7 @@ <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"管理信任的憑證"</string> <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"允許應用程式安裝 CA 憑證 (做為信任的憑證) 及解除安裝 CA 憑證。"</string> <string name="permlab_bindJobService" msgid="3637568367978271086">"執行應用程式的預定背景作業"</string> - <string name="permdesc_bindJobService" msgid="3473288460524119838">"這項權限可讓 Android 系統於收到要求時在背景執行應用程式。"</string> + <string name="permdesc_bindJobService" msgid="3473288460524119838">"這項權限可讓 Android 系統收到要求時在背景執行應用程式。"</string> <string name="permlab_diagnostic" msgid="8076743953908000342">"讀寫 diag 擁有的資源"</string> <string name="permdesc_diagnostic" msgid="6608295692002452283">"允許應用程式讀取或寫入診斷群組擁有的任何資源,例如 /dev 底下的檔案。這可能會影響系統的穩定性和安全性,因此應由製造商或電信業者操作,且只用在特定硬體診斷。"</string> <string name="permlab_changeComponentState" msgid="6335576775711095931">"啟用或停用應用程式元件"</string> @@ -1001,6 +1001,10 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"允許應用程式在安裝的鬧鐘應用程式中設定鬧鐘,某些鬧鐘應用程式可能無法執行這項功能。"</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"新增語音留言"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"允許應用程式將訊息新增至您的語音信箱收件匣。"</string> + <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) --> + <skip /> + <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) --> + <skip /> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"修改瀏覽器地理資訊的權限"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"允許應用程式修改瀏覽器的地理位置權限。請注意,惡意應用程式可能利用此功能允許將您的位置資訊任意傳送給某些網站。"</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"驗證套件"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index 07238c38d374..820ea50df59c 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -1001,6 +1001,8 @@ <string name="permdesc_setAlarm" msgid="316392039157473848">"Ivumela uhlelo lokusebenza ukuthi isethe i-alamu ensizeni efkiwe ye-alamu. Ezinye izinhlelo zokusebenza ze-alamu kungenzeka zingakusebenzisi lokho."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"engeza imeyili yezwi"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Ivumela uhlelo lokusebenza ukwengeza imiyalezo kwibhokisi lakho lemeyili yezwi."</string> + <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"funda wonke amavoyisimeyili"</string> + <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Ivumela uhlelo lokusebenza ukuthi lufunde wonke amavoyisimeyili wakho."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Gugula izimvume zendawo Yesiphequluli"</string> <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Ivumela uhlelo lokusebenza ukuthi iguqule izimvume eziphathelene nezindawo Zesiphequluli. Izuhlelo lokusebenza eziyingozi zingasebenzisa lokhu ukuvumela ukuvumela imininingwane yendawo kunoma imaphi amawebusayithi."</string> <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"qinisekisa amaphakheji"</string> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 8d8f69e87df8..d3e47905a218 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -5250,10 +5250,18 @@ </declare-styleable> <declare-styleable name="PathInterpolator"> + <!-- The x coordinate of the first control point of the cubic Bezier --> <attr name="controlX1" format="float" /> + <!-- The y coordinate of the first control point of the cubic Bezier --> <attr name="controlY1" format="float" /> + <!-- The x coordinate of the second control point of the cubic Bezier --> <attr name="controlX2" format="float" /> + <!-- The y coordinate of the second control point of the cubic Bezier --> <attr name="controlY2" format="float" /> + <!-- The control points defined as a path. + When pathData is defined, then both of the control points of the + cubic Bezier will be ignored. --> + <attr name="pathData"/> </declare-styleable> <!-- ========================== --> @@ -5403,6 +5411,12 @@ <declare-styleable name="PropertyAnimator"> <!-- Name of the property being animated. --> <attr name="propertyName" format="string"/> + <!-- Name of the property being animated as the X coordinate of the pathData. --> + <attr name="propertyXName" format="string"/> + <!-- Name of the property being animated as the Y coordinate of the pathData. --> + <attr name="propertyYName" format="string"/> + <!-- The path used to animate the properties in the ObjectAnimator --> + <attr name="pathData"/> </declare-styleable> @@ -6733,6 +6747,8 @@ <attr name="switchPadding" format="dimension" /> <!-- Whether to split the track and leave a gap for the thumb drawable. --> <attr name="splitTrack" /> + <!-- Whether to draw on/off text. --> + <attr name="showText" format="boolean" /> </declare-styleable> <declare-styleable name="Pointer"> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 4e06d9a03c5e..fc1d0df86f46 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -985,6 +985,14 @@ Intent.FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS} --> <attr name="autoRemoveFromRecents" format="boolean" /> + <!-- Tasks whose root has this attribute set to true will replace baseIntent with that of the + next activity in the task. If the next activity also has this attribute set to true then + it will yield the baseIntent to any activity that it launches in the same task. This + continues until an activity is encountered which has this attribute set to false. False + is the default. This attribute set to true also permits activity's use of the + TaskDescription to change labels, colors and icons in the recent task list. --> + <attr name="relinquishTaskIdentity" format="boolean" /> + <!-- The <code>manifest</code> tag is the root of an <code>AndroidManifest.xml</code> file, describing the contents of an Android package (.apk) file. One @@ -1653,6 +1661,7 @@ <attr name="documentLaunchMode" /> <attr name="maxRecents" /> <attr name="autoRemoveFromRecents" /> + <attr name="relinquishTaskIdentity" /> </declare-styleable> <!-- The <code>activity-alias</code> tag declares a new diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 471eece9d21e..d350ef2964b5 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1597,5 +1597,12 @@ <item>"1,sim,0,modem"</item> </string-array> + <!-- This string array can be overriden to add an additional DRM support for WebView EME. --> + <!-- Array of "[keySystemName],[UuidOfMediaDrm]" --> + <string-array name="config_keySystemUuidMapping" translatable="false"> + <!-- Example: + <item>"x-com.microsoft.playready,9A04F079-9840-4286-AB92-E65BE0885F95"</item> + --> + </string-array> </resources> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 7703bfa89041..c3e4d94e04e7 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2207,6 +2207,9 @@ <public type="attr" name="thumbTint" /> <public type="attr" name="thumbTintMode" /> <public type="attr" name="fullBackupOnly" /> + <public type="attr" name="propertyXName" /> + <public type="attr" name="propertyYName" /> + <public type="attr" name="relinquishTaskIdentity" /> <public-padding type="dimen" name="l_resource_pad" end="0x01050010" /> diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml index 25307b9ba198..75f905c07efd 100644 --- a/core/res/res/values/styles_material.xml +++ b/core/res/res/values/styles_material.xml @@ -493,11 +493,12 @@ please see styles_device_defaults.xml. <item name="thumb">@drawable/switch_thumb_material_anim</item> <item name="splitTrack">true</item> <item name="switchTextAppearance">@style/TextAppearance.Material.Widget.Switch</item> - <item name="textOn"></item> - <item name="textOff"></item> + <item name="textOn">@string/capital_on</item> + <item name="textOff">@string/capital_off</item> <item name="switchMinWidth">4dip</item> <item name="switchPadding">4dip</item> <item name="background">?attr/selectableItemBackgroundBorderless</item> + <item name="showText">false</item> </style> <style name="Widget.Material.EditText" parent="Widget.EditText"/> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 1547bbdcfb3f..7a871cc75f5f 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1002,6 +1002,7 @@ <java-symbol type="array" name="config_callBarringMMI" /> <java-symbol type="array" name="config_globalActionsList" /> <java-symbol type="array" name="config_telephonyHardware" /> + <java-symbol type="array" name="config_keySystemUuidMapping" /> <java-symbol type="drawable" name="default_wallpaper" /> <java-symbol type="drawable" name="indicator_input_error" /> diff --git a/data/fonts/DroidSansFallback.ttf b/data/fonts/DroidSansFallback.ttf Binary files differindex 2b75113962a4..8e70e8091941 100644 --- a/data/fonts/DroidSansFallback.ttf +++ b/data/fonts/DroidSansFallback.ttf diff --git a/data/fonts/DroidSansFallbackFull.ttf b/data/fonts/DroidSansFallbackFull.ttf Binary files differindex a9df00585a4e..68d275192e61 100644 --- a/data/fonts/DroidSansFallbackFull.ttf +++ b/data/fonts/DroidSansFallbackFull.ttf diff --git a/data/fonts/DroidSansFallbackLegacy.ttf b/data/fonts/DroidSansFallbackLegacy.ttf Binary files differdeleted file mode 100644 index 61460b1f9df6..000000000000 --- a/data/fonts/DroidSansFallbackLegacy.ttf +++ /dev/null diff --git a/docs/html/tools/help/adb.jd b/docs/html/tools/help/adb.jd index f980042ac1fa..e2dd196216d6 100644 --- a/docs/html/tools/help/adb.jd +++ b/docs/html/tools/help/adb.jd @@ -8,6 +8,7 @@ page.tags=adb <div id="qv"> <h2>In this document</h2> <ol> + <li><a href="#Enabling">Enabling adb Debugging</a></li> <li><a href="#issuingcommands">Syntax</a></li> <li><a href="#commandsummary">Commands</a></li> <li><a href="#devicestatus">Querying for Emulator/Device Instances</a></li> @@ -72,6 +73,19 @@ instances and handles commands from multiple adb clients, you can control any em instance from any client (or from a script).</p> +<h2 id="Enabling">Enabling adb Debugging</h2> + +<p>In order to use adb with a device connected over USB, you must enable +<strong>USB debugging</strong> in the device system settings, under <strong> +Developer options</strong>.</p> + +<p>On Android 4.2 and higher, the Developer options screen is +hidden by default. To make it visible, go to +<b>Settings > About phone</b> and tap <b>Build number</b> seven times. Return to the previous +screen to find <strong>Developer options</strong> at the bottom.</p> + +<p>On some devices, the Developer options screen may be located or named differently.</p> + <p class="note"><strong>Note:</strong> When you connect a device running Android 4.2.2 or higher to your computer, the system shows a dialog asking whether to accept an RSA key that allows debugging through this computer. This security mechanism protects user devices because it ensures @@ -80,6 +94,11 @@ device and acknowledge the dialog. This requires that you have adb version 1.0.3 SDK Platform-tools r16.0.1 and higher) in order to debug on a device running Android 4.2.2 or higher.</p> +<p>For more information about connecting to a device over USB, read +<a href="{@docRoot}tools/device.html">Using Hardware Devices</a>.</p> + + + <h2 id="issuingcommands">Syntax</h2> diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index 13421aa1dea0..99596ef78e9b 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -1712,7 +1712,8 @@ public class Canvas { * the pos array. * * This method does not support glyph composition and decomposition and - * should therefore not be used to render complex scripts. + * should therefore not be used to render complex scripts. It also doesn't + * handle supplementary characters (eg emoji). * * @param text The text to be drawn * @param index The index of the first character to draw @@ -1727,8 +1728,9 @@ public class Canvas { if (index < 0 || index + count > text.length || count*2 > pos.length) { throw new IndexOutOfBoundsException(); } - native_drawPosText(mNativeCanvasWrapper, text, index, count, pos, - paint.mNativePaint); + for (int i = 0; i < count; i++) { + drawText(text, index + i, 1, pos[i * 2], pos[i * 2 + 1], paint); + } } /** @@ -1736,7 +1738,8 @@ public class Canvas { * the pos array. * * This method does not support glyph composition and decomposition and - * should therefore not be used to render complex scripts. + * should therefore not be used to render complex scripts. It also doesn't + * handle supplementary characters (eg emoji). * * @param text The text to be drawn * @param pos Array of [x,y] positions, used to position each character @@ -1744,10 +1747,7 @@ public class Canvas { */ @Deprecated public void drawPosText(@NonNull String text, @NonNull float[] pos, @NonNull Paint paint) { - if (text.length()*2 > pos.length) { - throw new ArrayIndexOutOfBoundsException(); - } - native_drawPosText(mNativeCanvasWrapper, text, pos, paint.mNativePaint); + drawPosText(text.toCharArray(), 0, text.length(), pos, paint); } /** @@ -2009,13 +2009,6 @@ public class Canvas { int start, int count, int contextStart, int contextCount, float x, float y, boolean isRtl, long nativePaint, long nativeTypeface); - private static native void native_drawPosText(long nativeCanvas, - char[] text, int index, - int count, float[] pos, - long nativePaint); - private static native void native_drawPosText(long nativeCanvas, - String text, float[] pos, - long nativePaint); private static native void native_drawTextOnPath(long nativeCanvas, char[] text, int index, int count, long nativePath, diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index 005b8efeba32..28cd869d224e 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -135,7 +135,6 @@ public class GradientDrawable extends Drawable { private Paint mStrokePaint; // optional, set by the caller private ColorFilter mColorFilter; // optional, set by the caller private int mAlpha = 0xFF; // modified by the caller - private boolean mDither; private final Path mPath = new Path(); private final RectF mRect = new RectF(); @@ -543,7 +542,7 @@ public class GradientDrawable extends Drawable { if (mLayerPaint == null) { mLayerPaint = new Paint(); } - mLayerPaint.setDither(mDither); + mLayerPaint.setDither(st.mDither); mLayerPaint.setAlpha(mAlpha); mLayerPaint.setColorFilter(mColorFilter); @@ -561,14 +560,14 @@ public class GradientDrawable extends Drawable { individual paints */ mFillPaint.setAlpha(currFillAlpha); - mFillPaint.setDither(mDither); + mFillPaint.setDither(st.mDither); mFillPaint.setColorFilter(mColorFilter); - if (mColorFilter != null && mGradientState.mColorStateList == null) { + if (mColorFilter != null && st.mColorStateList == null) { mFillPaint.setColor(mAlpha << 24); } if (haveStroke) { mStrokePaint.setAlpha(currStrokeAlpha); - mStrokePaint.setDither(mDither); + mStrokePaint.setDither(st.mDither); mStrokePaint.setColorFilter(mColorFilter); } } @@ -804,8 +803,8 @@ public class GradientDrawable extends Drawable { @Override public void setDither(boolean dither) { - if (dither != mDither) { - mDither = dither; + if (dither != mGradientState.mDither) { + mGradientState.mDither = dither; invalidateSelf(); } } @@ -1015,7 +1014,7 @@ public class GradientDrawable extends Drawable { state.mThemeAttrs = a.extractThemeAttrs(); state.mShape = a.getInt(R.styleable.GradientDrawable_shape, state.mShape); - mDither = a.getBoolean(R.styleable.GradientDrawable_dither, mDither); + state.mDither = a.getBoolean(R.styleable.GradientDrawable_dither, state.mDither); if (state.mShape == RING) { state.mInnerRadius = a.getDimensionPixelSize( @@ -1459,6 +1458,8 @@ public class GradientDrawable extends Drawable { public float mThicknessRatio = DEFAULT_THICKNESS_RATIO; public int mInnerRadius = -1; public int mThickness = -1; + public boolean mDither = false; + private float mCenterX = 0.5f; private float mCenterY = 0.5f; private float mGradientRadius = 0.5f; @@ -1510,6 +1511,7 @@ public class GradientDrawable extends Drawable { mThicknessRatio = state.mThicknessRatio; mInnerRadius = state.mInnerRadius; mThickness = state.mThickness; + mDither = state.mDither; mCenterX = state.mCenterX; mCenterY = state.mCenterY; mGradientRadius = state.mGradientRadius; diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java index 0512ecc1d0a4..f2e75a5ccf27 100644 --- a/graphics/java/android/graphics/drawable/RippleDrawable.java +++ b/graphics/java/android/graphics/drawable/RippleDrawable.java @@ -645,25 +645,29 @@ public class RippleDrawable extends LayerDrawable { @Override public Rect getDirtyBounds() { - final Rect drawingBounds = mDrawingBounds; - final Rect dirtyBounds = mDirtyBounds; - dirtyBounds.set(drawingBounds); - drawingBounds.setEmpty(); - - final int cX = (int) mHotspotBounds.exactCenterX(); - final int cY = (int) mHotspotBounds.exactCenterY(); - final Rect rippleBounds = mTempRect; - final Ripple[] activeRipples = mAnimatingRipples; - final int N = mAnimatingRipplesCount; - for (int i = 0; i < N; i++) { - activeRipples[i].getBounds(rippleBounds); - rippleBounds.offset(cX, cY); - drawingBounds.union(rippleBounds); - } + if (isProjected()) { + final Rect drawingBounds = mDrawingBounds; + final Rect dirtyBounds = mDirtyBounds; + dirtyBounds.set(drawingBounds); + drawingBounds.setEmpty(); + + final int cX = (int) mHotspotBounds.exactCenterX(); + final int cY = (int) mHotspotBounds.exactCenterY(); + final Rect rippleBounds = mTempRect; + final Ripple[] activeRipples = mAnimatingRipples; + final int N = mAnimatingRipplesCount; + for (int i = 0; i < N; i++) { + activeRipples[i].getBounds(rippleBounds); + rippleBounds.offset(cX, cY); + drawingBounds.union(rippleBounds); + } - dirtyBounds.union(drawingBounds); - dirtyBounds.union(super.getDirtyBounds()); - return dirtyBounds; + dirtyBounds.union(drawingBounds); + dirtyBounds.union(super.getDirtyBounds()); + return dirtyBounds; + } else { + return getBounds(); + } } @Override diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java index beb300d5789d..369bb591803d 100644 --- a/graphics/java/android/graphics/drawable/ShapeDrawable.java +++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java @@ -416,6 +416,9 @@ public class ShapeDrawable extends Drawable { final ShapeState state = mShapeState; final Paint paint = state.mPaint; + // Extract the theme attributes, if any. + state.mThemeAttrs = a.extractThemeAttrs(); + int color = paint.getColor(); color = a.getColor(R.styleable.ShapeDrawable_color, color); paint.setColor(color); diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index a1e1f7612a60..b4d1fdc29828 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -33,6 +33,7 @@ import android.graphics.PorterDuff.Mode; import android.util.ArrayMap; import android.util.AttributeSet; import android.util.Log; +import android.util.PathParser; import android.util.Xml; import com.android.internal.R; @@ -956,7 +957,7 @@ public class VectorDrawable extends Drawable { } - static class VPath { + private static class VPath { private int[] mThemeAttrs; int mStrokeColor = 0; @@ -974,7 +975,7 @@ public class VectorDrawable extends Drawable { Paint.Join mStrokeLineJoin = Paint.Join.MITER; float mStrokeMiterlimit = 4; - private VNode[] mNode = null; + private PathParser.PathDataNode[] mNode = null; private String mPathName; public VPath() { @@ -984,7 +985,7 @@ public class VectorDrawable extends Drawable { public void toPath(Path path) { path.reset(); if (mNode != null) { - VNode.createPath(mNode, path); + PathParser.PathDataNode.nodesToPath(mNode, path); } } @@ -1099,7 +1100,8 @@ public class VectorDrawable extends Drawable { } if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_pathData] == 0) { - mNode = parsePath(a.getString(R.styleable.VectorDrawablePath_pathData)); + mNode = PathParser.createNodesFromPathData(a.getString( + R.styleable.VectorDrawablePath_pathData)); } if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_fill] == 0) { @@ -1182,7 +1184,8 @@ public class VectorDrawable extends Drawable { } if (a.hasValue(R.styleable.VectorDrawablePath_pathData)) { - mNode = parsePath(a.getString(R.styleable.VectorDrawablePath_pathData)); + mNode = PathParser.createNodesFromPathData(a.getString( + R.styleable.VectorDrawablePath_pathData)); } mFillColor = a.getColor(R.styleable.VectorDrawablePath_fill, mFillColor); @@ -1218,488 +1221,5 @@ public class VectorDrawable extends Drawable { mStrokeColor = applyAlpha(mStrokeColor, mStrokeOpacity); } } - - private static int nextStart(String s, int end) { - char c; - - while (end < s.length()) { - c = s.charAt(end); - if (((c - 'A') * (c - 'Z') <= 0) || (((c - 'a') * (c - 'z') <= 0))) { - return end; - } - end++; - } - return end; - } - - private void addNode(ArrayList<VectorDrawable.VNode> list, char cmd, float[] val) { - list.add(new VectorDrawable.VNode(cmd, val)); - } - - /** - * parse the floats in the string - * this is an optimized version of - * parseFloat(s.split(",|\\s")); - * - * @param s the string containing a command and list of floats - * @return array of floats - */ - private static float[] getFloats(String s) { - if (s.charAt(0) == 'z' | s.charAt(0) == 'Z') { - return new float[0]; - } - try { - float[] tmp = new float[s.length()]; - int count = 0; - int pos = 1, end; - while ((end = extract(s, pos)) >= 0) { - if (pos < end) { - tmp[count++] = Float.parseFloat(s.substring(pos, end)); - } - pos = end + 1; - } - // handle the final float if there is one - if (pos < s.length()) { - tmp[count++] = Float.parseFloat(s.substring(pos, s.length())); - } - return Arrays.copyOf(tmp, count); - } catch (NumberFormatException e){ - Log.e(LOGTAG,"error in parsing \""+s+"\""); - throw e; - } - } - - /** - * calculate the position of the next comma or space - * @param s the string to search - * @param start the position to start searching - * @return the position of the next comma or space or -1 if none found - */ - private static int extract(String s, int start) { - int space = s.indexOf(' ', start); - int comma = s.indexOf(',', start); - if (space == -1) { - return comma; - } - if (comma == -1) { - return space; - } - return (comma > space) ? space : comma; - } - - private VectorDrawable.VNode[] parsePath(String value) { - int start = 0; - int end = 1; - - ArrayList<VectorDrawable.VNode> list = new ArrayList<VectorDrawable.VNode>(); - while (end < value.length()) { - end = nextStart(value, end); - String s = value.substring(start, end); - float[] val = getFloats(s); - addNode(list, s.charAt(0), val); - - start = end; - end++; - } - if ((end - start) == 1 && start < value.length()) { - - addNode(list, value.charAt(start), new float[0]); - } - return list.toArray(new VectorDrawable.VNode[list.size()]); - } - } - - private static class VNode { - private char mType; - private float[] mParams; - - public VNode(char type, float[] params) { - mType = type; - mParams = params; - } - - public VNode(VNode n) { - mType = n.mType; - mParams = Arrays.copyOf(n.mParams, n.mParams.length); - } - - public static void createPath(VNode[] node, Path path) { - float[] current = new float[4]; - char previousCommand = 'm'; - for (int i = 0; i < node.length; i++) { - addCommand(path, current, previousCommand, node[i].mType, node[i].mParams); - previousCommand = node[i].mType; - } - } - - private static void addCommand(Path path, float[] current, - char previousCmd, char cmd, float[] val) { - - int incr = 2; - float currentX = current[0]; - float currentY = current[1]; - float ctrlPointX = current[2]; - float ctrlPointY = current[3]; - float reflectiveCtrlPointX; - float reflectiveCtrlPointY; - - switch (cmd) { - case 'z': - case 'Z': - path.close(); - return; - case 'm': - case 'M': - case 'l': - case 'L': - case 't': - case 'T': - incr = 2; - break; - case 'h': - case 'H': - case 'v': - case 'V': - incr = 1; - break; - case 'c': - case 'C': - incr = 6; - break; - case 's': - case 'S': - case 'q': - case 'Q': - incr = 4; - break; - case 'a': - case 'A': - incr = 7; - break; - } - for (int k = 0; k < val.length; k += incr) { - switch (cmd) { - case 'm': // moveto - Start a new sub-path (relative) - path.rMoveTo(val[k + 0], val[k + 1]); - currentX += val[k + 0]; - currentY += val[k + 1]; - break; - case 'M': // moveto - Start a new sub-path - path.moveTo(val[k + 0], val[k + 1]); - currentX = val[k + 0]; - currentY = val[k + 1]; - break; - case 'l': // lineto - Draw a line from the current point (relative) - path.rLineTo(val[k + 0], val[k + 1]); - currentX += val[k + 0]; - currentY += val[k + 1]; - break; - case 'L': // lineto - Draw a line from the current point - path.lineTo(val[k + 0], val[k + 1]); - currentX = val[k + 0]; - currentY = val[k + 1]; - break; - case 'z': // closepath - Close the current subpath - case 'Z': // closepath - Close the current subpath - path.close(); - break; - case 'h': // horizontal lineto - Draws a horizontal line (relative) - path.rLineTo(val[k + 0], 0); - currentX += val[k + 0]; - break; - case 'H': // horizontal lineto - Draws a horizontal line - path.lineTo(val[k + 0], currentY); - currentX = val[k + 0]; - break; - case 'v': // vertical lineto - Draws a vertical line from the current point (r) - path.rLineTo(0, val[k + 0]); - currentY += val[k + 0]; - break; - case 'V': // vertical lineto - Draws a vertical line from the current point - path.lineTo(currentX, val[k + 0]); - currentY = val[k + 0]; - break; - case 'c': // curveto - Draws a cubic Bézier curve (relative) - path.rCubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3], - val[k + 4], val[k + 5]); - - ctrlPointX = currentX + val[k + 2]; - ctrlPointY = currentY + val[k + 3]; - currentX += val[k + 4]; - currentY += val[k + 5]; - - break; - case 'C': // curveto - Draws a cubic Bézier curve - path.cubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3], - val[k + 4], val[k + 5]); - currentX = val[k + 4]; - currentY = val[k + 5]; - ctrlPointX = val[k + 2]; - ctrlPointY = val[k + 3]; - break; - case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp) - reflectiveCtrlPointX = 0; - reflectiveCtrlPointY = 0; - if (previousCmd == 'c' || previousCmd == 's' - || previousCmd == 'C' || previousCmd == 'S') { - reflectiveCtrlPointX = currentX - ctrlPointX; - reflectiveCtrlPointY = currentY - ctrlPointY; - } - path.rCubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY, - val[k + 0], val[k + 1], - val[k + 2], val[k + 3]); - - ctrlPointX = currentX + val[k + 0]; - ctrlPointY = currentY + val[k + 1]; - currentX += val[k + 2]; - currentY += val[k + 3]; - break; - case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp) - reflectiveCtrlPointX = currentX; - reflectiveCtrlPointY = currentY; - if (previousCmd == 'c' || previousCmd == 's' - || previousCmd == 'C' || previousCmd == 'S') { - reflectiveCtrlPointX = 2 * currentX - ctrlPointX; - reflectiveCtrlPointY = 2 * currentY - ctrlPointY; - } - path.cubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY, - val[k + 0], val[k + 1], val[k + 2], val[k + 3]); - ctrlPointX = val[k + 0]; - ctrlPointY = val[k + 1]; - currentX = val[k + 2]; - currentY = val[k + 3]; - break; - case 'q': // Draws a quadratic Bézier (relative) - path.rQuadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]); - ctrlPointX = currentX + val[k + 0]; - ctrlPointY = currentY + val[k + 1]; - currentX += val[k + 2]; - currentY += val[k + 3]; - break; - case 'Q': // Draws a quadratic Bézier - path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]); - ctrlPointX = val[k + 0]; - ctrlPointY = val[k + 1]; - currentX = val[k + 2]; - currentY = val[k + 3]; - break; - case 't': // Draws a quadratic Bézier curve(reflective control point)(relative) - reflectiveCtrlPointX = 0; - reflectiveCtrlPointY = 0; - if (previousCmd == 'q' || previousCmd == 't' - || previousCmd == 'Q' || previousCmd == 'T') { - reflectiveCtrlPointX = currentX - ctrlPointX; - reflectiveCtrlPointY = currentY - ctrlPointY; - } - path.rQuadTo(reflectiveCtrlPointX, reflectiveCtrlPointY, - val[k + 0], val[k + 1]); - ctrlPointX = currentX + reflectiveCtrlPointX; - ctrlPointY = currentY + reflectiveCtrlPointY; - currentX += val[k + 0]; - currentY += val[k + 1]; - break; - case 'T': // Draws a quadratic Bézier curve (reflective control point) - reflectiveCtrlPointX = currentX; - reflectiveCtrlPointY = currentY; - if (previousCmd == 'q' || previousCmd == 't' - || previousCmd == 'Q' || previousCmd == 'T') { - reflectiveCtrlPointX = 2 * currentX - ctrlPointX; - reflectiveCtrlPointY = 2 * currentY - ctrlPointY; - } - path.quadTo(reflectiveCtrlPointX, reflectiveCtrlPointY, - val[k + 0], val[k + 1]); - ctrlPointX = reflectiveCtrlPointX; - ctrlPointY = reflectiveCtrlPointY; - currentX = val[k + 0]; - currentY = val[k + 1]; - break; - case 'a': // Draws an elliptical arc - // (rx ry x-axis-rotation large-arc-flag sweep-flag x y) - drawArc(path, - currentX, - currentY, - val[k + 5] + currentX, - val[k + 6] + currentY, - val[k + 0], - val[k + 1], - val[k + 2], - val[k + 3] != 0, - val[k + 4] != 0); - currentX += val[k + 5]; - currentY += val[k + 6]; - ctrlPointX = currentX; - ctrlPointY = currentY; - break; - case 'A': // Draws an elliptical arc - drawArc(path, - currentX, - currentY, - val[k + 5], - val[k + 6], - val[k + 0], - val[k + 1], - val[k + 2], - val[k + 3] != 0, - val[k + 4] != 0); - currentX = val[k + 5]; - currentY = val[k + 6]; - ctrlPointX = currentX; - ctrlPointY = currentY; - break; - } - previousCmd = cmd; - } - current[0] = currentX; - current[1] = currentY; - current[2] = ctrlPointX; - current[3] = ctrlPointY; - } - - private static void drawArc(Path p, - float x0, - float y0, - float x1, - float y1, - float a, - float b, - float theta, - boolean isMoreThanHalf, - boolean isPositiveArc) { - - /* Convert rotation angle from degrees to radians */ - double thetaD = Math.toRadians(theta); - /* Pre-compute rotation matrix entries */ - double cosTheta = Math.cos(thetaD); - double sinTheta = Math.sin(thetaD); - /* Transform (x0, y0) and (x1, y1) into unit space */ - /* using (inverse) rotation, followed by (inverse) scale */ - double x0p = (x0 * cosTheta + y0 * sinTheta) / a; - double y0p = (-x0 * sinTheta + y0 * cosTheta) / b; - double x1p = (x1 * cosTheta + y1 * sinTheta) / a; - double y1p = (-x1 * sinTheta + y1 * cosTheta) / b; - - /* Compute differences and averages */ - double dx = x0p - x1p; - double dy = y0p - y1p; - double xm = (x0p + x1p) / 2; - double ym = (y0p + y1p) / 2; - /* Solve for intersecting unit circles */ - double dsq = dx * dx + dy * dy; - if (dsq == 0.0) { - Log.w(LOGTAG, " Points are coincident"); - return; /* Points are coincident */ - } - double disc = 1.0 / dsq - 1.0 / 4.0; - if (disc < 0.0) { - Log.w(LOGTAG, "Points are too far apart " + dsq); - float adjust = (float) (Math.sqrt(dsq) / 1.99999); - drawArc(p, x0, y0, x1, y1, a * adjust, - b * adjust, theta, isMoreThanHalf, isPositiveArc); - return; /* Points are too far apart */ - } - double s = Math.sqrt(disc); - double sdx = s * dx; - double sdy = s * dy; - double cx; - double cy; - if (isMoreThanHalf == isPositiveArc) { - cx = xm - sdy; - cy = ym + sdx; - } else { - cx = xm + sdy; - cy = ym - sdx; - } - - double eta0 = Math.atan2((y0p - cy), (x0p - cx)); - - double eta1 = Math.atan2((y1p - cy), (x1p - cx)); - - double sweep = (eta1 - eta0); - if (isPositiveArc != (sweep >= 0)) { - if (sweep > 0) { - sweep -= 2 * Math.PI; - } else { - sweep += 2 * Math.PI; - } - } - - cx *= a; - cy *= b; - double tcx = cx; - cx = cx * cosTheta - cy * sinTheta; - cy = tcx * sinTheta + cy * cosTheta; - - arcToBezier(p, cx, cy, a, b, x0, y0, thetaD, eta0, sweep); - } - - /** - * Converts an arc to cubic Bezier segments and records them in p. - * - * @param p The target for the cubic Bezier segments - * @param cx The x coordinate center of the ellipse - * @param cy The y coordinate center of the ellipse - * @param a The radius of the ellipse in the horizontal direction - * @param b The radius of the ellipse in the vertical direction - * @param e1x E(eta1) x coordinate of the starting point of the arc - * @param e1y E(eta2) y coordinate of the starting point of the arc - * @param theta The angle that the ellipse bounding rectangle makes with horizontal plane - * @param start The start angle of the arc on the ellipse - * @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse - */ - private static void arcToBezier(Path p, - double cx, - double cy, - double a, - double b, - double e1x, - double e1y, - double theta, - double start, - double sweep) { - // Taken from equations at: http://spaceroots.org/documents/ellipse/node8.html - // and http://www.spaceroots.org/documents/ellipse/node22.html - - // Maximum of 45 degrees per cubic Bezier segment - int numSegments = Math.abs((int) Math.ceil(sweep * 4 / Math.PI)); - - double eta1 = start; - double cosTheta = Math.cos(theta); - double sinTheta = Math.sin(theta); - double cosEta1 = Math.cos(eta1); - double sinEta1 = Math.sin(eta1); - double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1); - double ep1y = (-a * sinTheta * sinEta1) + (b * cosTheta * cosEta1); - - double anglePerSegment = sweep / numSegments; - for (int i = 0; i < numSegments; i++) { - double eta2 = eta1 + anglePerSegment; - double sinEta2 = Math.sin(eta2); - double cosEta2 = Math.cos(eta2); - double e2x = cx + (a * cosTheta * cosEta2) - (b * sinTheta * sinEta2); - double e2y = cy + (a * sinTheta * cosEta2) + (b * cosTheta * sinEta2); - double ep2x = -a * cosTheta * sinEta2 - b * sinTheta * cosEta2; - double ep2y = -a * sinTheta * sinEta2 + b * cosTheta * cosEta2; - double tanDiff2 = Math.tan((eta2 - eta1) / 2); - double alpha = - Math.sin(eta2 - eta1) * (Math.sqrt(4 + (3 * tanDiff2 * tanDiff2)) - 1) / 3; - double q1x = e1x + alpha * ep1x; - double q1y = e1y + alpha * ep1y; - double q2x = e2x - alpha * ep2x; - double q2y = e2y - alpha * ep2y; - - p.cubicTo((float) q1x, - (float) q1y, - (float) q2x, - (float) q2y, - (float) e2x, - (float) e2y); - eta1 = eta2; - e1x = e2x; - e1y = e2y; - ep1x = ep2x; - ep1y = ep2y; - } - } - } } diff --git a/libs/hwui/Interpolator.cpp b/libs/hwui/Interpolator.cpp index 1f84b86bca73..fc0e8a059f22 100644 --- a/libs/hwui/Interpolator.cpp +++ b/libs/hwui/Interpolator.cpp @@ -112,6 +112,10 @@ float LUTInterpolator::interpolate(float input) { int i1 = (int) ipart; int i2 = MathUtils::min(i1 + 1, mSize - 1); + LOG_ALWAYS_FATAL_IF(i1 < 0 || i2 < 0, "negatives in interpolation!" + " i1=%d, i2=%d, input=%f, lutpos=%f, size=%zu, values=%p, ipart=%f, weight=%f", + i1, i2, input, lutpos, mSize, mValues, ipart, weight); + float v1 = mValues[i1]; float v2 = mValues[i2]; diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java index e05aef06e238..bd2be1b94f37 100644 --- a/media/java/android/media/AudioFormat.java +++ b/media/java/android/media/AudioFormat.java @@ -25,10 +25,10 @@ import java.lang.annotation.RetentionPolicy; * The AudioFormat class is used to access a number of audio format and * channel configuration constants. They are for instance used * in {@link AudioTrack} and {@link AudioRecord}. - * + * */ public class AudioFormat { - + //--------------------------------------------------------- // Constants //-------------------- @@ -44,6 +44,10 @@ public class AudioFormat { public static final int ENCODING_PCM_8BIT = 3; /** Audio data format: single-precision floating-point per sample */ public static final int ENCODING_PCM_FLOAT = 4; + /** Audio data format: AC-3 compressed */ + public static final int ENCODING_AC3 = 5; + /** Audio data format: E-AC-3 compressed */ + public static final int ENCODING_E_AC3 = 6; /** Invalid audio channel configuration */ /** @deprecated use CHANNEL_INVALID instead */ @@ -152,11 +156,44 @@ public class AudioFormat { switch (audioFormat) { case ENCODING_PCM_8BIT: return 1; + case ENCODING_PCM_16BIT: + case ENCODING_DEFAULT: + return 2; case ENCODING_PCM_FLOAT: return 4; + case ENCODING_INVALID: + default: + throw new IllegalArgumentException("Bad audio format " + audioFormat); + } + } + + /** @hide */ + public static boolean isValidEncoding(int audioFormat) + { + switch (audioFormat) { + case ENCODING_PCM_8BIT: case ENCODING_PCM_16BIT: + case ENCODING_PCM_FLOAT: + case ENCODING_AC3: + case ENCODING_E_AC3: + return true; + default: + return false; + } + } + + /** @hide */ + public static boolean isEncodingLinearPcm(int audioFormat) + { + switch (audioFormat) { + case ENCODING_PCM_8BIT: + case ENCODING_PCM_16BIT: + case ENCODING_PCM_FLOAT: case ENCODING_DEFAULT: - return 2; + return true; + case ENCODING_AC3: + case ENCODING_E_AC3: + return false; case ENCODING_INVALID: default: throw new IllegalArgumentException("Bad audio format " + audioFormat); @@ -236,7 +273,9 @@ public class AudioFormat { * @param encoding one of {@link AudioFormat#ENCODING_DEFAULT}, * {@link AudioFormat#ENCODING_PCM_8BIT}, * {@link AudioFormat#ENCODING_PCM_16BIT}, - * {@link AudioFormat#ENCODING_PCM_FLOAT}. + * {@link AudioFormat#ENCODING_PCM_FLOAT}, + * {@link AudioFormat#ENCODING_AC3}, + * {@link AudioFormat#ENCODING_E_AC3}. * @return the same Builder instance. * @throws java.lang.IllegalArgumentException */ @@ -248,6 +287,8 @@ public class AudioFormat { case ENCODING_PCM_8BIT: case ENCODING_PCM_16BIT: case ENCODING_PCM_FLOAT: + case ENCODING_AC3: + case ENCODING_E_AC3: mEncoding = encoding; break; case ENCODING_INVALID: @@ -311,7 +352,9 @@ public class AudioFormat { ENCODING_DEFAULT, ENCODING_PCM_8BIT, ENCODING_PCM_16BIT, - ENCODING_PCM_FLOAT + ENCODING_PCM_FLOAT, + ENCODING_AC3, + ENCODING_E_AC3 }) @Retention(RetentionPolicy.SOURCE) public @interface Encoding {} diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 323849830dd3..47b6024c113e 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -1254,11 +1254,6 @@ public class AudioManager { * call {@link #stopBluetoothSco()} to clear the request and turn down the bluetooth connection. * <p>Even if a SCO connection is established, the following restrictions apply on audio * output streams so that they can be routed to SCO headset: - * <p>NOTE: up to and including API version - * {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}, this method initiates a virtual - * voice call to the bluetooth headset. - * After API version {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2} only a raw SCO audio - * connection is established. * <ul> * <li> the stream type must be {@link #STREAM_VOICE_CALL} </li> * <li> the format must be mono </li> @@ -1274,6 +1269,11 @@ public class AudioManager { * it will be ignored. Similarly, if a call is received or sent while an application * is using the SCO connection, the connection will be lost for the application and NOT * returned automatically when the call ends. + * <p>NOTE: up to and including API version + * {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}, this method initiates a virtual + * voice call to the bluetooth headset. + * After API version {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2} only a raw SCO audio + * connection is established. * @see #stopBluetoothSco() * @see #ACTION_SCO_AUDIO_STATE_UPDATED */ @@ -1287,13 +1287,38 @@ public class AudioManager { } /** + * Start bluetooth SCO audio connection in virtual call mode. + * <p>Requires Permission: + * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}. + * <p>Similar to {@link #startBluetoothSco()} with explicit selection of virtual call mode. + * Telephony and communication applications (VoIP, Video Chat) should preferably select + * virtual call mode. + * Applications using voice input for search or commands should first try raw audio connection + * with {@link #startBluetoothSco()} and fall back to startBluetoothScoVirtualCall() in case of + * failure. + * @see #startBluetoothSco() + * @see #stopBluetoothSco() + * @see #ACTION_SCO_AUDIO_STATE_UPDATED + */ + public void startBluetoothScoVirtualCall() { + IAudioService service = getService(); + try { + service.startBluetoothScoVirtualCall(mICallBack); + } catch (RemoteException e) { + Log.e(TAG, "Dead object in startBluetoothScoVirtualCall", e); + } + } + + /** * Stop bluetooth SCO audio connection. * <p>Requires Permission: * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}. * <p>This method must be called by applications having requested the use of - * bluetooth SCO audio with {@link #startBluetoothSco()} - * when finished with the SCO connection or if connection fails. + * bluetooth SCO audio with {@link #startBluetoothSco()} or + * {@link #startBluetoothScoVirtualCall()} when finished with the SCO connection or + * if connection fails. * @see #startBluetoothSco() + * @see #startBluetoothScoVirtualCall() */ public void stopBluetoothSco(){ IAudioService service = getService(); @@ -1616,26 +1641,6 @@ public class AudioManager { } /** - * @hide - * If the stream is active locally or remotely, adjust its volume according to the enforced - * priority rules. - * Note: only AudioManager.STREAM_MUSIC is supported at the moment - */ - public void adjustLocalOrRemoteStreamVolume(int streamType, int direction) { - if (streamType != STREAM_MUSIC) { - Log.w(TAG, "adjustLocalOrRemoteStreamVolume() doesn't support stream " + streamType); - } - IAudioService service = getService(); - try { - service.adjustLocalOrRemoteStreamVolume(streamType, direction, - mContext.getOpPackageName()); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in adjustLocalOrRemoteStreamVolume", e); - } - } - - - /** * Return a new audio session identifier not associated with any player or effect. * It can for instance be used to create one of the {@link android.media.audiofx.AudioEffect} * objects. @@ -2974,7 +2979,9 @@ public class AudioManager { /** @hide */ public static final int ERROR_NO_INIT = AudioSystem.NO_INIT; - /** @hide + /** + * An error code indicating that the object reporting it is no longer valid and needs to + * be recreated. */ public static final int ERROR_DEAD_OBJECT = AudioSystem.DEAD_OBJECT; diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 72f4a580532c..6b7d7a9b101e 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -830,24 +830,6 @@ public class AudioService extends IAudioService.Stub { } /** @see AudioManager#adjustVolume(int, int) */ - public void adjustVolume(int direction, int flags, String callingPackage) { - adjustSuggestedStreamVolume(direction, AudioManager.USE_DEFAULT_STREAM_TYPE, flags, - callingPackage); - } - - /** @see AudioManager#adjustLocalOrRemoteStreamVolume(int, int) with current assumption - * on streamType: fixed to STREAM_MUSIC */ - public void adjustLocalOrRemoteStreamVolume(int streamType, int direction, - String callingPackage) { - if (DEBUG_VOL) Log.d(TAG, "adjustLocalOrRemoteStreamVolume(dir="+direction+")"); - if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)) { - adjustStreamVolume(AudioSystem.STREAM_MUSIC, direction, 0, callingPackage); - } else if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) { - mMediaFocusControl.adjustRemoteVolume(AudioSystem.STREAM_MUSIC, direction, 0); - } - } - - /** @see AudioManager#adjustVolume(int, int) */ public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags, String callingPackage) { if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream="+suggestedStreamType); @@ -2074,7 +2056,19 @@ public class AudioService extends IAudioService.Stub { } /** @see AudioManager#startBluetoothSco() */ - public void startBluetoothSco(IBinder cb, int targetSdkVersion){ + public void startBluetoothSco(IBinder cb, int targetSdkVersion) { + int scoAudioMode = + (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ? + SCO_MODE_VIRTUAL_CALL : SCO_MODE_RAW; + startBluetoothScoInt(cb, scoAudioMode); + } + + /** @see AudioManager#startBluetoothScoVirtualCall() */ + public void startBluetoothScoVirtualCall(IBinder cb) { + startBluetoothScoInt(cb, SCO_MODE_VIRTUAL_CALL); + } + + void startBluetoothScoInt(IBinder cb, int scoAudioMode){ if (!checkAudioSettingsPermission("startBluetoothSco()") || !mSystemReady) { return; @@ -2086,7 +2080,7 @@ public class AudioService extends IAudioService.Stub { // The caller identity must be cleared after getScoClient() because it is needed if a new // client is created. final long ident = Binder.clearCallingIdentity(); - client.incCount(targetSdkVersion); + client.incCount(scoAudioMode); Binder.restoreCallingIdentity(ident); } @@ -2132,9 +2126,9 @@ public class AudioService extends IAudioService.Stub { } } - public void incCount(int targetSdkVersion) { + public void incCount(int scoAudioMode) { synchronized(mScoClients) { - requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, targetSdkVersion); + requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode); if (mStartcount == 0) { try { mCb.linkToDeath(this, 0); @@ -2204,7 +2198,7 @@ public class AudioService extends IAudioService.Stub { } } - private void requestScoState(int state, int targetSdkVersion) { + private void requestScoState(int state, int scoAudioMode) { checkScoAudioState(); if (totalCount() == 0) { if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) { @@ -2219,9 +2213,7 @@ public class AudioService extends IAudioService.Stub { (mScoAudioState == SCO_STATE_INACTIVE || mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) { if (mScoAudioState == SCO_STATE_INACTIVE) { - mScoAudioMode = - (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ? - SCO_MODE_VIRTUAL_CALL : SCO_MODE_RAW; + mScoAudioMode = scoAudioMode; if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) { boolean status; if (mScoAudioMode == SCO_MODE_RAW) { @@ -4482,22 +4474,6 @@ public class AudioService extends IAudioService.Stub { mMediaFocusControl.setPlaybackInfoForRcc(rccId, what, value); } - public void dispatchMediaKeyEvent(KeyEvent keyEvent) { - if (DEBUG_SESSIONS) { - int pid = getCallingPid(); - Log.w(TAG, "Call to dispatchMediaKeyEvent from " + pid); - } - MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(keyEvent, false); - } - - public void dispatchMediaKeyEventUnderWakelock(KeyEvent keyEvent) { - if (DEBUG_SESSIONS) { - int pid = getCallingPid(); - Log.w(TAG, "Call to dispatchMediaKeyEventUnderWakelock from " + pid); - } - MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(keyEvent, true); - } - //========================================================================================== // Audio Focus //========================================================================================== diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index cfd9c3bc32c9..3a72833db2c9 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -457,25 +457,19 @@ public class AudioTrack //-------------- // audio format - switch (audioFormat) { - case AudioFormat.ENCODING_DEFAULT: - mAudioFormat = AudioFormat.ENCODING_PCM_16BIT; - break; - case AudioFormat.ENCODING_PCM_16BIT: - case AudioFormat.ENCODING_PCM_8BIT: - case AudioFormat.ENCODING_PCM_FLOAT: - mAudioFormat = audioFormat; - break; - default: - throw new IllegalArgumentException("Unsupported sample encoding." - + " Should be ENCODING_PCM_8BIT or ENCODING_PCM_16BIT" - + " or ENCODING_PCM_FLOAT" - + "."); + if (audioFormat == AudioFormat.ENCODING_DEFAULT) { + audioFormat = AudioFormat.ENCODING_PCM_16BIT; + } + + if (!AudioFormat.isValidEncoding(audioFormat)) { + throw new IllegalArgumentException("Unsupported audio encoding."); } + mAudioFormat = audioFormat; //-------------- // audio load mode - if ( (mode != MODE_STREAM) && (mode != MODE_STATIC) ) { + if (((mode != MODE_STREAM) && (mode != MODE_STATIC)) || + ((mode != MODE_STREAM) && !AudioFormat.isEncodingLinearPcm(mAudioFormat))) { throw new IllegalArgumentException("Invalid mode."); } mDataLoadMode = mode; @@ -522,8 +516,13 @@ public class AudioTrack private void audioBuffSizeCheck(int audioBufferSize) { // NB: this section is only valid with PCM data. // To update when supporting compressed formats - int frameSizeInBytes = mChannelCount - * (AudioFormat.getBytesPerSample(mAudioFormat)); + int frameSizeInBytes; + if (AudioFormat.isEncodingLinearPcm(mAudioFormat)) { + frameSizeInBytes = mChannelCount + * (AudioFormat.getBytesPerSample(mAudioFormat)); + } else { + frameSizeInBytes = 1; + } if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) { throw new IllegalArgumentException("Invalid audio buffer size."); } @@ -757,9 +756,7 @@ public class AudioTrack } } - if ((audioFormat != AudioFormat.ENCODING_PCM_16BIT) - && (audioFormat != AudioFormat.ENCODING_PCM_8BIT) - && (audioFormat != AudioFormat.ENCODING_PCM_FLOAT)) { + if (!AudioFormat.isValidEncoding(audioFormat)) { loge("getMinBufferSize(): Invalid audio format."); return ERROR_BAD_VALUE; } @@ -1164,7 +1161,9 @@ public class AudioTrack * @param sizeInBytes the number of bytes to read in audioData after the offset. * @return the number of bytes that were written or {@link #ERROR_INVALID_OPERATION} * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if - * the parameters don't resolve to valid data and indexes. + * the parameters don't resolve to valid data and indexes, or + * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and + * needs to be recreated. */ public int write(byte[] audioData, int offsetInBytes, int sizeInBytes) { @@ -1213,7 +1212,7 @@ public class AudioTrack public int write(short[] audioData, int offsetInShorts, int sizeInShorts) { - if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) { + if (mState == STATE_UNINITIALIZED || mAudioFormat != AudioFormat.ENCODING_PCM_16BIT) { return ERROR_INVALID_OPERATION; } @@ -1473,7 +1472,6 @@ public class AudioTrack void onPeriodicNotification(AudioTrack track); } - //--------------------------------------------------------- // Inner classes //-------------------- diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index c29e967868fe..41e691d55303 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -36,13 +36,8 @@ import android.view.KeyEvent; */ interface IAudioService { - void adjustVolume(int direction, int flags, String callingPackage); - boolean isLocalOrRemoteMusicActive(); - oneway void adjustLocalOrRemoteStreamVolume(int streamType, int direction, - String callingPackage); - void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags, String callingPackage); @@ -127,9 +122,6 @@ interface IAudioService { int getCurrentAudioFocus(); - oneway void dispatchMediaKeyEvent(in KeyEvent keyEvent); - void dispatchMediaKeyEventUnderWakelock(in KeyEvent keyEvent); - void registerMediaButtonIntent(in PendingIntent pi, in ComponentName c, IBinder token); oneway void unregisterMediaButtonIntent(in PendingIntent pi); @@ -225,6 +217,7 @@ interface IAudioService { oneway void registerRemoteVolumeObserverForRcc(int rccId, in IRemoteVolumeObserver rvo); void startBluetoothSco(IBinder cb, int targetSdkVersion); + void startBluetoothScoVirtualCall(IBinder cb); void stopBluetoothSco(IBinder cb); void forceVolumeControlStream(int streamType, IBinder cb); diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java index 5ca7daa6560f..87a43e4828fa 100644 --- a/media/java/android/media/session/MediaController.java +++ b/media/java/android/media/session/MediaController.java @@ -70,14 +70,7 @@ public final class MediaController { * @hide */ public static MediaController fromBinder(ISessionController sessionBinder) { - MediaController controller = new MediaController(sessionBinder); - try { - controller.mSessionBinder.registerCallbackListener(controller.mCbStub); - } catch (RemoteException e) { - Log.wtf(TAG, "MediaController created with expired token", e); - controller = null; - } - return controller; + return new MediaController(sessionBinder); } /** @@ -305,7 +298,7 @@ public final class MediaController { mSessionBinder.registerCallbackListener(mCbStub); mCbRegistered = true; } catch (RemoteException e) { - Log.d(TAG, "Dead object in registerCallback", e); + Log.e(TAG, "Dead object in registerCallback", e); } } } @@ -314,14 +307,23 @@ public final class MediaController { if (cb == null) { throw new IllegalArgumentException("Callback cannot be null"); } + boolean success = false; for (int i = mCallbacks.size() - 1; i >= 0; i--) { MessageHandler handler = mCallbacks.get(i); if (cb == handler.mCallback) { mCallbacks.remove(i); - return true; + success = true; } } - return false; + if (mCbRegistered && mCallbacks.size() == 0) { + try { + mSessionBinder.unregisterCallbackListener(mCbStub); + } catch (RemoteException e) { + Log.e(TAG, "Dead object in removeCallbackLocked"); + } + mCbRegistered = false; + } + return success; } private MessageHandler getHandlerForCallbackLocked(Callback cb) { diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java index 7dba21da4c9d..b6bb578fe920 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java @@ -205,6 +205,37 @@ public class CameraBinderTest extends AndroidTestCase { } } + @SmallTest + public void testConnectLegacy() throws Exception { + final int CAMERA_HAL_API_VERSION_1_0 = 0x100; + for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) { + ICamera cameraUser = null; + ICameraClient dummyCallbacks = new DummyCameraClient(); + + String clientPackageName = getContext().getPackageName(); + + BinderHolder holder = new BinderHolder(); + + try { + CameraBinderDecorator.newInstance(mUtils.getCameraService()) + .connectLegacy(dummyCallbacks, cameraId, CAMERA_HAL_API_VERSION_1_0, + clientPackageName, + CameraBinderTestUtils.USE_CALLING_UID, holder); + cameraUser = ICamera.Stub.asInterface(holder.getBinder()); + assertNotNull(String.format("Camera %s was null", cameraId), cameraUser); + + Log.v(TAG, String.format("Camera %s connected as HAL1 legacy device", cameraId)); + } catch (RuntimeException e) { + // Not all camera device support openLegacy. + Log.i(TAG, "Unable to open camera as HAL1 legacy camera device " + e); + } finally { + if (cameraUser != null) { + cameraUser.disconnect(); + } + } + } + } + static class DummyCameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub { /* diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraOpenTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraOpenTest.java new file mode 100644 index 000000000000..14bbe44c1516 --- /dev/null +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraOpenTest.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 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 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.mediaframeworktest.unit; + +import android.hardware.Camera; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.Log; + +/** + * <pre> + * adb shell am instrument \ + * -e class 'com.android.mediaframeworktest.unit.CameraOpenTest' \ + * -w com.android.mediaframeworktest/.MediaFrameworkUnitTestRunner + * </pre> + */ +public class CameraOpenTest extends junit.framework.TestCase { + private static String TAG = "CameraOpenTest"; + + private Camera mCamera; + + /** + * Test @hide android.hardware.Camera#openLegacy API that cannot be tested in CTS. + */ + @SmallTest + public void testOpenLegacy() { + int nCameras = Camera.getNumberOfCameras(); + for (int id = 0; id < nCameras; id++) { + try { + mCamera.openLegacy(id, Camera.CAMERA_HAL_API_VERSION_1_0); + } catch (RuntimeException e) { + Log.i(TAG, "Unable to open camera as HAL1 legacy camera device " + e); + } finally { + if (mCamera != null) { + mCamera.release(); + } + } + } + } +} diff --git a/media/tests/ScoAudioTest/res/layout/scoaudiotest.xml b/media/tests/ScoAudioTest/res/layout/scoaudiotest.xml index b769a0c6a092..acb77677793c 100644 --- a/media/tests/ScoAudioTest/res/layout/scoaudiotest.xml +++ b/media/tests/ScoAudioTest/res/layout/scoaudiotest.xml @@ -125,6 +125,11 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/audiomanagertwo" /> + <CheckBox + android:id="@+id/useVirtualCallCheckBox" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/useVirtualCallCheckText" /> </LinearLayout> diff --git a/media/tests/ScoAudioTest/res/values/strings.xml b/media/tests/ScoAudioTest/res/values/strings.xml index c3ff6d5b0fe5..b0284e26ac50 100644 --- a/media/tests/ScoAudioTest/res/values/strings.xml +++ b/media/tests/ScoAudioTest/res/values/strings.xml @@ -10,5 +10,5 @@ <string name="tts_speak">Speak TTS</string> <string name="tts_to_file">TTS to file</string> <string name="audiomanagertwo">Use different AudioManager for starting SCO</string> - + <string name="useVirtualCallCheckText">Use Virtual Call</string> </resources> diff --git a/media/tests/ScoAudioTest/src/com/android/scoaudiotest/ScoAudioTest.java b/media/tests/ScoAudioTest/src/com/android/scoaudiotest/ScoAudioTest.java index 030464034516..7e21876accb2 100644 --- a/media/tests/ScoAudioTest/src/com/android/scoaudiotest/ScoAudioTest.java +++ b/media/tests/ScoAudioTest/src/com/android/scoaudiotest/ScoAudioTest.java @@ -207,16 +207,25 @@ public class ScoAudioTest extends Activity { if (mForceScoOn != isChecked) { mForceScoOn = isChecked; AudioManager mngr = mAudioManager; + boolean useVirtualCall = false; CheckBox box = (CheckBox) findViewById(R.id.useSecondAudioManager); if (box.isChecked()) { Log.i(TAG, "Using 2nd audio manager"); mngr = mAudioManager2; } + box = (CheckBox) findViewById(R.id.useVirtualCallCheckBox); + useVirtualCall = box.isChecked(); if (mForceScoOn) { - Log.e(TAG, "startBluetoothSco() IN"); - mngr.startBluetoothSco(); - Log.e(TAG, "startBluetoothSco() OUT"); + if (useVirtualCall) { + Log.e(TAG, "startBluetoothScoVirtualCall() IN"); + mngr.startBluetoothScoVirtualCall(); + Log.e(TAG, "startBluetoothScoVirtualCall() OUT"); + } else { + Log.e(TAG, "startBluetoothSco() IN"); + mngr.startBluetoothSco(); + Log.e(TAG, "startBluetoothSco() OUT"); + } } else { Log.e(TAG, "stopBluetoothSco() IN"); mngr.stopBluetoothSco(); diff --git a/packages/DocumentsUI/res/values-km-rKH/strings.xml b/packages/DocumentsUI/res/values-km-rKH/strings.xml index 8c9030dc3403..e8944ec2ad72 100644 --- a/packages/DocumentsUI/res/values-km-rKH/strings.xml +++ b/packages/DocumentsUI/res/values-km-rKH/strings.xml @@ -20,14 +20,14 @@ <string name="title_open" msgid="4353228937663917801">"បើកពី"</string> <string name="title_save" msgid="2433679664882857999">"រក្សាទុកទៅ"</string> <string name="menu_create_dir" msgid="5947289605844398389">"បង្កើតថត"</string> - <string name="menu_grid" msgid="6878021334497835259">"ទិដ្ឋភាពក្រឡា"</string> + <string name="menu_grid" msgid="6878021334497835259">"ទិដ្ឋភាពក្រឡា"</string> <string name="menu_list" msgid="7279285939892417279">"ទិដ្ឋភាពបញ្ជី"</string> <string name="menu_sort" msgid="7677740407158414452">"តម្រៀបតាម"</string> <string name="menu_search" msgid="3816712084502856974">"ស្វែងរក"</string> <string name="menu_settings" msgid="6008033148948428823">"ការកំណត់"</string> <string name="menu_open" msgid="432922957274920903">"បើក"</string> <string name="menu_save" msgid="2394743337684426338">"រក្សាទុក"</string> - <string name="menu_share" msgid="3075149983979628146">"ចែករំលែក"</string> + <string name="menu_share" msgid="3075149983979628146">"ចែករំលែក"</string> <string name="menu_delete" msgid="8138799623850614177">"លុប"</string> <string name="menu_select" msgid="8711270657353563424">"ជ្រើស \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string> <string name="mode_selected_count" msgid="459111894725594625">"បានជ្រើស <xliff:g id="COUNT">%1$d</xliff:g>"</string> @@ -48,7 +48,7 @@ <string name="pref_advanced_devices" msgid="903257239609301276">"បង្ហាញឧបករណ៍កម្រិតខ្ពស់"</string> <string name="pref_file_size" msgid="2826879315743961459">"បង្ហាញទំហំឯកសារ"</string> <string name="pref_device_size" msgid="3542106883278997222">"បង្ហាញទំហំឧបករណ៍"</string> - <string name="empty" msgid="7858882803708117596">"គ្មានធាតុ"</string> + <string name="empty" msgid="7858882803708117596">"គ្មានធាតុ"</string> <string name="toast_no_application" msgid="1339885974067891667">"មិនអាចបើកឯកសារ"</string> <string name="toast_failed_delete" msgid="2180678019407244069">"មិនអាចលុបឯកសារមួយចំនួន"</string> <string name="share_via" msgid="8966594246261344259">"ចែករំលែកតាម"</string> diff --git a/packages/Keyguard/res/values-ca/strings.xml b/packages/Keyguard/res/values-ca/strings.xml index d23d4871cd41..f258224b27c8 100644 --- a/packages/Keyguard/res/values-ca/strings.xml +++ b/packages/Keyguard/res/values-ca/strings.xml @@ -59,7 +59,7 @@ <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"S\'ha iniciat la reorganització del widget."</string> <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Ha finalitzat la reorganització del widget."</string> <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"S\'ha suprimit el widget de <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string> - <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Amplia l\'àrea de desbloqueig."</string> + <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Desplega l\'àrea de desbloqueig."</string> <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Desbloqueig lliscant el dit"</string> <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueig mitjançant patró"</string> <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Desbloqueig facial"</string> diff --git a/packages/Keyguard/res/values-km-rKH/strings.xml b/packages/Keyguard/res/values-km-rKH/strings.xml index c26b1b493baa..ecdad8c57ab9 100644 --- a/packages/Keyguard/res/values-km-rKH/strings.xml +++ b/packages/Keyguard/res/values-km-rKH/strings.xml @@ -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">"ប្ដូររបៀប"</string> @@ -120,7 +120,7 @@ <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_password_hint" msgid="9057289103827298549">"ពាក្យសម្ងាត់"</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> diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java index d2bf30c17256..ab1827145101 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java @@ -71,6 +71,7 @@ public class KeyguardHostView extends KeyguardViewBase { private AppWidgetHost mAppWidgetHost; private AppWidgetManager mAppWidgetManager; private KeyguardWidgetPager mAppWidgetContainer; + // TODO remove transport control references, these don't exist anymore private KeyguardTransportControlView mTransportControl; private int mAppWidgetToShow; @@ -235,36 +236,6 @@ public class KeyguardHostView extends KeyguardViewBase { mKeyguardMultiUserSelectorView.finalizeActiveUserView(true); } } - @Override - public void onMusicClientIdChanged( - int clientGeneration, boolean clearing, android.app.PendingIntent intent) { - // Set transport state to invisible until we know music is playing (below) - if (DEBUGXPORT && (mClientGeneration != clientGeneration || clearing)) { - Log.v(TAG, (clearing ? "hide" : "show") + " transport, gen:" + clientGeneration); - } - mClientGeneration = clientGeneration; - final int newState = (clearing ? TRANSPORT_GONE - : (mTransportState == TRANSPORT_VISIBLE ? - TRANSPORT_VISIBLE : TRANSPORT_INVISIBLE)); - if (newState != mTransportState) { - mTransportState = newState; - if (DEBUGXPORT) Log.v(TAG, "update widget: transport state changed"); - KeyguardHostView.this.post(mSwitchPageRunnable); - } - } - @Override - public void onMusicPlaybackStateChanged(int playbackState, long eventTime) { - if (DEBUGXPORT) Log.v(TAG, "music state changed: " + playbackState); - if (mTransportState != TRANSPORT_GONE) { - final int newState = (isMusicPlaying(playbackState) ? - TRANSPORT_VISIBLE : TRANSPORT_INVISIBLE); - if (newState != mTransportState) { - mTransportState = newState; - if (DEBUGXPORT) Log.v(TAG, "update widget: play state changed"); - KeyguardHostView.this.post(mSwitchPageRunnable); - } - } - } }; private static final boolean isMusicPlaying(int playbackState) { diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java index 79187552f7c1..38316ff9de90 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java @@ -166,6 +166,11 @@ public class KeyguardStatusView extends GridLayout { return info; } + @Override + public boolean hasOverlappingRendering() { + return false; + } + // DateFormat.getBestDateTimePattern is extremely expensive, and refresh is called often. // This is an optimization to ensure we only recompute the patterns when the inputs change. private static final class Patterns { diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java index 668e1ef684cc..bf34705dd1a6 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -91,8 +91,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private static final int MSG_KEYGUARD_VISIBILITY_CHANGED = 312; protected static final int MSG_BOOT_COMPLETED = 313; private static final int MSG_USER_SWITCH_COMPLETE = 314; - private static final int MSG_SET_CURRENT_CLIENT_ID = 315; - protected static final int MSG_SET_PLAYBACK_STATE = 316; protected static final int MSG_USER_INFO_CHANGED = 317; protected static final int MSG_REPORT_EMERGENCY_CALL_ACTION = 318; private static final int MSG_SCREEN_TURNED_ON = 319; @@ -184,12 +182,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { case MSG_BOOT_COMPLETED: handleBootCompleted(); break; - case MSG_SET_CURRENT_CLIENT_ID: - handleSetGenerationId(msg.arg1, msg.arg2 != 0, (PendingIntent) msg.obj); - break; - case MSG_SET_PLAYBACK_STATE: - handleSetPlaybackState(msg.arg1, msg.arg2, (Long) msg.obj); - break; case MSG_USER_INFO_CHANGED: handleUserInfoChanged(msg.arg1); break; @@ -206,8 +198,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } }; - private AudioManager mAudioManager; - private SparseBooleanArray mUserHasTrust = new SparseBooleanArray(); @Override @@ -257,49 +247,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private DisplayClientState mDisplayClientState = new DisplayClientState(); - /** - * This currently implements the bare minimum required to enable showing and hiding - * KeyguardTransportControl. There's a lot of client state to maintain which is why - * KeyguardTransportControl maintains an independent connection while it's showing. - */ - private final IRemoteControlDisplay.Stub mRemoteControlDisplay = - new IRemoteControlDisplay.Stub() { - - public void setPlaybackState(int generationId, int state, long stateChangeTimeMs, - long currentPosMs, float speed) { - Message msg = mHandler.obtainMessage(MSG_SET_PLAYBACK_STATE, - generationId, state, stateChangeTimeMs); - mHandler.sendMessage(msg); - } - - public void setMetadata(int generationId, Bundle metadata) { - - } - - public void setTransportControlInfo(int generationId, int flags, int posCapabilities) { - - } - - public void setArtwork(int generationId, Bitmap bitmap) { - - } - - public void setAllMetadata(int generationId, Bundle metadata, Bitmap bitmap) { - - } - - public void setEnabled(boolean enabled) { - // no-op: this RemoteControlDisplay is not subject to being disabled. - } - - public void setCurrentClientId(int clientGeneration, PendingIntent mediaIntent, - boolean clearing) throws RemoteException { - Message msg = mHandler.obtainMessage(MSG_SET_CURRENT_CLIENT_ID, - clientGeneration, (clearing ? 1 : 0), mediaIntent); - mHandler.sendMessage(msg); - } - }; - private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { @@ -501,38 +448,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } - protected void handleSetGenerationId(int clientGeneration, boolean clearing, PendingIntent p) { - mDisplayClientState.clientGeneration = clientGeneration; - mDisplayClientState.clearing = clearing; - mDisplayClientState.intent = p; - if (DEBUG) - Log.v(TAG, "handleSetGenerationId(g=" + clientGeneration + ", clear=" + clearing + ")"); - for (int i = 0; i < mCallbacks.size(); i++) { - KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); - if (cb != null) { - cb.onMusicClientIdChanged(clientGeneration, clearing, p); - } - } - } - - protected void handleSetPlaybackState(int generationId, int playbackState, long eventTime) { - if (DEBUG) - Log.v(TAG, "handleSetPlaybackState(gen=" + generationId - + ", state=" + playbackState + ", t=" + eventTime + ")"); - mDisplayClientState.playbackState = playbackState; - mDisplayClientState.playbackEventTime = eventTime; - if (generationId == mDisplayClientState.clientGeneration) { - for (int i = 0; i < mCallbacks.size(); i++) { - KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); - if (cb != null) { - cb.onMusicPlaybackStateChanged(playbackState, eventTime); - } - } - } else { - Log.w(TAG, "Ignoring generation id " + generationId + " because it's not current"); - } - } - private void handleUserInfoChanged(int userId) { for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); @@ -694,8 +609,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { protected void handleBootCompleted() { if (mBootCompleted) return; mBootCompleted = true; - mAudioManager = new AudioManager(mContext); - mAudioManager.registerRemoteControlDisplay(mRemoteControlDisplay); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -1013,12 +926,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { callback.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn); callback.onClockVisibilityChanged(); callback.onSimStateChanged(mSimState); - callback.onMusicClientIdChanged( - mDisplayClientState.clientGeneration, - mDisplayClientState.clearing, - mDisplayClientState.intent); - callback.onMusicPlaybackStateChanged(mDisplayClientState.playbackState, - mDisplayClientState.playbackEventTime); } public void sendKeyguardVisibilityChanged(boolean showing) { diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java index bcdf18fefc52..01600d208d7e 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java @@ -144,18 +144,6 @@ public class KeyguardUpdateMonitorCallback { public void onBootCompleted() { } /** - * Called when audio client attaches or detaches from AudioManager. - */ - public void onMusicClientIdChanged(int clientGeneration, boolean clearing, PendingIntent intent) { } - - /** - * Called when the audio playback state changes. - * @param playbackState - * @param eventTime - */ - public void onMusicPlaybackStateChanged(int playbackState, long eventTime) { } - - /** * Called when the emergency call button is pressed. */ void onEmergencyCallAction() { } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java index 3e444fa3ceb3..8945b15c1915 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java @@ -341,11 +341,11 @@ public abstract class KeyguardViewBase extends FrameLayout implements SecurityCa } // Volume buttons should only function for music (local or remote). // TODO: Actually handle MUTE. - mAudioManager.adjustLocalOrRemoteStreamVolume( - AudioManager.STREAM_MUSIC, + mAudioManager.adjustSuggestedStreamVolume( keyCode == KeyEvent.KEYCODE_VOLUME_UP ? AudioManager.ADJUST_RAISE - : AudioManager.ADJUST_LOWER); + : AudioManager.ADJUST_LOWER /* direction */, + AudioManager.STREAM_MUSIC /* stream */, 0 /* flags */); // Don't execute default volume behavior return true; } else { @@ -376,17 +376,13 @@ public abstract class KeyguardViewBase extends FrameLayout implements SecurityCa } private void handleMediaKeyEvent(KeyEvent keyEvent) { - IAudioService audioService = IAudioService.Stub.asInterface( - ServiceManager.checkService(Context.AUDIO_SERVICE)); - if (audioService != null) { - try { - audioService.dispatchMediaKeyEvent(keyEvent); - } catch (RemoteException e) { - Log.e("KeyguardViewBase", "dispatchMediaKeyEvent threw exception " + e); + synchronized (this) { + if (mAudioManager == null) { + mAudioManager = (AudioManager) getContext().getSystemService( + Context.AUDIO_SERVICE); } - } else { - Slog.w("KeyguardViewBase", "Unable to find IAudioService for media key event"); } + mAudioManager.dispatchMediaKeyEvent(keyEvent); } @Override diff --git a/packages/PrintSpooler/res/values-km-rKH/strings.xml b/packages/PrintSpooler/res/values-km-rKH/strings.xml index cdcb21fea9c7..0146ab7593c3 100644 --- a/packages/PrintSpooler/res/values-km-rKH/strings.xml +++ b/packages/PrintSpooler/res/values-km-rKH/strings.xml @@ -60,7 +60,7 @@ </plurals> <string name="cancel" msgid="4373674107267141885">"បោះបង់"</string> <string name="restart" msgid="2472034227037808749">"ចាប់ផ្ដើមឡើងវិញ"</string> - <string name="no_connection_to_printer" msgid="2159246915977282728">"គ្មានការភ្ជាប់ទៅម៉ាស៊ីនបោះពុម្ព"</string> + <string name="no_connection_to_printer" msgid="2159246915977282728">"គ្មានការភ្ជាប់ទៅម៉ាស៊ីនបោះពុម្ព"</string> <string name="reason_unknown" msgid="5507940196503246139">"មិនស្គាល់"</string> <string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – មិនអាចប្រើបាន"</string> <string-array name="color_mode_labels"> diff --git a/packages/SystemUI/res/drawable/ic_account_circle.xml b/packages/SystemUI/res/drawable/ic_account_circle.xml index a7e8514ae7e2..4a4c1c1e2afc 100644 --- a/packages/SystemUI/res/drawable/ic_account_circle.xml +++ b/packages/SystemUI/res/drawable/ic_account_circle.xml @@ -22,7 +22,13 @@ Copyright (C) 2014 The Android Open Source Project android:viewportWidth="24.0" android:viewportHeight="24.0"/> + <group + android:scaleX="1.2" + android:scaleY="1.2" + android:pivotX="12.0" + android:pivotY="12.0"> <path android:fill="#FFFFFFFF" android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0c5.5,0.0 10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM12.0,5.0c1.7,0.0 3.0,1.3 3.0,3.0c0.0,1.7 -1.3,3.0 -3.0,3.0c-1.7,0.0 -3.0,-1.3 -3.0,-3.0C9.0,6.3 10.3,5.0 12.0,5.0zM12.0,19.2c-2.5,0.0 -4.7,-1.3 -6.0,-3.2c0.0,-2.0 4.0,-3.1 6.0,-3.1c2.0,0.0 6.0,1.1 6.0,3.1C16.7,17.9 14.5,19.2 12.0,19.2z"/> + </group> </vector> diff --git a/packages/SystemUI/res/drawable/notification_scrim.xml b/packages/SystemUI/res/drawable/notification_scrim.xml new file mode 100644 index 000000000000..ff7e31f19bac --- /dev/null +++ b/packages/SystemUI/res/drawable/notification_scrim.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 + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="#34000000" /> + <corners android:radius="@*android:dimen/notification_material_rounded_rect_radius" /> +</shape>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/keyguard_user_switcher.xml b/packages/SystemUI/res/layout/keyguard_user_switcher.xml new file mode 100644 index 000000000000..5648065b3b0e --- /dev/null +++ b/packages/SystemUI/res/layout/keyguard_user_switcher.xml @@ -0,0 +1,25 @@ +<?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 + --> +<LinearLayout 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"> +</LinearLayout> diff --git a/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml b/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml new file mode 100644 index 000000000000..691a80eb0821 --- /dev/null +++ b/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml @@ -0,0 +1,40 @@ +<?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 + --> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:sysui="http://schemas.android.com/apk/res-auto" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="8dp" + android:layout_marginEnd="8dp" + android:gravity="center_vertical" + android:clickable="true" + android:background="@drawable/ripple_drawable"> + <TextView android:id="@+id/name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="16dp" + android:textAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher.UserName" + /> + <com.android.systemui.statusbar.phone.UserAvatarView android:id="@+id/picture" + android:layout_width="48dp" + android:layout_height="48dp" + android:contentDescription="@null" + sysui:frameWidth="@dimen/keyguard_user_switcher_border_thickness" + sysui:activeFrameColor="@color/current_user_border_color" /> +</LinearLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml index cde83bfc32aa..b54ba1a7254f 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded.xml @@ -24,6 +24,7 @@ android:id="@+id/notification_panel" android:layout_width="match_parent" android:layout_height="match_parent" + android:background="@android:color/transparent" > <include @@ -91,6 +92,14 @@ <include layout="@layout/status_bar_expanded_header" /> + <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" /> + <include layout="@layout/keyguard_bottom_area" android:visibility="gone" /> diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml index 353368b0a8c7..2e4c0efefb9a 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml @@ -73,9 +73,9 @@ android:layout_width="wrap_content" android:layout_height="@dimen/status_bar_header_height" android:layout_toStartOf="@id/multi_user_switch" - android:layout_marginEnd="2dp" + android:layout_alignWithParentIfMissing="true" android:layout_marginStart="16dp" - /> + android:paddingEnd="2dp" /> <TextView android:id="@+id/header_charging_info" diff --git a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml index c442f796bbda..f0f50e11fb65 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml @@ -49,4 +49,10 @@ android:layout_width="120dp" android:layout_height="wrap_content" /> + + <com.android.systemui.statusbar.NotificationScrimView + android:id="@+id/scrim_view" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + </com.android.systemui.statusbar.NotificationOverflowContainer> diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml index 5fabd3e82972..7663d54a2498 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_row.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml @@ -48,4 +48,9 @@ android:padding="2dp" /> + <com.android.systemui.statusbar.NotificationScrimView + android:id="@+id/scrim_view" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + </com.android.systemui.statusbar.ExpandableNotificationRow> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 19b0f17f57b3..019fea0ec3a2 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -243,10 +243,8 @@ <string name="camera_hint" msgid="5241441720959174226">"Avaa kamera pyyhkäisemällä oikealle"</string> <string name="zen_mode_forever" msgid="7420011936770086993">"Kunnes poistat tämän käytöstä"</string> <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Ladataan (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> kunnes täynnä)"</string> - <!-- no translation found for guest_nickname (8059989128963789678) --> - <skip /> - <!-- no translation found for guest_new_guest (4259024453643879653) --> - <skip /> + <string name="guest_nickname" msgid="8059989128963789678">"Vieras"</string> + <string name="guest_new_guest" msgid="4259024453643879653">"+ Vieras"</string> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Minuutiksi"</item> <item quantity="other" msgid="6924190729213550991">"%d minuutiksi"</item> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index fcad161c054a..d11c9bea96db 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -244,7 +244,7 @@ <string name="phone_hint" msgid="3101468054914424646">"Balayer l\'écran vers la droite pour accéder au téléphone"</string> <string name="camera_hint" msgid="5241441720959174226">"Balayer l\'écran vers la gauche pour accéder à l\'appareil photo"</string> <string name="zen_mode_forever" msgid="7420011936770086993">"Jusqu\'à la désactivation"</string> - <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charge en cours… (chargé à 100 % dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string> + <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charge en cours… (chargé à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string> <string name="guest_nickname" msgid="8059989128963789678">"Invité"</string> <string name="guest_new_guest" msgid="4259024453643879653">"Ajouter un invité"</string> <plurals name="zen_mode_duration_minutes"> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 9f1722da03c9..ddb766978185 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -40,7 +40,7 @@ <string name="invalid_charger_text" msgid="5474997287953892710">"Utilizza solo il caricabatterie fornito in dotazione."</string> <string name="battery_low_why" msgid="4553600287639198111">"Impostazioni"</string> <string name="battery_saver_confirmation_title" msgid="5987726159603849352">"Avviare risparmio batteria?"</string> - <string name="battery_saver_confirmation_ok" msgid="7283108887345688413">"Inizia"</string> + <string name="battery_saver_confirmation_ok" msgid="7283108887345688413">"Avvia"</string> <string name="battery_saver_start_action" msgid="7245333922937402896">"Avvia risparmio batteria"</string> <string name="battery_saver_confirmation_text" msgid="8417584516834617662">"Per aumentare la durata della batteria, Risparmio batteria riduce le prestazioni del tuo dispositivo.\n\nRisparmio batteria si disattiva quando il dispositivo è collegato alla corrente."</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Impostazioni"</string> diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml index 8f1f30a3c4f6..a35c8214a3a8 100644 --- a/packages/SystemUI/res/values-ka-rGE/strings.xml +++ b/packages/SystemUI/res/values-ka-rGE/strings.xml @@ -42,7 +42,7 @@ <string name="battery_saver_confirmation_title" msgid="5987726159603849352">"გსურთ ბატარეის დამზოგის დაწყება?"</string> <string name="battery_saver_confirmation_ok" msgid="7283108887345688413">"დაწყება"</string> <string name="battery_saver_start_action" msgid="7245333922937402896">"ბატარეის დამზოგის დაწყება"</string> - <string name="battery_saver_confirmation_text" msgid="8417584516834617662">"ბატარეის მოქმედების გასახანგრძლივებლად, ბატარეის დამზოგი შეამცირებს თქვენი მოწყობილობის წარმადობას.\n\nბატარეის დამზოგი გამოირთვება, როდესაც მოწყობილობას ელკვებაზე მიაერთებთ."</string> + <string name="battery_saver_confirmation_text" msgid="8417584516834617662">"ბატარეის მოქმედების გასახანგრძლივებლად ბატარეის დამზოგი შეამცირებს თქვენი მოწყობილობის წარმადობას.\n\nბატარეის დამზოგი გამოირთვება, როდესაც მოწყობილობას ელკვებაზე მიაერთებთ."</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"პარამეტრები"</string> <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string> <string name="status_bar_settings_airplane" msgid="4879879698500955300">"თვითმფრინავის რეჟიმი"</string> diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml index 88d9b6461ea5..29c5e5c756f0 100644 --- a/packages/SystemUI/res/values-km-rKH/strings.xml +++ b/packages/SystemUI/res/values-km-rKH/strings.xml @@ -70,7 +70,7 @@ <string name="screenshot_saving_ticker" msgid="7403652894056693515">"កំពុងរក្សាទុករូបថតអេក្រង់…"</string> <string name="screenshot_saving_title" msgid="8242282144535555697">"កំពុងរក្សាទុករូបថតអេក្រង់..."</string> <string name="screenshot_saving_text" msgid="2419718443411738818">"រូបថតអេក្រង់កំពុងត្រូវបានរក្សាទុក។"</string> - <string name="screenshot_saved_title" msgid="6461865960961414961">"បានចាប់យករូបថតអេក្រង់។"</string> + <string name="screenshot_saved_title" msgid="6461865960961414961">"បានចាប់យករូបថតអេក្រង់។"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"ប៉ះ ដើម្បីមើលរូបថតអេក្រង់របស់អ្នក។"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"មិនអាចចាប់យករូបថតអេក្រង់។"</string> <string name="screenshot_failed_text" msgid="8134011269572415402">"មិនអាចរក្សាទុករូបថតអេក្រង់។ ឧបករណ៍ផ្ទុកអាចកំពុងប្រើ។"</string> @@ -147,7 +147,7 @@ <string name="accessibility_remove_notification" msgid="3603099514902182350">"សម្អាតការជូនដំណឹង។"</string> <string name="accessibility_gps_enabled" msgid="3511469499240123019">"បានបើក GPS ។"</string> <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"ទទួល GPS ។"</string> - <string name="accessibility_tty_enabled" msgid="4613200365379426561">"បានបើកម៉ាស៊ីនអង្គុលីលេខ"</string> + <string name="accessibility_tty_enabled" msgid="4613200365379426561">"បានបើកម៉ាស៊ីនអង្គុលីលេខ"</string> <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"កម្មវិធីរោទ៍ញ័រ។"</string> <string name="accessibility_ringer_silent" msgid="9061243307939135383">"កម្មវិធីរោទ៍ស្ងាត់។"</string> <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> បដិសេធ។"</string> @@ -197,7 +197,7 @@ <string name="quick_settings_rotation_locked_portrait_label" msgid="5102691921442135053">"បញ្ឈរ"</string> <string name="quick_settings_rotation_locked_landscape_label" msgid="8553157770061178719">"ទេសភាព"</string> <string name="quick_settings_ime_label" msgid="7073463064369468429">"វិធីសាស្ត្របញ្ចូល"</string> - <string name="quick_settings_location_label" msgid="5011327048748762257">"ទីតាំង"</string> + <string name="quick_settings_location_label" msgid="5011327048748762257">"ទីតាំង"</string> <string name="quick_settings_location_off_label" msgid="7464544086507331459">"ទីតាំងបានបិទ"</string> <string name="quick_settings_media_device_label" msgid="1302906836372603762">"ឧបករណ៍មេឌៀ"</string> <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string> @@ -221,11 +221,11 @@ <string name="recents_empty_message" msgid="7883614615463619450">"មិនមានកម្មវិធីថ្មីៗ"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"ព័ត៌មានកម្មវិធី"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"ស្វែងរក"</string> - <string name="expanded_header_battery_charged" msgid="5945855970267657951">"បានបញ្ចូលថ្ម"</string> + <string name="expanded_header_battery_charged" msgid="5945855970267657951">"បានបញ្ចូលថ្ម"</string> <string name="expanded_header_battery_charging" msgid="205623198487189724">"កំពុងបញ្ចូលថ្ម"</string> <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> រហូតដល់ពេញ"</string> <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"មិនកំពុងបញ្ចូលថ្ម"</string> - <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"បណ្ដាញអាច\nត្រូវបានត្រួតពិនិត្យ"</string> + <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"បណ្ដាញអាច\nត្រូវបានត្រួតពិនិត្យ"</string> <string name="description_target_search" msgid="3091587249776033139">"ស្វែងរក"</string> <string name="description_direction_up" msgid="7169032478259485180">"រុញឡើងលើដើម្បី <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> diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml index 3688c570ed3d..b765fb72e750 100644 --- a/packages/SystemUI/res/values-lo-rLA/strings.xml +++ b/packages/SystemUI/res/values-lo-rLA/strings.xml @@ -241,7 +241,7 @@ <string name="keyguard_unlock" msgid="8043466894212841998">"ເລື່ອນຂຶ້ນເພື່ອປົດລັອກ"</string> <string name="phone_hint" msgid="3101468054914424646">"ປັດຂວາເພື່ອໃຊ້ໂທລະສັບ"</string> <string name="camera_hint" msgid="5241441720959174226">"ປັດຊ້າຍເພື່ອໃຊ້ກ້ອງ"</string> - <string name="zen_mode_forever" msgid="7420011936770086993">"ຈົນກວ່າທ່ານຈະປິດ"</string> + <string name="zen_mode_forever" msgid="7420011936770086993">"ຈົນກວ່າທ່ານຈະປິດ"</string> <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"ກຳລັງສາກໄຟ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ກວ່າຈະເຕັມ)"</string> <string name="guest_nickname" msgid="8059989128963789678">"ແຂກ"</string> <string name="guest_new_guest" msgid="4259024453643879653">"+ ແຂກ"</string> diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml index 7d8a1ad8625a..2fed4bd0574b 100644 --- a/packages/SystemUI/res/values-ms-rMY/strings.xml +++ b/packages/SystemUI/res/values-ms-rMY/strings.xml @@ -32,16 +32,16 @@ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Tiada pemberitahuan"</string> <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 rendah"</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">"<xliff:g id="NUMBER">%d%%</xliff:g> yang tinggal. Penjimat bateri dihidupkan."</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="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> <string name="battery_low_why" msgid="4553600287639198111">"Tetapan"</string> - <string name="battery_saver_confirmation_title" msgid="5987726159603849352">"Hidupkan penjimat bateri?"</string> - <string name="battery_saver_confirmation_ok" msgid="7283108887345688413">"Bermula"</string> - <string name="battery_saver_start_action" msgid="7245333922937402896">"Hidupkan penjimat bateri"</string> + <string name="battery_saver_confirmation_title" msgid="5987726159603849352">"Mulakan penjimat bateri?"</string> + <string name="battery_saver_confirmation_ok" msgid="7283108887345688413">"Mula"</string> + <string name="battery_saver_start_action" msgid="7245333922937402896">"Mulakan penjimat bateri"</string> <string name="battery_saver_confirmation_text" msgid="8417584516834617662">"Untuk membantu meningkatkan hayat bateri, penjimat Bateri akan mengurangkan prestasi peranti anda.\n\nPenjimat bateri akan dilumpuhkan apabila peranti anda disambungkan kepada sumber kuasa."</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Tetapan"</string> <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string> @@ -243,10 +243,8 @@ <string name="camera_hint" msgid="5241441720959174226">"Leret ke kiri untuk kamera"</string> <string name="zen_mode_forever" msgid="7420011936770086993">"Sehingga anda matikan"</string> <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Mengecas (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> sehingga penuh)"</string> - <!-- no translation found for guest_nickname (8059989128963789678) --> - <skip /> - <!-- no translation found for guest_new_guest (4259024453643879653) --> - <skip /> + <string name="guest_nickname" msgid="8059989128963789678">"Tetamu"</string> + <string name="guest_new_guest" msgid="4259024453643879653">"+ Tetamu"</string> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Selama satu minit"</item> <item quantity="other" msgid="6924190729213550991">"Selama %d minit"</item> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index c099dd9030cc..8ec3621cf558 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -243,10 +243,8 @@ <string name="camera_hint" msgid="5241441720959174226">"Glisați la stânga pentru a accesa camera foto"</string> <string name="zen_mode_forever" msgid="7420011936770086993">"Până la dezactivare"</string> <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Se încarcă (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> până la finalizare)"</string> - <!-- no translation found for guest_nickname (8059989128963789678) --> - <skip /> - <!-- no translation found for guest_new_guest (4259024453643879653) --> - <skip /> + <string name="guest_nickname" msgid="8059989128963789678">"Invitat"</string> + <string name="guest_new_guest" msgid="4259024453643879653">"+ Invitat"</string> <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> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 3bee434d9101..d9c1cfcc1b3c 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -42,7 +42,7 @@ <string name="battery_saver_confirmation_title" msgid="5987726159603849352">"Желите ли да покренете Штедњу батерије?"</string> <string name="battery_saver_confirmation_ok" msgid="7283108887345688413">"Покрени"</string> <string name="battery_saver_start_action" msgid="7245333922937402896">"Покрените Штедњу батерије"</string> - <string name="battery_saver_confirmation_text" msgid="8417584516834617662">"Да би продужила век трајања батерије, Штедња батерије ће умањити перформансе уређаја.\n\nШтедња батерије ће се искључити када укључите уређај."</string> + <string name="battery_saver_confirmation_text" msgid="8417584516834617662">"Да би продужила век трајања батерије, Штедња батерије умањује перформансе уређаја.\n\nШтедња батерије ће се искључити када прикључите уређај на напајање."</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Подешавања"</string> <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string> <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Режим рада у авиону"</string> diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml index 47581a99b001..9f4c364f4a72 100644 --- a/packages/SystemUI/res/values-sw600dp/config.xml +++ b/packages/SystemUI/res/values-sw600dp/config.xml @@ -32,4 +32,7 @@ <!-- The maximum count of notifications on Keyguard. The rest will be collapsed in an overflow card. --> <integer name="keyguard_max_notification_count">5</integer> + + <!-- Set to true to enable the user switcher on the keyguard. --> + <bool name="config_keyguardUserSwitcher">true</bool> </resources> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 7635c011e2cd..fbd8549f1b2d 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -42,7 +42,7 @@ <string name="battery_saver_confirmation_title" msgid="5987726159603849352">"Pil tasarrufu başlatılsın mı?"</string> <string name="battery_saver_confirmation_ok" msgid="7283108887345688413">"Başlat"</string> <string name="battery_saver_start_action" msgid="7245333922937402896">"Pil tasarrufunu başlat"</string> - <string name="battery_saver_confirmation_text" msgid="8417584516834617662">"Pil tasarrufu, pil ömrünü iyileştirmeye yardımcı olmak için cihazınızın performansını düşürür.\n\nCihazınız fişe takılıyken Pil tasarrufu devre dışı bırakılır."</string> + <string name="battery_saver_confirmation_text" msgid="8417584516834617662">"Pil tasarrufu, pil ömrünü iyileştirmeye yardımcı olmak için cihazınızın performansını düşürür.\n\nCihazınız fişe takıldığında Pil tasarrufu devre dışı bırakılır."</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Ayarlar"</string> <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Kablosuz"</string> <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Uçak modu"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index e15d3e5ccb8c..5c24e8b08854 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -42,7 +42,7 @@ <string name="battery_saver_confirmation_title" msgid="5987726159603849352">"Khởi động trình tiết kiệm pin?"</string> <string name="battery_saver_confirmation_ok" msgid="7283108887345688413">"Bắt đầu"</string> <string name="battery_saver_start_action" msgid="7245333922937402896">"Khởi động trình tiết kiệm pin"</string> - <string name="battery_saver_confirmation_text" msgid="8417584516834617662">"Để giúp tăng tuổi thọ pin, trình tiết kiệm pin sẽ giảm hiệu suất của thiết bị.\n\nTrình tiết kiệm pin sẽ tắt khi thiết bị của bạn được cắm vào."</string> + <string name="battery_saver_confirmation_text" msgid="8417584516834617662">"Để giúp tăng tuổi thọ pin, trình tiết kiệm pin sẽ giảm hiệu suất của thiết bị.\n\nTrình tiết kiệm pin sẽ tắt khi thiết bị của bạn được cắm vào nguồn điện."</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Cài đặt"</string> <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string> <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Chế độ trên máy bay"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index cfd4fe9716ec..f975252e5166 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -34,15 +34,15 @@ <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_saver_started" msgid="6534746636002666456">"电量还剩<xliff:g id="NUMBER">%d%%</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_title" msgid="3515740382572798460">"不支持USB充电。"</string> <string name="invalid_charger_text" msgid="5474997287953892710">"仅限使用设备随附的充电器。"</string> <string name="battery_low_why" msgid="4553600287639198111">"设置"</string> - <string name="battery_saver_confirmation_title" msgid="5987726159603849352">"启动节电助手?"</string> - <string name="battery_saver_confirmation_ok" msgid="7283108887345688413">"启动"</string> - <string name="battery_saver_start_action" msgid="7245333922937402896">"启动节电助手"</string> - <string name="battery_saver_confirmation_text" msgid="8417584516834617662">"为了延长电池的续航时间,节电助手会减降设备的性能。\n\n设备接通电源后,节电助手会自动停用。"</string> + <string name="battery_saver_confirmation_title" msgid="5987726159603849352">"要开启节电助手吗?"</string> + <string name="battery_saver_confirmation_ok" msgid="7283108887345688413">"开启"</string> + <string name="battery_saver_start_action" msgid="7245333922937402896">"开启节电助手"</string> + <string name="battery_saver_confirmation_text" msgid="8417584516834617662">"为了延长电池的续航时间,节电助手会减降设备的性能。\n\n设备接通电源后,节电助手会自动关闭。"</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"设置"</string> <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"WLAN"</string> <string name="status_bar_settings_airplane" msgid="4879879698500955300">"飞行模式"</string> @@ -245,10 +245,8 @@ <string name="camera_hint" msgid="5241441720959174226">"向左滑动可打开相机"</string> <string name="zen_mode_forever" msgid="7420011936770086993">"直到您将其关闭"</string> <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"正在充电(还需<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>才能充满)"</string> - <!-- no translation found for guest_nickname (8059989128963789678) --> - <skip /> - <!-- no translation found for guest_new_guest (4259024453643879653) --> - <skip /> + <string name="guest_nickname" msgid="8059989128963789678">"访客"</string> + <string name="guest_new_guest" msgid="4259024453643879653">"添加新访客"</string> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"1分钟"</item> <item quantity="other" msgid="6924190729213550991">"%d分钟"</item> @@ -257,7 +255,7 @@ <item quantity="one" msgid="3480040795582254384">"1小时"</item> <item quantity="other" msgid="5408537517529822157">"%d小时"</item> </plurals> - <string name="battery_saver_notification_title" msgid="237918726750955859">"节电助手已启用"</string> + <string name="battery_saver_notification_title" msgid="237918726750955859">"节电助手已开启"</string> <string name="battery_saver_notification_text" msgid="7796554871101546872">"设备性能已减降。"</string> <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"打开节电助手设置"</string> </resources> diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml index c45361874f1c..8473d9609a8c 100644 --- a/packages/SystemUI/res/values/attrs.xml +++ b/packages/SystemUI/res/values/attrs.xml @@ -54,5 +54,10 @@ <enum name="horizontal" value="0" /> <enum name="vertical" value="1" /> </attr> + <declare-styleable name="UserAvatarView"> + <attr name="frameWidth" format="dimension" /> + <attr name="activeFrameColor" format="color" /> + <attr name="frameColor" /> + </declare-styleable> </resources> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 3bd86891e5e1..4e38da6123d9 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -60,6 +60,9 @@ <color name="keyguard_affordance">#ffffffff</color> + <!-- The color of the circle around the primary user in the user switcher --> + <color name="current_user_border_color">@color/primary_color</color> + <!-- Our material color palette (deep teal) --> <color name="primary_color">#ff7fcac3</color> <color name="background_color_1">#ff384248</color> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index c64a182c788f..48b327d0e5fd 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -154,5 +154,8 @@ Notification.tickerText across the status bar for what seems like an eternity. --> <bool name="enable_ticker">false</bool> + + <!-- Set to true to enable the user switcher on the keyguard. --> + <bool name="config_keyguardUserSwitcher">false</bool> </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index bbcc9c13c9ea..36c1994fad75 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -320,6 +320,9 @@ device. --> <dimen name="unlock_move_distance">75dp</dimen> + <!-- Distance after which the scrim starts fading in when dragging down the quick settings --> + <dimen name="notification_scrim_wait_distance">100dp</dimen> + <!-- Move distance for the unlock hint animation on the lockscreen --> <dimen name="hint_move_distance">75dp</dimen> @@ -332,4 +335,11 @@ <!-- end margin for multi user switch in expanded quick settings --> <dimen name="multi_user_switch_expanded_margin">8dp</dimen> + + <!-- end margin for system icons if multi user switch is hidden --> + <dimen name="system_icons_switcher_hidden_expanded_margin">16dp</dimen> + + <!-- The thickness of the colored border around the current user. --> + <dimen name="keyguard_user_switcher_border_thickness">2dp</dimen> + </resources> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index c117eba8aefe..e5d5b03c34f1 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -100,6 +100,13 @@ <style name="TextAppearance.StatusBar.Expanded.Network.EmergencyOnly"> </style> + <style name="TextAppearance.StatusBar.Expanded.UserSwitcher"> + <item name="android:textSize">16sp</item> + <item name="android:textStyle">normal</item> + <item name="android:textColor">#ffffff</item> + </style> + <style name="TextAppearance.StatusBar.Expanded.UserSwitcher.UserName" /> + <style name="TextAppearance" /> <style name="TextAppearance.QuickSettings" /> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java index 8d19f50e25ad..f6f78e99020f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java @@ -119,6 +119,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView private NotificationBackgroundView mBackgroundNormal; private NotificationBackgroundView mBackgroundDimmed; + private NotificationScrimView mScrimView; private ObjectAnimator mBackgroundAnimator; private RectF mAppearAnimationRect = new RectF(); private PorterDuffColorFilter mAppearAnimationFilter; @@ -153,6 +154,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView mBackgroundDimmed = (NotificationBackgroundView) findViewById(R.id.backgroundDimmed); updateBackground(); updateBackgroundResources(); + mScrimView = (NotificationScrimView) findViewById(R.id.scrim_view); } private final Runnable mTapTimeoutRunnable = new Runnable() { @@ -379,6 +381,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView setPivotY(actualHeight / 2); mBackgroundNormal.setActualHeight(actualHeight); mBackgroundDimmed.setActualHeight(actualHeight); + mScrimView.setActualHeight(actualHeight); } @Override @@ -386,6 +389,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView super.setClipTopAmount(clipTopAmount); mBackgroundNormal.setClipTopAmount(clipTopAmount); mBackgroundDimmed.setClipTopAmount(clipTopAmount); + mScrimView.setClipTopAmount(clipTopAmount); } @Override @@ -405,6 +409,11 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView } } + @Override + public void setScrimAmount(float scrimAmount) { + mScrimView.setAlpha(scrimAmount); + } + private void startAppearAnimation(boolean isAppearing, float translationDirection, long delay, final Runnable onFinishedRunnable) { if (mAppearAnimator != null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java index ac2537cc1d55..4d4a8abe7500 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java @@ -223,6 +223,8 @@ public abstract class ExpandableView extends FrameLayout { public abstract void performAddAnimation(long delay); + public abstract void setScrimAmount(float scrimAmount); + /** * A listener notifying when {@link #getActualHeight} changes. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationScrimView.java new file mode 100644 index 000000000000..440b2c1df871 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationScrimView.java @@ -0,0 +1,79 @@ +/* + * 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.statusbar; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; + +import com.android.keyguard.R; + +/** + * A view that can be used for both the dimmed and normal background of an notification. + */ +public class NotificationScrimView extends View { + + private Drawable mBackground; + private int mClipTopAmount; + private int mActualHeight; + + public NotificationScrimView(Context context, AttributeSet attrs) { + super(context, attrs); + mBackground = getResources().getDrawable(R.drawable.notification_scrim); + } + + @Override + protected void onDraw(Canvas canvas) { + draw(canvas, mBackground); + } + + private void draw(Canvas canvas, Drawable drawable) { + if (drawable != null) { + drawable.setBounds(0, mClipTopAmount, getWidth(), mActualHeight); + drawable.draw(canvas); + } + } + + @Override + protected boolean verifyDrawable(Drawable who) { + return super.verifyDrawable(who) || who == mBackground; + } + + public void setActualHeight(int actualHeight) { + mActualHeight = actualHeight; + invalidate(); + } + + public int getActualHeight() { + return mActualHeight; + } + + public void setClipTopAmount(int clipTopAmount) { + mClipTopAmount = clipTopAmount; + invalidate(); + } + + @Override + public boolean hasOverlappingRendering() { + + // Prevents this view from creating a layer when alpha is animating. + return false; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java index f80f0fdf1c7e..650abaa3e09d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java @@ -121,4 +121,9 @@ public class SpeedBumpView extends ExpandableView { public void performAddAnimation(long delay) { performVisibilityAnimation(true); } + + @Override + public void setScrimAmount(float scrimAmount) { + // We don't need to scrim the speedbumps + } } 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 97aa993864ca..63698e440c88 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -58,6 +58,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private ImageView mCameraImageView; private ImageView mPhoneImageView; private ImageView mLockIcon; + private View mIndicationText; private ActivityStarter mActivityStarter; private UnlockMethodCache mUnlockMethodCache; @@ -87,6 +88,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mCameraImageView = (ImageView) findViewById(R.id.camera_button); mPhoneImageView = (ImageView) findViewById(R.id.phone_button); mLockIcon = (ImageView) findViewById(R.id.lock_icon); + mIndicationText = findViewById(R.id.keyguard_indication_text); watchForCameraPolicyChanges(); watchForAccessibilityChanges(); updateCameraVisibility(); @@ -231,6 +233,10 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL return mLockIcon; } + public View getIndicationView() { + return mIndicationText; + } + @Override public void onMethodSecureChanged(boolean methodSecure) { updateTrust(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java index 6a83a5e2226a..319096d197e6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone; import android.content.res.Resources; import android.graphics.Path; +import android.view.animation.AccelerateInterpolator; import android.view.animation.PathInterpolator; import com.android.systemui.R; @@ -31,6 +32,10 @@ public class KeyguardClockPositionAlgorithm { private static final float CLOCK_RUBBERBAND_FACTOR_MIN = 0.08f; private static final float CLOCK_RUBBERBAND_FACTOR_MAX = 0.8f; + private static final float CLOCK_SCALE_FADE_START = 0.95f; + private static final float CLOCK_SCALE_FADE_END = 0.75f; + private static final float CLOCK_SCALE_FADE_END_NO_NOTIFS = 0.5f; + private static final float CLOCK_ADJ_TOP_PADDING_MULTIPLIER_MIN = 1.4f; private static final float CLOCK_ADJ_TOP_PADDING_MULTIPLIER_MAX = 3.2f; @@ -61,6 +66,8 @@ public class KeyguardClockPositionAlgorithm { sSlowDownInterpolator = new PathInterpolator(path); } + private AccelerateInterpolator mAccelerateInterpolator = new AccelerateInterpolator(); + /** * Refreshes the dimension values. */ @@ -87,18 +94,29 @@ public class KeyguardClockPositionAlgorithm { } public void run(Result result) { - int y = getClockY() - mKeyguardStatusHeight/2; + int y = getClockY() - mKeyguardStatusHeight / 2; float clockAdjustment = getClockYExpansionAdjustment(); float topPaddingAdjMultiplier = getTopPaddingAdjMultiplier(); result.stackScrollerPaddingAdjustment = (int) (clockAdjustment*topPaddingAdjMultiplier); int clockNotificationsPadding = getClockNotificationsPadding() + result.stackScrollerPaddingAdjustment; int padding = y + clockNotificationsPadding; - y += clockAdjustment; result.clockY = y; result.stackScrollerPadding = mKeyguardStatusHeight + padding; - result.clockAlpha = getClockAlpha(result.stackScrollerPadding - - (y + mKeyguardStatusHeight)); + result.clockScale = getClockScale(result.stackScrollerPadding, + result.clockY, + y + getClockNotificationsPadding() + mKeyguardStatusHeight); + result.clockAlpha = getClockAlpha(result.clockScale); + } + + private float getClockScale(int notificationPadding, int clockY, int startPadding) { + float scaleMultiplier = getNotificationAmountT() == 0 ? 6.0f : 5.0f; + float scaleEnd = clockY - mKeyguardStatusHeight * scaleMultiplier; + float distanceToScaleEnd = notificationPadding - scaleEnd; + float progress = distanceToScaleEnd / (startPadding - scaleEnd); + progress = Math.max(0.0f, Math.min(progress, 1.0f)); + progress = mAccelerateInterpolator.getInterpolation(progress); + return progress; } private int getClockNotificationsPadding() { @@ -144,11 +162,12 @@ public class KeyguardClockPositionAlgorithm { + t * CLOCK_ADJ_TOP_PADDING_MULTIPLIER_MAX; } - private float getClockAlpha(int clockNotificationPadding) { - float t = getNotificationAmountT(); - t = (float) Math.pow(t, 0.3f); - float multiplier = 1 + 2 * (1 - t); - float alpha = 1 + (float) clockNotificationPadding * multiplier / mKeyguardStatusHeight * 3; + private float getClockAlpha(float scale) { + float fadeEnd = getNotificationAmountT() == 0.0f + ? CLOCK_SCALE_FADE_END_NO_NOTIFS + : CLOCK_SCALE_FADE_END; + float alpha = (scale - fadeEnd) + / (CLOCK_SCALE_FADE_START - fadeEnd); return Math.max(0, Math.min(1, alpha)); } @@ -168,6 +187,11 @@ public class KeyguardClockPositionAlgorithm { public int clockY; /** + * The scale of the Clock + */ + public float clockScale; + + /** * The alpha value of the clock. */ public float clockAlpha; 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 dde95bf46a77..a6ce5d5a5fa3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -32,6 +32,7 @@ import android.view.accessibility.AccessibilityEvent; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import android.widget.LinearLayout; +import android.widget.TextView; import com.android.systemui.R; import com.android.systemui.statusbar.ExpandableView; @@ -48,6 +49,11 @@ public class NotificationPanelView extends PanelView implements View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener, KeyguardPageSwipeHelper.Callback { + // Cap and total height of Roboto font. Needs to be adjusted when font for the big clock is + // changed. + private static final int CAP_HEIGHT = 1456; + private static final int FONT_HEIGHT = 2163; + private static final float LOCK_ICON_ACTIVE_SCALE = 1.2f; private KeyguardPageSwipeHelper mPageSwiper; @@ -56,7 +62,7 @@ public class NotificationPanelView extends PanelView implements private View mQsPanel; private View mKeyguardStatusView; private ObservableScrollView mScrollView; - private View mStackScrollerContainer; + private TextView mClockView; private NotificationStackScrollLayout mNotificationStackScroller; private int mNotificationTopPadding; @@ -105,9 +111,11 @@ public class NotificationPanelView extends PanelView implements new KeyguardClockPositionAlgorithm.Result(); private boolean mIsSwipedHorizontally; private boolean mIsExpanding; - private KeyguardBottomAreaView mKeyguardBottomArea; + private boolean mBlockTouches; private ArrayList<View> mSwipeTranslationViews = new ArrayList<>(); + private int mNotificationScrimWaitDistance; + private boolean mOnNotificationsOnDown; public NotificationPanelView(Context context, AttributeSet attrs) { super(context, attrs); @@ -135,9 +143,9 @@ public class NotificationPanelView extends PanelView implements mHeader.getBackgroundView().setOnClickListener(this); mHeader.setOverlayParent(this); mKeyguardStatusView = findViewById(R.id.keyguard_status_view); - mStackScrollerContainer = findViewById(R.id.notification_container_parent); mQsContainer = findViewById(R.id.quick_settings_container); mQsPanel = findViewById(R.id.quick_settings_panel); + mClockView = (TextView) findViewById(R.id.clock_view); mScrollView = (ObservableScrollView) findViewById(R.id.scroll_view); mScrollView.setListener(this); mNotificationStackScroller = (NotificationStackScrollLayout) @@ -169,12 +177,19 @@ public class NotificationPanelView extends PanelView implements getResources().getDimensionPixelSize(R.dimen.header_notifications_collide_distance); mUnlockMoveDistance = getResources().getDimensionPixelOffset(R.dimen.unlock_move_distance); mClockPositionAlgorithm.loadDimens(getResources()); + mNotificationScrimWaitDistance = + getResources().getDimensionPixelSize(R.dimen.notification_scrim_wait_distance); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); + // Update Clock Pivot + mKeyguardStatusView.setPivotX(getWidth() / 2); + mKeyguardStatusView.setPivotY( + (FONT_HEIGHT - CAP_HEIGHT) / 2048f * mClockView.getTextSize()); + // Calculate quick setting heights. mQsMinExpansionHeight = mHeader.getCollapsedHeight() + mQsPeekHeight; mQsMaxExpansionHeight = mHeader.getExpandedHeight() + mQsContainer.getHeight(); @@ -197,7 +212,7 @@ public class NotificationPanelView extends PanelView implements * showing. */ private void positionClockAndNotifications() { - boolean animateClock = mNotificationStackScroller.isAddOrRemoveAnimationPending(); + boolean animate = mNotificationStackScroller.isAddOrRemoveAnimationPending(); int stackScrollerPadding; if (mStatusBar.getBarState() != StatusBarState.KEYGUARD) { int bottom = mStackScrollerOverscrolling @@ -215,17 +230,17 @@ public class NotificationPanelView extends PanelView implements getHeight(), mKeyguardStatusView.getHeight()); mClockPositionAlgorithm.run(mClockPositionResult); - if (animateClock || mClockAnimator != null) { + if (animate || mClockAnimator != null) { startClockAnimation(mClockPositionResult.clockY); } else { mKeyguardStatusView.setY(mClockPositionResult.clockY); } - applyClockAlpha(mClockPositionResult.clockAlpha); + updateClock(mClockPositionResult.clockAlpha, mClockPositionResult.clockScale); stackScrollerPadding = mClockPositionResult.stackScrollerPadding; mTopPaddingAdjustment = mClockPositionResult.stackScrollerPaddingAdjustment; } mNotificationStackScroller.setIntrinsicPadding(stackScrollerPadding); - requestScrollerTopPaddingUpdate(animateClock); + requestScrollerTopPaddingUpdate(animate); } private void startClockAnimation(int y) { @@ -258,13 +273,10 @@ public class NotificationPanelView extends PanelView implements }); } - private void applyClockAlpha(float alpha) { - if (alpha != 1.0f) { - mKeyguardStatusView.setLayerType(LAYER_TYPE_HARDWARE, null); - } else { - mKeyguardStatusView.setLayerType(LAYER_TYPE_NONE, null); - } + private void updateClock(float alpha, float scale) { mKeyguardStatusView.setAlpha(alpha); + mKeyguardStatusView.setScaleX(scale); + mKeyguardStatusView.setScaleY(scale); } public void animateToFullShade() { @@ -344,6 +356,7 @@ public class NotificationPanelView extends PanelView implements mInitialTouchX = x; initVelocityTracker(); trackMovement(event); + mOnNotificationsOnDown = isOnNotifications(x, y); if (shouldQuickSettingsIntercept(mInitialTouchX, mInitialTouchY, 0)) { getParent().requestDisallowInterceptTouchEvent(true); } @@ -391,6 +404,8 @@ public class NotificationPanelView extends PanelView implements if (mQsTracking) { flingQsWithCurrentVelocity(); mQsTracking = false; + } else if (mQsFullyExpanded && mOnNotificationsOnDown) { + flingSettings(0 /* vel */, false /* expand */); } mIntercepting = false; break; @@ -398,6 +413,10 @@ public class NotificationPanelView extends PanelView implements return !mQsExpanded && super.onInterceptTouchEvent(event); } + private boolean isOnNotifications(float x, float y) { + return mNotificationStackScroller.getChildAtPosition(x, y) != null; + } + @Override public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { @@ -577,9 +596,17 @@ public class NotificationPanelView extends PanelView implements mHeader.setExpansion(height - mQsPeekHeight); setQsTranslation(height); requestScrollerTopPaddingUpdate(false /* animate */); + updateNotificationScrim(height); mStatusBar.userActivity(); } + private void updateNotificationScrim(float height) { + int startDistance = mQsMinExpansionHeight + mNotificationScrimWaitDistance; + float progress = (height - startDistance) / (mQsMaxExpansionHeight - startDistance); + progress = Math.max(0.0f, Math.min(progress, 1.0f)); + mNotificationStackScroller.setScrimAlpha(progress); + } + private void setQsTranslation(float height) { mQsContainer.setY(height - mQsContainer.getHeight()); } 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 1f3098d94d41..12aa0042c10c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -62,6 +62,7 @@ public abstract class PanelView extends FrameLayout { protected int mTouchSlop; protected boolean mHintAnimationRunning; private boolean mOverExpandedBeforeFling; + private float mOriginalIndicationY; private ValueAnimator mHeightAnimator; private ObjectAnimator mPeekAnimator; @@ -82,6 +83,7 @@ public abstract class PanelView extends FrameLayout { private Interpolator mLinearOutSlowInInterpolator; private Interpolator mBounceInterpolator; + protected KeyguardBottomAreaView mKeyguardBottomArea; protected void onExpandingFinished() { mBar.onExpandingFinished(); @@ -652,6 +654,22 @@ public abstract class PanelView extends FrameLayout { }); animator.start(); mHeightAnimator = animator; + mOriginalIndicationY = mKeyguardBottomArea.getIndicationView().getY(); + mKeyguardBottomArea.getIndicationView().animate() + .y(mOriginalIndicationY - mHintDistance) + .setDuration(250) + .setInterpolator(mLinearOutSlowInInterpolator) + .withEndAction(new Runnable() { + @Override + public void run() { + mKeyguardBottomArea.getIndicationView().animate() + .y(mOriginalIndicationY) + .setDuration(450) + .setInterpolator(mBounceInterpolator) + .start(); + } + }) + .start(); } /** 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 1da7dabb55be..d52377e2a0d6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -82,7 +82,6 @@ import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.ViewPropertyAnimator; import android.view.ViewStub; -import android.view.ViewTreeObserver; import android.view.WindowManager; import android.view.animation.AccelerateInterpolator; import android.view.animation.Animation; @@ -123,6 +122,7 @@ import com.android.systemui.statusbar.policy.BluetoothControllerImpl; import com.android.systemui.statusbar.policy.CastControllerImpl; import com.android.systemui.statusbar.policy.DateView; import com.android.systemui.statusbar.policy.HeadsUpNotificationView; +import com.android.systemui.statusbar.policy.KeyguardUserSwitcher; import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.LocationControllerImpl; import com.android.systemui.statusbar.policy.NetworkControllerImpl; @@ -211,6 +211,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, ZenModeController mZenModeController; CastControllerImpl mCastController; VolumeComponent mVolumeComponent; + KeyguardUserSwitcher mKeyguardUserSwitcher; int mNaturalBarHeight = -1; int mIconSize = -1; @@ -260,6 +261,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, boolean mLeaveOpenOnKeyguardHide; KeyguardIndicationController mKeyguardIndicationController; + private boolean mKeyguardFadingAway; + private long mKeyguardFadingAwayDelay; + private long mKeyguardFadingAwayDuration; + int mKeyguardMaxNotificationCount; View mDateTimeView; @@ -399,7 +404,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private boolean mSettingsCancelled; private boolean mSettingsClosing; private boolean mVisible; + private boolean mWaitingForKeyguardExit; + private Interpolator mLinearOutSlowIn; private Interpolator mAlphaOut = new PathInterpolator(0f, 0.4f, 1f, 1f); private Interpolator mAlphaIn = new PathInterpolator(0f, 0f, 0.8f, 1f); @@ -713,6 +720,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, final SignalClusterView signalCluster = (SignalClusterView)mStatusBarView.findViewById(R.id.signal_cluster); + mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext, + (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_user_switcher), mHeader); mNetworkController.addSignalCluster(signalCluster); signalCluster.setNetworkController(mNetworkController); @@ -1453,7 +1462,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } private int adjustDisableFlags(int state) { - if (mExpandedVisible) { + if (mExpandedVisible || mBouncerShowing || mWaitingForKeyguardExit) { state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS; state |= StatusBarManager.DISABLE_SYSTEM_INFO; } @@ -1501,19 +1510,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) { mSystemIconArea.animate().cancel(); if ((state & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) { - mSystemIconArea.animate() - .alpha(0f) - .withLayer() - .setDuration(160) - .setInterpolator(mAlphaIn) - .setListener(mMakeIconsInvisible); + animateStatusBarHide(mSystemIconArea); } else { - mSystemIconArea.setVisibility(View.VISIBLE); - mSystemIconArea.animate() - .alpha(1f) - .withLayer() - .setInterpolator(mAlphaOut) - .setDuration(320); + animateStatusBarShow(mSystemIconArea); } } @@ -1546,25 +1545,48 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mTicking) { haltTicker(); } - - mNotificationIcons.animate() - .alpha(0f) - .withLayer() - .setDuration(160) - .setInterpolator(mAlphaIn) - .setListener(mMakeIconsInvisible) - .start(); + animateStatusBarHide(mNotificationIcons); } else { - mNotificationIcons.setVisibility(View.VISIBLE); - mNotificationIcons.animate() - .alpha(1f) - .withLayer() - .setInterpolator(mAlphaOut) - .setDuration(320); + animateStatusBarShow(mNotificationIcons); } } } + /** + * Animates {@code v}, a view that is part of the status bar, out. + */ + private void animateStatusBarHide(View v) { + v.animate() + .alpha(0f) + .withLayer() + .setDuration(160) + .setInterpolator(mAlphaIn) + .setStartDelay(0) + .setListener(mMakeIconsInvisible) + .start(); + } + + /** + * Animates {@code v}, a view that is part of the status bar, in. + */ + private void animateStatusBarShow(View v) { + v.setVisibility(View.VISIBLE); + v.animate() + .alpha(1f) + .withLayer() + .setInterpolator(mAlphaOut) + .setDuration(320) + .setStartDelay(0); + + // Synchronize the motion with the Keyguard fading if necessary. + if (mKeyguardFadingAway) { + v.animate() + .setDuration(mKeyguardFadingAwayDuration) + .setInterpolator(mLinearOutSlowIn) + .setStartDelay(mKeyguardFadingAwayDelay); + } + } + @Override protected BaseStatusBar.H createHandler() { return new PhoneStatusBar.H(); @@ -1666,6 +1688,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mStatusBarWindowManager.setStatusBarExpanded(true); visibilityChanged(true); + mWaitingForKeyguardExit = false; disable(mDisabledUnmodified); setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true); } @@ -1859,8 +1882,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false); - disable(mDisabledUnmodified); showBouncer(); + disable(mDisabledUnmodified); } public boolean interceptTouchEvent(MotionEvent event) { @@ -2574,6 +2597,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mQSPanel != null) mQSPanel.updateResources(); loadDimens(); + mLinearOutSlowIn = AnimationUtils.loadInterpolator( + mContext, android.R.interpolator.linear_out_slow_in); } protected void loadDimens() { @@ -2901,6 +2926,27 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, updateKeyguardState(); } + /** + * Notifies the status bar the Keyguard is fading away with the specified timings. + * + * @param delay the animation delay in miliseconds + * @param fadeoutDuration the duration of the exit animation, in milliseconds + */ + public void setKeyguardFadingAway(long delay, long fadeoutDuration) { + mKeyguardFadingAway = true; + mKeyguardFadingAwayDelay = delay; + mKeyguardFadingAwayDuration = fadeoutDuration; + mWaitingForKeyguardExit = false; + disable(mDisabledUnmodified); + } + + /** + * Notifies that the Keyguard fading away animation is done. + */ + public void finishKeyguardFadingAway() { + mKeyguardFadingAway = false; + } + private void updatePublicMode() { setLockscreenPublicMode( (mStatusBarKeyguardViewManager.isShowing() || @@ -2913,9 +2959,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mKeyguardStatusView.setVisibility(View.VISIBLE); mKeyguardIndicationController.setVisible(true); mNotificationPanel.resetViews(); + mKeyguardUserSwitcher.setKeyguard(true); } else { mKeyguardStatusView.setVisibility(View.GONE); mKeyguardIndicationController.setVisible(false); + mKeyguardUserSwitcher.setKeyguard(false); } if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { mKeyguardBottomArea.setVisibility(View.VISIBLE); @@ -2975,6 +3023,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private void showBouncer() { if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { + mWaitingForKeyguardExit = true; mStatusBarKeyguardViewManager.dismiss(); } } @@ -3125,6 +3174,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mSystemIconArea.addView(mSystemIcons, 0); } + @Override + public void setBouncerShowing(boolean bouncerShowing) { + super.setBouncerShowing(bouncerShowing); + disable(mDisabledUnmodified); + } + public void onScreenTurnedOff() { mStackScroller.setAnimationsEnabled(false); } 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 1712124e18d8..fc10a081e384 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java @@ -63,6 +63,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL private boolean mShowEmergencyCallsOnly; private boolean mShowChargingInfo; + private boolean mKeyguardUserSwitcherShowing; private int mCollapsedHeight; private int mExpandedHeight; @@ -72,6 +73,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL private int mNormalWidth; private int mPadding; private int mMultiUserExpandedMargin; + private int mSystemIconsSwitcherHiddenExpandedMargin; private ActivityStarter mActivityStarter; private BrightnessController mBrightnessController; @@ -125,7 +127,8 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL mPadding = getResources().getDimensionPixelSize(R.dimen.notification_side_padding); mMultiUserExpandedMargin = getResources().getDimensionPixelSize(R.dimen.multi_user_switch_expanded_margin); - + mSystemIconsSwitcherHiddenExpandedMargin = getResources().getDimensionPixelSize( + R.dimen.system_icons_switcher_hidden_expanded_margin); } public void setActivityStarter(ActivityStarter activityStarter) { @@ -216,12 +219,15 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL ? VISIBLE : GONE); mChargingInfo.setVisibility(mExpanded && !mOverscrolled && mShowChargingInfo && !mShowEmergencyCallsOnly ? VISIBLE : GONE); + mMultiUserSwitch.setVisibility(mExpanded || !mKeyguardUserSwitcherShowing + ? VISIBLE : GONE); } private void updateSystemIconsLayoutParams() { RelativeLayout.LayoutParams lp = (LayoutParams) mSystemIconsContainer.getLayoutParams(); boolean systemIconsAboveClock = mExpanded && !mOverscrolled && mShowChargingInfo && !mShowEmergencyCallsOnly; + lp.setMarginEnd(0); if (systemIconsAboveClock) { lp.addRule(ALIGN_PARENT_START); lp.removeRule(START_OF); @@ -230,7 +236,11 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL ? mSettingsButton.getId() : mMultiUserSwitch.getId()); lp.removeRule(ALIGN_PARENT_START); + if (mMultiUserSwitch.getVisibility() == GONE) { + lp.setMarginEnd(mSystemIconsSwitcherHiddenExpandedMargin); + } } + mSystemIconsContainer.setLayoutParams(lp); RelativeLayout.LayoutParams clockLp = (LayoutParams) mDateTime.getLayoutParams(); if (systemIconsAboveClock) { @@ -238,6 +248,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL } else { clockLp.addRule(BELOW, mEmergencyCallsOnly.getId()); } + mDateTime.setLayoutParams(clockLp); } private void updateBrightnessControllerState() { @@ -385,4 +396,11 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL public void setChargingInfo(CharSequence chargingInfo) { mChargingInfo.setText(chargingInfo); } + + public void setKeyguardUserSwitcherShowing(boolean showing) { + // STOPSHIP: NOT CALLED PROPERLY WHEN GOING TO FULL SHADE AND RETURNING!?! + mKeyguardUserSwitcherShowing = showing; + updateVisibilities(); + updateSystemIconsLayoutParams(); + } } 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 09e4d940b2e1..a36f3d64c0cc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -190,19 +190,23 @@ public class StatusBarKeyguardViewManager { */ public void hide(long startTime, long fadeoutDuration) { mShowing = false; - mPhoneStatusBar.hideKeyguard(); - mStatusBarWindowManager.setKeyguardFadingAway(true); - mStatusBarWindowManager.setKeyguardShowing(false); + long uptimeMillis = SystemClock.uptimeMillis(); long delay = startTime - uptimeMillis; if (delay < 0) { delay = 0; } + + mPhoneStatusBar.setKeyguardFadingAway(delay, fadeoutDuration); + mPhoneStatusBar.hideKeyguard(); + mStatusBarWindowManager.setKeyguardFadingAway(true); + mStatusBarWindowManager.setKeyguardShowing(false); mBouncer.animateHide(delay, fadeoutDuration); mScrimController.animateKeyguardFadingOut(delay, fadeoutDuration, new Runnable() { @Override public void run() { mStatusBarWindowManager.setKeyguardFadingAway(false); + mPhoneStatusBar.finishKeyguardFadingAway(); } }); mViewMediatorCallback.keyguardGone(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java new file mode 100644 index 000000000000..6f2642a67425 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java @@ -0,0 +1,219 @@ +/* + * 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.statusbar.phone; + +import com.android.systemui.R; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Shader; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; + +/** + * A view that displays a user image cropped to a circle with a frame. + */ +public class UserAvatarView extends View { + + private int mActiveFrameColor; + private int mFrameColor; + private float mFrameWidth; + private Bitmap mBitmap; + private Drawable mDrawable; + + private final Paint mFramePaint = new Paint(); + private final Paint mBitmapPaint = new Paint(); + private final Matrix mDrawMatrix = new Matrix(); + + private float mScale = 1; + + public UserAvatarView(Context context, AttributeSet attrs, + int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + final TypedArray a = context.obtainStyledAttributes( + attrs, R.styleable.UserAvatarView, defStyleAttr, defStyleRes); + final int N = a.getIndexCount(); + for (int i = 0; i < N; i++) { + int attr = a.getIndex(i); + switch (attr) { + case R.styleable.UserAvatarView_frameWidth: + setFrameWidth(a.getDimension(attr, 0)); + break; + case R.styleable.UserAvatarView_activeFrameColor: + setActiveFrameColor(a.getColor(attr, 0)); + break; + case R.styleable.UserAvatarView_frameColor: + setFrameColor(a.getColor(attr, 0)); + break; + } + } + a.recycle(); + + mFramePaint.setAntiAlias(true); + mFramePaint.setStyle(Paint.Style.STROKE); + mBitmapPaint.setAntiAlias(true); + } + + public UserAvatarView(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public UserAvatarView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public UserAvatarView(Context context) { + this(context, null); + } + + public void setBitmap(Bitmap bitmap) { + setDrawable(null); + mBitmap = bitmap; + if (mBitmap != null) { + mBitmapPaint.setShader(new BitmapShader( + bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)); + } else { + mBitmapPaint.setShader(null); + } + configureBounds(); + invalidate(); + } + + public void setFrameColor(int frameColor) { + mFrameColor = frameColor; + invalidate(); + } + + public void setActiveFrameColor(int activeFrameColor) { + mActiveFrameColor = activeFrameColor; + invalidate(); + } + + public void setFrameWidth(float frameWidth) { + mFrameWidth = frameWidth; + invalidate(); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + configureBounds(); + } + + public void configureBounds() { + int vwidth = getWidth() - mPaddingLeft - mPaddingRight; + int vheight = getHeight() - mPaddingTop - mPaddingBottom; + + int dwidth; + int dheight; + if (mBitmap != null) { + dwidth = mBitmap.getWidth(); + dheight = mBitmap.getHeight(); + } else if (mDrawable != null) { + dwidth = mDrawable.getIntrinsicWidth(); + dheight = mDrawable.getIntrinsicHeight(); + mDrawable.setBounds(0, 0, dwidth, dheight); + vwidth -= 2 * (mFrameWidth - 1); + vheight -= 2 * (mFrameWidth - 1); + } else { + return; + } + + float scale; + float dx; + float dy; + + scale = Math.min((float) vwidth / (float) dwidth, + (float) vheight / (float) dheight); + + dx = (int) ((vwidth - dwidth * scale) * 0.5f + 0.5f); + dy = (int) ((vheight - dheight * scale) * 0.5f + 0.5f); + + mDrawMatrix.setScale(scale, scale); + mDrawMatrix.postTranslate(dx, dy); + mScale = scale; + } + + @Override + protected void onDraw(Canvas canvas) { + int frameColor = isActivated() ? mActiveFrameColor : mFrameColor; + float halfW = getWidth() / 2f; + float halfH = getHeight() / 2f; + float halfSW = Math.min(halfH, halfW); + if (mBitmap != null && mScale > 0) { + int saveCount = canvas.getSaveCount(); + canvas.save(); + canvas.translate(mPaddingLeft, mPaddingTop); + canvas.concat(mDrawMatrix); + float halfBW = mBitmap.getWidth() / 2f; + float halfBH = mBitmap.getHeight() / 2f; + float halfBSW = Math.min(halfBH, halfBW); + canvas.drawCircle(halfBW, halfBH, halfBSW - mFrameWidth / mScale + 1, mBitmapPaint); + canvas.restoreToCount(saveCount); + } else if (mDrawable != null && mScale > 0) { + int saveCount = canvas.getSaveCount(); + canvas.save(); + canvas.translate(mPaddingLeft, mPaddingTop); + canvas.translate(mFrameWidth - 1, mFrameWidth - 1); + canvas.concat(mDrawMatrix); + mDrawable.draw(canvas); + canvas.restoreToCount(saveCount); + } + if (frameColor != 0) { + mFramePaint.setColor(frameColor); + mFramePaint.setStrokeWidth(mFrameWidth); + canvas.drawCircle(halfW, halfH, halfSW - mFrameWidth / 2f, mFramePaint); + } + } + + public void setDrawable(Drawable d) { + if (mDrawable != null) { + mDrawable.setCallback(null); + unscheduleDrawable(mDrawable); + } + mDrawable = d; + if (d != null) { + d.setCallback(this); + if (d.isStateful()) { + d.setState(getDrawableState()); + } + d.setLayoutDirection(getLayoutDirection()); + configureBounds(); + } + if (d != null) { + mBitmap = null; + } + configureBounds(); + invalidate(); + } + + @Override + public void invalidateDrawable(Drawable dr) { + if (dr == mDrawable) { + invalidate(); + } else { + super.invalidateDrawable(dr); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java new file mode 100644 index 000000000000..c90750c082e6 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java @@ -0,0 +1,209 @@ +/* + * 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.statusbar.policy; + +import com.android.systemui.R; +import com.android.systemui.statusbar.phone.StatusBarHeaderView; +import com.android.systemui.statusbar.phone.UserAvatarView; + +import android.app.ActivityManagerNative; +import android.content.Context; +import android.content.pm.UserInfo; +import android.graphics.Bitmap; +import android.os.AsyncTask; +import android.os.RemoteException; +import android.os.UserManager; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewStub; +import android.view.WindowManagerGlobal; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.List; + +/** + * Manages the user switcher on the Keyguard. + */ +public class KeyguardUserSwitcher implements View.OnClickListener { + + private static final String TAG = "KeyguardUserSwitcher"; + + private final Context mContext; + private final ViewGroup mUserSwitcher; + private final UserManager mUserManager; + private final StatusBarHeaderView mHeader; + + public KeyguardUserSwitcher(Context context, ViewStub userSwitcher, + StatusBarHeaderView header) { + mContext = context; + if (context.getResources().getBoolean(R.bool.config_keyguardUserSwitcher)) { + mUserSwitcher = (ViewGroup) userSwitcher.inflate(); + mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); + mHeader = header; + refresh(); + } else { + mUserSwitcher = null; + mUserManager = null; + mHeader = null; + } + } + + public void setKeyguard(boolean keyguard) { + if (mUserSwitcher != null) { + // TODO: Cache showUserSwitcherOnKeyguard(). + if (keyguard && showUserSwitcherOnKeyguard()) { + show(); + refresh(); + } else { + hide(); + } + } + } + + /** + * @return true if the user switcher should be shown on the lock screen. + * @see android.os.UserManager#isUserSwitcherEnabled() + */ + private boolean showUserSwitcherOnKeyguard() { + // TODO: Set isEdu. The edu provisioning process can add settings to Settings.Global. + boolean isEdu = false; + if (isEdu) { + return true; + } + List<UserInfo> users = mUserManager.getUsers(true /* excludeDying */); + int N = users.size(); + int switchableUsers = 0; + for (int i = 0; i < N; i++) { + if (users.get(i).supportsSwitchTo()) { + switchableUsers++; + } + } + return switchableUsers > 1; + } + + public void show() { + if (mUserSwitcher != null) { + // TODO: animate + mUserSwitcher.setVisibility(View.VISIBLE); + mHeader.setKeyguardUserSwitcherShowing(true); + } + } + + private void hide() { + if (mUserSwitcher != null) { + // TODO: animate + mUserSwitcher.setVisibility(View.GONE); + mHeader.setKeyguardUserSwitcherShowing(false); + } + } + + private void refresh() { + if (mUserSwitcher != null) { + new AsyncTask<Void, Void, ArrayList<UserData>>() { + @Override + protected ArrayList<UserData> doInBackground(Void... params) { + return loadUsers(); + } + + @Override + protected void onPostExecute(ArrayList<UserData> userInfos) { + bind(userInfos); + } + }.execute((Void[]) null); + } + } + + private void bind(ArrayList<UserData> userList) { + mUserSwitcher.removeAllViews(); + int N = userList.size(); + for (int i = 0; i < N; i++) { + mUserSwitcher.addView(inflateUser(userList.get(i))); + } + // TODO: add Guest + // TODO: add (+) button + } + + private View inflateUser(UserData user) { + View v = LayoutInflater.from(mUserSwitcher.getContext()).inflate( + R.layout.keyguard_user_switcher_item, mUserSwitcher, false); + TextView name = (TextView) v.findViewById(R.id.name); + UserAvatarView picture = (UserAvatarView) v.findViewById(R.id.picture); + name.setText(user.userInfo.name); + picture.setActivated(user.isCurrent); + if (user.userInfo.isGuest()) { + picture.setDrawable(mContext.getResources().getDrawable(R.drawable.ic_account_circle)); + } else { + picture.setBitmap(user.userIcon); + } + v.setOnClickListener(this); + v.setTag(user.userInfo); + // TODO: mark which user is current for accessibility. + return v; + } + + @Override + public void onClick(View v) { + switchUser(((UserInfo)v.getTag()).id); + } + + // TODO: Factor out logic below and share with QS implementation. + + private ArrayList<UserData> loadUsers() { + ArrayList<UserInfo> users = (ArrayList<UserInfo>) mUserManager + .getUsers(true /* excludeDying */); + int N = users.size(); + ArrayList<UserData> result = new ArrayList<>(N); + int currentUser = -1; + try { + currentUser = ActivityManagerNative.getDefault().getCurrentUser().id; + } catch (RemoteException e) { + Log.e(TAG, "Couln't get current user.", e); + } + for (int i = 0; i < N; i++) { + UserInfo user = users.get(i); + if (user.supportsSwitchTo()) { + boolean isCurrent = user.id == currentUser; + result.add(new UserData(user, mUserManager.getUserIcon(user.id), isCurrent)); + } + } + return result; + } + + private void switchUser(int userId) { + try { + WindowManagerGlobal.getWindowManagerService().lockNow(null); + ActivityManagerNative.getDefault().switchUser(userId); + } catch (RemoteException e) { + Log.e(TAG, "Couldn't switch user.", e); + } + } + + private static class UserData { + final UserInfo userInfo; + final Bitmap userIcon; + final boolean isCurrent; + + UserData(UserInfo userInfo, Bitmap userIcon, boolean isCurrent) { + this.userInfo = userInfo; + this.userIcon = userIcon; + this.isCurrent = isCurrent; + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java index 6d92b058b598..fcc951ebba00 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java @@ -32,6 +32,7 @@ public class AmbientState { private float mOverScrollTopAmount; private float mOverScrollBottomAmount; private int mSpeedBumpIndex = -1; + private float mScrimAmount; public int getScrollY() { return mScrollY; @@ -85,6 +86,14 @@ public class AmbientState { } } + public void setScrimAmount(float scrimAmount) { + mScrimAmount = scrimAmount; + } + + public float getScrimAmount() { + return mScrimAmount; + } + public float getOverScrollAmount(boolean top) { return top ? mOverScrollTopAmount : mOverScrollBottomAmount; } 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 ccbaed346e08..f6e9aefc5b20 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -541,8 +541,9 @@ public class NotificationStackScrollLayout extends ViewGroup if (slidingChild.getVisibility() == GONE) { continue; } - float top = slidingChild.getTranslationY(); - float bottom = top + slidingChild.getActualHeight(); + float childTop = slidingChild.getTranslationY(); + float top = childTop + slidingChild.getClipTopAmount(); + float bottom = childTop + slidingChild.getActualHeight(); int left = slidingChild.getLeft(); int right = slidingChild.getRight(); @@ -1845,6 +1846,11 @@ public class NotificationStackScrollLayout extends ViewGroup return true; } + public void setScrimAlpha(float progress) { + mAmbientState.setScrimAmount(progress); + requestChildrenUpdate(); + } + /** * A listener that is notified when some child locations might have changed. */ 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 602c22b37aea..9a4b7980a8e0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java @@ -154,6 +154,17 @@ public class StackScrollAlgorithm { handleDraggedViews(ambientState, resultState, algorithmState); updateDimmedActivated(ambientState, resultState, algorithmState); updateClipping(resultState, algorithmState); + updateScrimAmount(resultState, algorithmState, ambientState.getScrimAmount()); + } + + private void updateScrimAmount(StackScrollState resultState, + StackScrollAlgorithmState algorithmState, float scrimAmount) { + int childCount = algorithmState.visibleChildren.size(); + for (int i = 0; i < childCount; i++) { + View child = algorithmState.visibleChildren.get(i); + StackScrollState.ViewState childViewState = resultState.getViewStateForView(child); + childViewState.scrimAmount = scrimAmount; + } } private void updateClipping(StackScrollState resultState, 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 1ad4accb20f6..02f2cd64c6d5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java @@ -148,6 +148,9 @@ public class StackScrollState { // apply dimming child.setDimmed(state.dimmed, false /* animate */); + // apply scrimming + child.setScrimAmount(state.scrimAmount); + float oldClipTopAmount = child.getClipTopAmount(); if (oldClipTopAmount != state.clipTopAmount) { child.setClipTopAmount(state.clipTopAmount); @@ -223,6 +226,12 @@ public class StackScrollState { boolean dimmed; /** + * A value between 0 and 1 indicating how much the view should be scrimmed. + * 1 means that the notifications will be darkened as much as possible. + */ + float scrimAmount; + + /** * The amount which the view should be clipped from the top. This is calculated to * perceive consistent shadows. */ 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 225398a4c939..0006dadc9703 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java @@ -176,6 +176,9 @@ public class StackStateAnimator { // start dimmed animation child.setDimmed(viewState.dimmed, mAnimationFilter.animateDimmed); + // apply scrimming + child.setScrimAmount(viewState.scrimAmount); + if (wasAdded) { child.performAddAnimation(delay); } diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java index 9e893da02c70..9f080cabd5ff 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java @@ -219,6 +219,7 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo // Wait for a down key event to start processing. if (!mKeyEventSequenceStarted) { if (event.getAction() != KeyEvent.ACTION_DOWN) { + super.onInputEvent(event, policyFlags); return; } mKeyEventSequenceStarted = true; diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 816e022c324f..69262c8405ba 100755 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -1328,7 +1328,7 @@ public final class ActiveServices { + " app=" + app); if (app != null && app.thread != null) { try { - app.addPackage(r.appInfo.packageName, mAm.mProcessStats); + app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats); realStartServiceLocked(r, app, execInFg); return null; } catch (RemoteException e) { @@ -1883,7 +1883,8 @@ public final class ActiveServices { mPendingServices.remove(i); i--; - proc.addPackage(sr.appInfo.packageName, mAm.mProcessStats); + proc.addPackage(sr.appInfo.packageName, sr.appInfo.versionCode, + mAm.mProcessStats); realStartServiceLocked(sr, proc, sr.createdFromFg); didSomething = true; } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 34c1ecd7b72f..40251b9825c7 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -570,6 +570,12 @@ public final class ActivityManagerService extends ActivityManagerNative long mLastFullPssTime = SystemClock.uptimeMillis(); /** + * If set, the next time we collect PSS data we should do a full collection + * with data from native processes and the kernel. + */ + boolean mFullPssPending = false; + + /** * This is the process holding what we currently consider to be * the "home" activity. */ @@ -1801,8 +1807,49 @@ public final class ActivityManagerService extends ActivityManagerNative public void handleMessage(Message msg) { switch (msg.what) { case COLLECT_PSS_BG_MSG: { - int i=0, num=0; long start = SystemClock.uptimeMillis(); + MemInfoReader memInfo = null; + synchronized (ActivityManagerService.this) { + if (mFullPssPending) { + mFullPssPending = false; + memInfo = new MemInfoReader(); + } + } + if (memInfo != null) { + updateCpuStatsNow(); + long nativeTotalPss = 0; + synchronized (mProcessCpuThread) { + final int N = mProcessCpuTracker.countStats(); + for (int j=0; j<N; j++) { + ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(j); + if (st.vsize <= 0 || st.uid >= Process.FIRST_APPLICATION_UID + || st.uid == Process.SYSTEM_UID) { + // This is definitely an application process; skip it. + continue; + } + synchronized (mPidsSelfLocked) { + if (mPidsSelfLocked.indexOfKey(st.pid) >= 0) { + // This is one of our own processes; skip it. + continue; + } + } + nativeTotalPss += Debug.getPss(st.pid, null); + } + } + memInfo.readMemInfo(); + synchronized (this) { + if (DEBUG_PSS) Slog.d(TAG, "Collected native and kernel memory in " + + (SystemClock.uptimeMillis()-start) + "ms"); + mProcessStats.addSysMemUsageLocked(memInfo.getCachedSizeKb(), + memInfo.getFreeSizeKb(), + memInfo.getSwapTotalSizeKb()-memInfo.getSwapFreeSizeKb(), + memInfo.getBuffersSizeKb()+memInfo.getShmemSizeKb() + +memInfo.getSlabSizeKb(), + nativeTotalPss); + } + } + + int i=0, num=0; long[] tmp = new long[1]; do { ProcessRecord proc; @@ -2769,7 +2816,7 @@ public final class ActivityManagerService extends ActivityManagerNative // come up (we have a pid but not yet its thread), so keep it. if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app); // If this is a new package in the process, add the package to the list - app.addPackage(info.packageName, mProcessStats); + app.addPackage(info.packageName, info.versionCode, mProcessStats); return app; } @@ -2824,7 +2871,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } else { // If this is a new package in the process, add the package to the list - app.addPackage(info.packageName, mProcessStats); + app.addPackage(info.packageName, info.versionCode, mProcessStats); } // If the system is not ready yet, then hold off on starting this @@ -6044,7 +6091,11 @@ public final class ActivityManagerService extends ActivityManagerNative if (UserHandle.getUserId(uid) != grantUri.sourceUserId) { return false; } + return checkHoldingPermissionsInternalLocked(pm, pi, grantUri, uid, modeFlags, true); + } + private final boolean checkHoldingPermissionsInternalLocked(IPackageManager pm, ProviderInfo pi, + GrantUri grantUri, int uid, final int modeFlags, boolean considerUidPermissions) { if (pi.applicationInfo.uid == uid) { return true; } else if (!pi.exported) { @@ -6055,11 +6106,11 @@ public final class ActivityManagerService extends ActivityManagerNative boolean writeMet = (modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0; try { // check if target holds top-level <provider> permissions - if (!readMet && pi.readPermission != null + if (!readMet && pi.readPermission != null && considerUidPermissions && (pm.checkUidPermission(pi.readPermission, uid) == PERMISSION_GRANTED)) { readMet = true; } - if (!writeMet && pi.writePermission != null + if (!writeMet && pi.writePermission != null && considerUidPermissions && (pm.checkUidPermission(pi.writePermission, uid) == PERMISSION_GRANTED)) { writeMet = true; } @@ -6085,7 +6136,8 @@ public final class ActivityManagerService extends ActivityManagerNative + ": match=" + pp.match(path) + " check=" + pm.checkUidPermission(pprperm, uid)); if (pprperm != null) { - if (pm.checkUidPermission(pprperm, uid) == PERMISSION_GRANTED) { + if (considerUidPermissions && pm.checkUidPermission(pprperm, uid) + == PERMISSION_GRANTED) { readMet = true; } else { allowDefaultRead = false; @@ -6099,7 +6151,8 @@ public final class ActivityManagerService extends ActivityManagerNative + ": match=" + pp.match(path) + " check=" + pm.checkUidPermission(ppwperm, uid)); if (ppwperm != null) { - if (pm.checkUidPermission(ppwperm, uid) == PERMISSION_GRANTED) { + if (considerUidPermissions && pm.checkUidPermission(ppwperm, uid) + == PERMISSION_GRANTED) { writeMet = true; } else { allowDefaultWrite = false; @@ -6296,28 +6349,40 @@ public final class ActivityManagerService extends ActivityManagerNative } } + /* There is a special cross user grant if: + * - The target is on another user. + * - Apps on the current user can access the uri without any uid permissions. + * In this case, we grant a uri permission, even if the ContentProvider does not normally + * grant uri permissions. + */ + boolean specialCrossUserGrant = UserHandle.getUserId(targetUid) != grantUri.sourceUserId + && checkHoldingPermissionsInternalLocked(pm, pi, grantUri, callingUid, + modeFlags, false /*without considering the uid permissions*/); + // Second... is the provider allowing granting of URI permissions? - if (!pi.grantUriPermissions) { - throw new SecurityException("Provider " + pi.packageName - + "/" + pi.name - + " does not allow granting of Uri permissions (uri " - + grantUri + ")"); - } - if (pi.uriPermissionPatterns != null) { - final int N = pi.uriPermissionPatterns.length; - boolean allowed = false; - for (int i=0; i<N; i++) { - if (pi.uriPermissionPatterns[i] != null - && pi.uriPermissionPatterns[i].match(grantUri.uri.getPath())) { - allowed = true; - break; - } - } - if (!allowed) { + if (!specialCrossUserGrant) { + if (!pi.grantUriPermissions) { throw new SecurityException("Provider " + pi.packageName + "/" + pi.name - + " does not allow granting of permission to path of Uri " - + grantUri); + + " does not allow granting of Uri permissions (uri " + + grantUri + ")"); + } + if (pi.uriPermissionPatterns != null) { + final int N = pi.uriPermissionPatterns.length; + boolean allowed = false; + for (int i=0; i<N; i++) { + if (pi.uriPermissionPatterns[i] != null + && pi.uriPermissionPatterns[i].match(grantUri.uri.getPath())) { + allowed = true; + break; + } + } + if (!allowed) { + throw new SecurityException("Provider " + pi.packageName + + "/" + pi.name + + " does not allow granting of permission to path of Uri " + + grantUri); + } } } @@ -7780,7 +7845,8 @@ public final class ActivityManagerService extends ActivityManagerNative // to run in multiple processes, because this is actually // part of the framework so doesn't make sense to track as a // separate apk in the process. - app.addPackage(cpi.applicationInfo.packageName, mProcessStats); + app.addPackage(cpi.applicationInfo.packageName, cpi.applicationInfo.versionCode, + mProcessStats); } ensurePackageDexOpt(cpi.applicationInfo.packageName); } @@ -12588,6 +12654,8 @@ public final class ActivityManagerService extends ActivityManagerNative } } + long nativeProcTotalPss = 0; + if (!isCheckinRequest && procs.size() > 1) { // If we are showing aggregations, also look for native processes to // include so that our aggregations are more accurate. @@ -12609,6 +12677,7 @@ public final class ActivityManagerService extends ActivityManagerNative final long myTotalPss = mi.getTotalPss(); totalPss += myTotalPss; + nativeProcTotalPss += myTotalPss; MemItem pssItem = new MemItem(st.name + " (pid " + st.pid + ")", st.name, myTotalPss, st.pid, false); @@ -12676,6 +12745,15 @@ public final class ActivityManagerService extends ActivityManagerNative } MemInfoReader memInfo = new MemInfoReader(); memInfo.readMemInfo(); + if (nativeProcTotalPss > 0) { + synchronized (this) { + mProcessStats.addSysMemUsageLocked(memInfo.getCachedSizeKb(), + memInfo.getFreeSizeKb(), + memInfo.getSwapTotalSizeKb()-memInfo.getSwapFreeSizeKb(), + memInfo.getBuffersSizeKb()+memInfo.getShmemSizeKb()+memInfo.getSlabSizeKb(), + nativeProcTotalPss); + } + } if (!brief) { if (!isCompact) { pw.print("Total RAM: "); pw.print(memInfo.getTotalSizeKb()); @@ -15456,6 +15534,7 @@ public final class ActivityManagerService extends ActivityManagerNative } if (DEBUG_PSS) Slog.d(TAG, "Requesting PSS of all procs! memLowered=" + memLowered); mLastFullPssTime = now; + mFullPssPending = true; mPendingPssProcesses.ensureCapacity(mLruProcesses.size()); mPendingPssProcesses.clear(); for (int i=mLruProcesses.size()-1; i>=0; i--) { diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index dd9cae90dd00..0825f2e75554 100755 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -582,11 +582,6 @@ final class ActivityRecord { } } - boolean isRootActivity() { - final ArrayList<ActivityRecord> activities = task.mActivities; - return activities.size() == 0 || this == activities.get(0); - } - UriPermissionOwner getUriPermissionsLocked() { if (uriPermissions == null) { uriPermissions = new UriPermissionOwner(service, this); @@ -1035,11 +1030,11 @@ final class ActivityRecord { return -1; } final TaskRecord task = r.task; - switch (task.mActivities.indexOf(r)) { - case -1: return -1; - case 0: return task.taskId; - default: return onlyRoot ? -1 : task.taskId; + final int activityNdx = task.mActivities.indexOf(r); + if (activityNdx < 0 || (onlyRoot && activityNdx > task.findEffectiveRootIndex())) { + return -1; } + return task.taskId; } static ActivityRecord isInStackLocked(IBinder token) { diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 03ce5300e863..fe2a473e3173 100755 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -1066,40 +1066,6 @@ final class ActivityStack { } } - /** - * Determine if home should be visible below the passed record. - * @param record activity we are querying for. - * @return true if home is visible below the passed activity, false otherwise. - */ - boolean isActivityOverHome(ActivityRecord record) { - // Start at record and go down, look for either home or a visible fullscreen activity. - final TaskRecord recordTask = record.task; - for (int taskNdx = mTaskHistory.indexOf(recordTask); taskNdx >= 0; --taskNdx) { - TaskRecord task = mTaskHistory.get(taskNdx); - final ArrayList<ActivityRecord> activities = task.mActivities; - final int startNdx = - task == recordTask ? activities.indexOf(record) : activities.size() - 1; - for (int activityNdx = startNdx; activityNdx >= 0; --activityNdx) { - final ActivityRecord r = activities.get(activityNdx); - if (r.isHomeActivity()) { - return true; - } - if (!r.finishing && r.fullscreen) { - // Passed activity is over a fullscreen activity. - return false; - } - } - if (task.mOnTopOfHome) { - // Got to the bottom of a task on top of home without finding a visible fullscreen - // activity. Home is visible. - return true; - } - } - // Got to the bottom of this stack and still don't know. If this is over the home stack - // then record is over home. May not work if we ever get more than two layers. - return mStackSupervisor.isFrontStack(this); - } - private void setVisibile(ActivityRecord r, boolean visible) { r.visible = visible; mWindowManager.setAppVisibility(r.appToken, visible); @@ -1954,8 +1920,7 @@ final class ActivityStack { // existing activities from other tasks in to it. // If the caller has requested that the target task be // reset, then do so. - if ((r.intent.getFlags() - & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { + if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { resetTaskIfNeededLocked(r, r); doShow = topRunningNonDelayedActivityLocked(null) == r; } @@ -2048,7 +2013,8 @@ final class ActivityStack { // the root, we may no longer have the task!). final ArrayList<ActivityRecord> activities = task.mActivities; final int numActivities = activities.size(); - for (int i = numActivities - 1; i > 0; --i ) { + final int rootActivityNdx = task.findEffectiveRootIndex(); + for (int i = numActivities - 1; i > rootActivityNdx; --i ) { ActivityRecord target = activities.get(i); final int flags = target.info.flags; @@ -2207,8 +2173,10 @@ final class ActivityStack { final ArrayList<ActivityRecord> activities = affinityTask.mActivities; final int numActivities = activities.size(); - // Do not operate on the root Activity. - for (int i = numActivities - 1; i > 0; --i) { + final int rootActivityNdx = affinityTask.findEffectiveRootIndex(); + + // Do not operate on or below the effective root Activity. + for (int i = numActivities - 1; i > rootActivityNdx; --i) { ActivityRecord target = activities.get(i); final int flags = target.info.flags; diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 9264186c6329..976352367721 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -1178,7 +1178,8 @@ public final class ActivityStackSupervisor implements DisplayListener { // to run in multiple processes, because this is actually // part of the framework so doesn't make sense to track as a // separate apk in the process. - app.addPackage(r.info.packageName, mService.mProcessStats); + app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode, + mService.mProcessStats); } realStartActivityLocked(r, app, andResume, checkConfig); return; diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 7b2b04da278f..cdcc74b2685b 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -887,7 +887,8 @@ public final class BroadcastQueue { info.activityInfo.applicationInfo.uid, false); if (app != null && app.thread != null) { try { - app.addPackage(info.activityInfo.packageName, mService.mProcessStats); + app.addPackage(info.activityInfo.packageName, + info.activityInfo.applicationInfo.versionCode, mService.mProcessStats); processCurBroadcastLocked(r, app); return; } catch (RemoteException e) { diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 8d7d300941b5..a5b80bcc9e84 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -53,8 +53,8 @@ final class ProcessRecord { final int userId; // user of process. final String processName; // name of the process // List of packages running in the process - final ArrayMap<String, ProcessStats.ProcessState> pkgList - = new ArrayMap<String, ProcessStats.ProcessState>(); + final ArrayMap<String, ProcessStats.ProcessStateHolder> pkgList + = new ArrayMap<String, ProcessStats.ProcessStateHolder>(); IApplicationThread thread; // the actual proc... may be null only if // 'persistent' is true (in which case we // are in the process of launching the app) @@ -371,7 +371,7 @@ final class ProcessRecord { uid = _uid; userId = UserHandle.getUserId(_uid); processName = _processName; - pkgList.put(_info.packageName, null); + pkgList.put(_info.packageName, new ProcessStats.ProcessStateHolder(_info.versionCode)); maxAdj = ProcessList.UNKNOWN_ADJ; curRawAdj = setRawAdj = -100; curAdj = setAdj = -100; @@ -398,16 +398,15 @@ final class ProcessRecord { info.versionCode, processName); baseProcessTracker.makeActive(); for (int i=0; i<pkgList.size(); i++) { - ProcessStats.ProcessState ps = pkgList.valueAt(i); - if (ps != null && ps != origBase) { - ps.makeInactive(); + ProcessStats.ProcessStateHolder holder = pkgList.valueAt(i); + if (holder.state != null && holder.state != origBase) { + holder.state.makeInactive(); } - ps = tracker.getProcessStateLocked(pkgList.keyAt(i), info.uid, + holder.state = tracker.getProcessStateLocked(pkgList.keyAt(i), info.uid, info.versionCode, processName); - if (ps != baseProcessTracker) { - ps.makeActive(); + if (holder.state != baseProcessTracker) { + holder.state.makeActive(); } - pkgList.setValueAt(i, ps); } } thread = _thread; @@ -424,11 +423,11 @@ final class ProcessRecord { } baseProcessTracker = null; for (int i=0; i<pkgList.size(); i++) { - ProcessStats.ProcessState ps = pkgList.valueAt(i); - if (ps != null && ps != origBase) { - ps.makeInactive(); + ProcessStats.ProcessStateHolder holder = pkgList.valueAt(i); + if (holder.state != null && holder.state != origBase) { + holder.state.makeInactive(); } - pkgList.setValueAt(i, null); + holder.state = null; } } } @@ -572,14 +571,16 @@ final class ProcessRecord { /* * Return true if package has been added false if not */ - public boolean addPackage(String pkg, ProcessStatsService tracker) { + public boolean addPackage(String pkg, int versionCode, ProcessStatsService tracker) { if (!pkgList.containsKey(pkg)) { if (baseProcessTracker != null) { - ProcessStats.ProcessState state = tracker.getProcessStateLocked( - pkg, info.uid, info.versionCode, processName); - pkgList.put(pkg, state); - if (state != baseProcessTracker) { - state.makeActive(); + ProcessStats.ProcessStateHolder holder = new ProcessStats.ProcessStateHolder( + versionCode); + holder.state = tracker.getProcessStateLocked( + pkg, info.uid, versionCode, processName); + pkgList.put(pkg, holder); + if (holder.state != baseProcessTracker) { + holder.state.makeActive(); } } else { pkgList.put(pkg, null); @@ -615,23 +616,26 @@ final class ProcessRecord { tracker.getMemFactorLocked(), now, pkgList); if (N != 1) { for (int i=0; i<N; i++) { - ProcessStats.ProcessState ps = pkgList.valueAt(i); - if (ps != null && ps != baseProcessTracker) { - ps.makeInactive(); + ProcessStats.ProcessStateHolder holder = pkgList.valueAt(i); + if (holder.state != null && holder.state != baseProcessTracker) { + holder.state.makeInactive(); } } pkgList.clear(); ProcessStats.ProcessState ps = tracker.getProcessStateLocked( info.packageName, info.uid, info.versionCode, processName); - pkgList.put(info.packageName, ps); + ProcessStats.ProcessStateHolder holder = new ProcessStats.ProcessStateHolder( + info.versionCode); + holder.state = ps; + pkgList.put(info.packageName, holder); if (ps != baseProcessTracker) { ps.makeActive(); } } } else if (N != 1) { pkgList.clear(); - pkgList.put(info.packageName, null); + pkgList.put(info.packageName, new ProcessStats.ProcessStateHolder(info.versionCode)); } } diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java index 14f3ef981375..7ec14c295bd6 100644 --- a/services/core/java/com/android/server/am/ProcessStatsService.java +++ b/services/core/java/com/android/server/am/ProcessStatsService.java @@ -171,10 +171,17 @@ public final class ProcessStatsService extends IProcessStats.Stub { return mProcessStats.mMemFactor != ProcessStats.STATE_NOTHING ? mProcessStats.mMemFactor : 0; } + public void addSysMemUsageLocked(long cachedMem, long freeMem, long zramMem, long kernelMem, + long nativeMem) { + mProcessStats.addSysMemUsage(cachedMem, freeMem, zramMem, kernelMem, nativeMem); + } + public boolean shouldWriteNowLocked(long now) { if (now > (mLastWriteTime+WRITE_PERIOD)) { if (SystemClock.elapsedRealtime() - > (mProcessStats.mTimePeriodStartRealtime+ProcessStats.COMMIT_PERIOD)) { + > (mProcessStats.mTimePeriodStartRealtime+ProcessStats.COMMIT_PERIOD) && + SystemClock.uptimeMillis() + > (mProcessStats.mTimePeriodStartUptime+ProcessStats.COMMIT_UPTIME_PERIOD)) { mCommitPending = true; } return true; @@ -212,6 +219,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { if (mPendingWrite == null || !mPendingWriteCommitted) { mPendingWrite = Parcel.obtain(); mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime(); + mProcessStats.mTimePeriodEndUptime = now; if (commit) { mProcessStats.mFlags |= ProcessStats.FLAG_COMPLETE; } @@ -439,8 +447,10 @@ public final class ProcessStatsService extends IProcessStats.Stub { mWriteLock.lock(); try { synchronized (mAm) { + long now = SystemClock.uptimeMillis(); mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime(); - mProcessStats.writeToParcel(current, 0); + mProcessStats.mTimePeriodEndUptime = now; + mProcessStats.writeToParcel(current, now, 0); } if (historic != null) { ArrayList<String> files = getCommittedFiles(0, false, true); @@ -470,8 +480,10 @@ public final class ProcessStatsService extends IProcessStats.Stub { Parcel current = Parcel.obtain(); long curTime; synchronized (mAm) { + long now = SystemClock.uptimeMillis(); mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime(); - mProcessStats.writeToParcel(current, 0); + mProcessStats.mTimePeriodEndUptime = now; + mProcessStats.writeToParcel(current, now, 0); curTime = mProcessStats.mTimePeriodEndRealtime - mProcessStats.mTimePeriodStartRealtime; } @@ -568,8 +580,8 @@ public final class ProcessStatsService extends IProcessStats.Stub { static private void dumpHelp(PrintWriter pw) { pw.println("Process stats (procstats) dump options:"); pw.println(" [--checkin|-c|--csv] [--csv-screen] [--csv-proc] [--csv-mem]"); - pw.println(" [--details] [--full-details] [--current] [--hours] [--active]"); - pw.println(" [--commit] [--reset] [--clear] [--write] [-h] [<package.name>]"); + pw.println(" [--details] [--full-details] [--current] [--hours N] [--last N]"); + pw.println(" [--active] [--commit] [--reset] [--clear] [--write] [-h] [<package.name>]"); pw.println(" --checkin: perform a checkin: print and delete old committed states."); pw.println(" --c: print only state in checkin format."); pw.println(" --csv: output data suitable for putting in a spreadsheet."); @@ -581,6 +593,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { pw.println(" --full-details: dump all timing and active state details."); pw.println(" --current: only dump current state."); pw.println(" --hours: aggregate over about N last hours."); + pw.println(" --last: only show the last committed stats at index N (starting at 1)."); pw.println(" --active: only show currently active processes/services."); pw.println(" --commit: commit current stats to disk and reset to start new stats."); pw.println(" --reset: reset current stats, without committing."); @@ -621,6 +634,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { boolean dumpFullDetails = false; boolean dumpAll = false; int aggregateHours = 0; + int lastIndex = 0; boolean activeOnly = false; String reqPackage = null; boolean csvSepScreenStats = false; @@ -705,6 +719,20 @@ public final class ProcessStatsService extends IProcessStats.Stub { dumpHelp(pw); return; } + } else if ("--last".equals(arg)) { + i++; + if (i >= args.length) { + pw.println("Error: argument required for --last"); + dumpHelp(pw); + return; + } + try { + lastIndex = Integer.parseInt(args[i]); + } catch (NumberFormatException e) { + pw.println("Error: --last argument not an int -- " + args[i]); + dumpHelp(pw); + return; + } } else if ("--active".equals(arg)) { activeOnly = true; currentOnly = true; @@ -818,6 +846,43 @@ public final class ProcessStatsService extends IProcessStats.Stub { dumpAggregatedStats(pw, aggregateHours, now, reqPackage, isCompact, dumpDetails, dumpFullDetails, dumpAll, activeOnly); return; + } else if (lastIndex > 0) { + pw.print("LAST STATS AT INDEX "); pw.print(lastIndex); pw.println(":"); + ArrayList<String> files = getCommittedFiles(0, false, true); + if (lastIndex >= files.size()) { + pw.print("Only have "); pw.print(files.size()); pw.println(" data sets"); + return; + } + AtomicFile file = new AtomicFile(new File(files.get(lastIndex))); + ProcessStats processStats = new ProcessStats(false); + readLocked(processStats, file); + if (processStats.mReadError != null) { + if (isCheckin || isCompact) pw.print("err,"); + pw.print("Failure reading "); pw.print(files.get(lastIndex)); + pw.print("; "); pw.println(processStats.mReadError); + return; + } + String fileStr = file.getBaseFile().getPath(); + boolean checkedIn = fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX); + if (isCheckin || isCompact) { + // Don't really need to lock because we uniquely own this object. + processStats.dumpCheckinLocked(pw, reqPackage); + } else { + pw.print("COMMITTED STATS FROM "); + pw.print(processStats.mTimePeriodStartClockStr); + if (checkedIn) pw.print(" (checked in)"); + pw.println(":"); + if (dumpDetails || dumpFullDetails) { + processStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll, + activeOnly); + if (dumpAll) { + pw.print(" mFile="); pw.println(mFile.getBaseFile()); + } + } else { + processStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly); + } + } + return; } boolean sepNeeded = false; @@ -859,7 +924,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { // Always dump summary here, dumping all details is just too // much crud. if (dumpFullDetails) { - mProcessStats.dumpLocked(pw, reqPackage, now, false, false, + processStats.dumpLocked(pw, reqPackage, now, false, false, activeOnly); } else { processStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly); diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 1cde41fb92ad..9fff329b7bca 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -27,7 +27,6 @@ import android.content.ComponentName; import android.content.Intent; import android.content.pm.ActivityInfo; import android.graphics.Bitmap; -import android.os.SystemClock; import android.os.UserHandle; import android.service.voice.IVoiceInteractionSession; import android.util.Slog; @@ -57,11 +56,12 @@ final class TaskRecord extends ThumbnailHolder { private static final String ATTR_ONTOPOFHOME = "on_top_of_home"; private static final String ATTR_LASTDESCRIPTION = "last_description"; private static final String ATTR_LASTTIMEMOVED = "last_time_moved"; + private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity"; private static final String TASK_THUMBNAIL_SUFFIX = "_task_thumbnail"; final int taskId; // Unique identifier for this task. - final String affinity; // The affinity name for this task, or null. + String affinity; // The affinity name for this task, or null. final IVoiceInteractionSession voiceSession; // Voice interaction session driving task final IVoiceInteractor voiceInteractor; // Associated interactor to provide to app Intent intent; // The original intent that started the task. @@ -111,13 +111,15 @@ final class TaskRecord extends ThumbnailHolder { * Display.DEFAULT_DISPLAY. */ boolean mOnTopOfHome = false; + /** If original intent did not allow relinquishing task identity, save that information */ + boolean mNeverRelinquishIdentity = true; + final ActivityManagerService mService; TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent, IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) { mService = service; taskId = _taskId; - affinity = info.taskAffinity; voiceSession = _voiceSession; voiceInteractor = _voiceInteractor; setIntent(_intent, info); @@ -128,7 +130,7 @@ final class TaskRecord extends ThumbnailHolder { String _affinity, ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset, boolean _askedCompatMode, int _taskType, boolean _onTopOfHome, int _userId, String _lastDescription, ArrayList<ActivityRecord> activities, - long lastTimeMoved) { + long lastTimeMoved, boolean neverRelinquishIdentity) { mService = service; taskId = _taskId; intent = _intent; @@ -146,6 +148,7 @@ final class TaskRecord extends ThumbnailHolder { lastDescription = _lastDescription; mActivities = activities; mLastTimeMoved = lastTimeMoved; + mNeverRelinquishIdentity = neverRelinquishIdentity; } void touchActiveTime() { @@ -157,6 +160,14 @@ final class TaskRecord extends ThumbnailHolder { } void setIntent(Intent _intent, ActivityInfo info) { + if (intent == null) { + mNeverRelinquishIdentity = + (info.flags & ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY) == 0; + } else if (mNeverRelinquishIdentity) { + return; + } + + affinity = info.taskAffinity; stringName = null; if (info.targetActivity == null) { @@ -282,6 +293,7 @@ final class TaskRecord extends ThumbnailHolder { mActivities.remove(newTop); mActivities.add(newTop); + updateEffectiveIntent(); setFrontOfTask(); } @@ -311,6 +323,7 @@ final class TaskRecord extends ThumbnailHolder { r.mActivityType = taskType; } mActivities.add(index, r); + updateEffectiveIntent(); if (r.isPersistable()) { mService.notifyTaskPersisterLocked(this, false); } @@ -322,6 +335,7 @@ final class TaskRecord extends ThumbnailHolder { // Was previously in list. numFullscreen--; } + updateEffectiveIntent(); if (r.isPersistable()) { mService.notifyTaskPersisterLocked(this, false); } @@ -579,12 +593,19 @@ final class TaskRecord extends ThumbnailHolder { // utility activities. int activityNdx; final int numActivities = mActivities.size(); + final boolean relinquish = numActivities == 0 ? false : + (mActivities.get(0).info.flags & ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY) != 0; for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities; ++activityNdx) { final ActivityRecord r = mActivities.get(activityNdx); + if (relinquish && (r.info.flags & ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY) == 0) { + // This will be the top activity for determining taskDescription. Pre-inc to + // overcome initial decrement below. + ++activityNdx; + break; + } if (r.intent != null && - (r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) - != 0) { + (r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) { break; } } @@ -615,6 +636,27 @@ final class TaskRecord extends ThumbnailHolder { } } + int findEffectiveRootIndex() { + int activityNdx; + final int topActivityNdx = mActivities.size() - 1; + for (activityNdx = 0; activityNdx < topActivityNdx; ++activityNdx) { + final ActivityRecord r = mActivities.get(activityNdx); + if (r.finishing) { + continue; + } + if ((r.info.flags & ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY) == 0) { + break; + } + } + return activityNdx; + } + + void updateEffectiveIntent() { + final int effectiveRootIndex = findEffectiveRootIndex(); + final ActivityRecord r = mActivities.get(effectiveRootIndex); + setIntent(r.intent, r.info); + } + void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException { Slog.i(TAG, "Saving task=" + this); @@ -634,6 +676,7 @@ final class TaskRecord extends ThumbnailHolder { out.attribute(null, ATTR_TASKTYPE, String.valueOf(taskType)); out.attribute(null, ATTR_ONTOPOFHOME, String.valueOf(mOnTopOfHome)); out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved)); + out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity)); if (lastDescription != null) { out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString()); } @@ -684,6 +727,7 @@ final class TaskRecord extends ThumbnailHolder { int userId = 0; String lastDescription = null; long lastTimeOnTop = 0; + boolean neverRelinquishIdentity = true; int taskId = -1; final int outerDepth = in.getDepth(); @@ -714,6 +758,8 @@ final class TaskRecord extends ThumbnailHolder { lastDescription = attrValue; } else if (ATTR_LASTTIMEMOVED.equals(attrName)) { lastTimeOnTop = Long.valueOf(attrValue); + } else if (ATTR_NEVERRELINQUISH.equals(attrName)) { + neverRelinquishIdentity = Boolean.valueOf(attrValue); } else { Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName); } @@ -748,7 +794,7 @@ final class TaskRecord extends ThumbnailHolder { final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent, affinityIntent, affinity, realActivity, origActivity, rootHasReset, askedCompatMode, taskType, onTopOfHome, userId, lastDescription, activities, - lastTimeOnTop); + lastTimeOnTop, neverRelinquishIdentity); for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index 353f6036bcfc..52c092cd7e05 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -78,7 +78,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { */ void deviceSelect(int targetAddress, IHdmiControlCallback callback) { assertRunOnServiceThread(); - HdmiCecDeviceInfo targetDevice = mService.getDeviceInfo(targetAddress); + HdmiCecDeviceInfo targetDevice = getDeviceInfo(targetAddress); if (targetDevice == null) { invokeCallback(callback, HdmiCec.RESULT_TARGET_NOT_AVAILABLE); return; @@ -142,6 +142,9 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { } private static void invokeCallback(IHdmiControlCallback callback, int result) { + if (callback == null) { + return; + } try { callback.onComplete(result); } catch (RemoteException e) { @@ -455,8 +458,11 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { final void addCecDevice(HdmiCecDeviceInfo info) { assertRunOnServiceThread(); addDeviceInfo(info); - - // TODO: announce new device detection. + if (info.getLogicalAddress() == mAddress) { + // The addition of TV device itself should not be notified. + return; + } + mService.invokeDeviceEventListeners(info, true); } /** @@ -466,10 +472,9 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { */ final void removeCecDevice(int address) { assertRunOnServiceThread(); - removeDeviceInfo(address); + HdmiCecDeviceInfo info = removeDeviceInfo(address); mCecMessageCache.flushMessagesFrom(address); - - // TODO: announce a device removal. + mService.invokeDeviceEventListeners(info, false); } /** diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index fddb833c7c88..d323f34ed101 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -37,6 +37,7 @@ import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; +import com.android.internal.annotations.GuardedBy; import com.android.server.SystemService; import com.android.server.hdmi.HdmiCecController.AllocateAddressCallback; @@ -94,21 +95,25 @@ public final class HdmiControlService extends SystemService { // List of listeners registered by callers that want to get notified of // hotplug events. + @GuardedBy("mLock") private final ArrayList<IHdmiHotplugEventListener> mHotplugEventListeners = new ArrayList<>(); // List of records for hotplug event listener to handle the the caller killed in action. + @GuardedBy("mLock") private final ArrayList<HotplugEventListenerRecord> mHotplugEventListenerRecords = new ArrayList<>(); // List of listeners registered by callers that want to get notified of // device status events. + @GuardedBy("mLock") private final ArrayList<IHdmiDeviceEventListener> mDeviceEventListeners = new ArrayList<>(); // List of records for device event listener to handle the the caller killed in action. + @GuardedBy("mLock") private final ArrayList<DeviceEventListenerRecord> mDeviceEventListenerRecords = new ArrayList<>(); - // Handler running on service thread. It's used to run a task in service thread. + // Handler used to run a task in service thread. private final Handler mHandler = new Handler(); @Nullable @@ -153,6 +158,7 @@ public final class HdmiControlService extends SystemService { // A container for [Logical Address, Local device info]. final SparseArray<HdmiCecLocalDevice> devices = new SparseArray<>(); final SparseIntArray finished = new SparseIntArray(); + mCecController.clearLogicalAddress(); for (int type : deviceTypes) { final HdmiCecLocalDevice localDevice = HdmiCecLocalDevice.create(this, type); localDevice.init(); @@ -171,8 +177,7 @@ public final class HdmiControlService extends SystemService { } finished.append(deviceType, logicalAddress); - // Once finish address allocation for all devices, notify - // it to each device. + // Address allocation completed for all devices. Notify each device. if (deviceTypes.size() == finished.size()) { notifyAddressAllocated(devices); } @@ -185,7 +190,7 @@ public final class HdmiControlService extends SystemService { for (int i = 0; i < devices.size(); ++i) { int address = devices.keyAt(i); HdmiCecLocalDevice device = devices.valueAt(i); - device.onAddressAllocated(address); + device.handleAddressAllocated(address); } } @@ -663,15 +668,28 @@ public final class HdmiControlService extends SystemService { } private void addDeviceEventListener(IHdmiDeviceEventListener listener) { + DeviceEventListenerRecord record = new DeviceEventListenerRecord(listener); + try { + listener.asBinder().linkToDeath(record, 0); + } catch (RemoteException e) { + Slog.w(TAG, "Listener already died"); + return; + } synchronized (mLock) { - for (DeviceEventListenerRecord record : mDeviceEventListenerRecords) { - if (record.mListener.asBinder() == listener.asBinder()) { - listener.asBinder().unlinkToDeath(record, 0); - mDeviceEventListenerRecords.remove(record); - break; + mDeviceEventListeners.add(listener); + mDeviceEventListenerRecords.add(record); + } + } + + void invokeDeviceEventListeners(HdmiCecDeviceInfo device, boolean activated) { + synchronized (mLock) { + for (IHdmiDeviceEventListener listener : mDeviceEventListeners) { + try { + listener.onStatusChanged(device, activated); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to report device event:" + e); } } - mHotplugEventListeners.remove(listener); } } @@ -683,16 +701,16 @@ public final class HdmiControlService extends SystemService { } } - private void announceHotplugEvent(int portNo, boolean connected) { - HdmiHotplugEvent event = new HdmiHotplugEvent(portNo, connected); + private void announceHotplugEvent(int portId, boolean connected) { + HdmiHotplugEvent event = new HdmiHotplugEvent(portId, connected); synchronized (mLock) { for (IHdmiHotplugEventListener listener : mHotplugEventListeners) { - invokeHotplugEventListener(listener, event); + invokeHotplugEventListenerLocked(listener, event); } } } - private void invokeHotplugEventListener(IHdmiHotplugEventListener listener, + private void invokeHotplugEventListenerLocked(IHdmiHotplugEventListener listener, HdmiHotplugEvent event) { try { listener.onReceived(event); diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAction.java index e48b0dc3e862..92418abf6d5f 100644 --- a/services/core/java/com/android/server/hdmi/SystemAudioAction.java +++ b/services/core/java/com/android/server/hdmi/SystemAudioAction.java @@ -28,9 +28,6 @@ abstract class SystemAudioAction extends FeatureAction { // State in which waits for <SetSystemAudioMode>. private static final int STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE = 1; - // State in which waits for <ReportAudioStatus>. - private static final int STATE_WAIT_FOR_REPORT_AUDIO_STATUS = 2; - private static final int MAX_SEND_RETRY_COUNT = 2; private static final int ON_TIMEOUT_MS = 5000; @@ -92,39 +89,6 @@ abstract class SystemAudioAction extends FeatureAction { tv().setSystemAudioMode(mode); } - protected void sendGiveAudioStatus() { - HdmiCecMessage command = HdmiCecMessageBuilder.buildGiveAudioStatus(getSourceAddress(), - mAvrLogicalAddress); - sendCommand(command, new HdmiControlService.SendMessageCallback() { - @Override - public void onSendCompleted(int error) { - if (error == HdmiConstants.SEND_RESULT_SUCCESS) { - mState = STATE_WAIT_FOR_REPORT_AUDIO_STATUS; - addTimer(mState, TIMEOUT_MS); - } else { - handleSendGiveAudioStatusFailure(); - } - } - }); - } - - private void handleSendGiveAudioStatusFailure() { - // TODO: Notify the failure status. - - int uiCommand = tv().getSystemAudioMode() - ? HdmiConstants.UI_COMMAND_RESTORE_VOLUME_FUNCTION // SystemAudioMode: ON - : HdmiConstants.UI_COMMAND_MUTE_FUNCTION; // SystemAudioMode: OFF - sendUserControlPressedAndReleased(uiCommand); - finish(); - } - - private void sendUserControlPressedAndReleased(int uiCommand) { - sendCommand(HdmiCecMessageBuilder.buildUserControlPressed( - getSourceAddress(), mAvrLogicalAddress, uiCommand)); - sendCommand(HdmiCecMessageBuilder.buildUserControlReleased( - getSourceAddress(), mAvrLogicalAddress)); - } - @Override final boolean processCommand(HdmiCecMessage cmd) { switch (mState) { @@ -137,7 +101,8 @@ abstract class SystemAudioAction extends FeatureAction { boolean receivedStatus = HdmiUtils.parseCommandParamSystemAudioStatus(cmd); if (receivedStatus == mTargetAudioStatus) { setSystemAudioMode(receivedStatus); - sendGiveAudioStatus(); + startAudioStatusAction(); + return true; } else { // Unexpected response, consider the request is newly initiated by AVR. // To return 'false' will initiate new SystemAudioActionFromAvr by the control @@ -145,28 +110,14 @@ abstract class SystemAudioAction extends FeatureAction { finish(); return false; } - return true; - - case STATE_WAIT_FOR_REPORT_AUDIO_STATUS: - // TODO: Handle <FeatureAbort> of <GiveAudioStatus> - if (cmd.getOpcode() != HdmiCec.MESSAGE_REPORT_AUDIO_STATUS - || !HdmiUtils.checkCommandSource(cmd, mAvrLogicalAddress, TAG)) { - return false; - } - byte[] params = cmd.getParams(); - if (params.length > 0) { - boolean mute = (params[0] & 0x80) == 0x80; - int volume = params[0] & 0x7F; - tv().setAudioStatus(mute, volume); - if (mTargetAudioStatus && mute || !mTargetAudioStatus && !mute) { - // Toggle AVR's mute status to match with the system audio status. - sendUserControlPressedAndReleased(HdmiConstants.UI_COMMAND_MUTE); - } - } - finish(); - return true; + default: + return false; } - return false; + } + + protected void startAudioStatusAction() { + addAndStartAction(new SystemAudioStatusAction(tv(), mAvrLogicalAddress)); + finish(); } protected void removeSystemAudioActionInProgress() { @@ -183,9 +134,6 @@ abstract class SystemAudioAction extends FeatureAction { case STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE: handleSendSystemAudioModeRequestTimeout(); return; - case STATE_WAIT_FOR_REPORT_AUDIO_STATUS: - handleSendGiveAudioStatusFailure(); - return; } } } diff --git a/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java b/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java index 3907b714b4da..b743c64571b9 100644 --- a/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java +++ b/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java @@ -59,7 +59,7 @@ final class SystemAudioActionFromAvr extends SystemAudioAction { // TODO: Stop the action for System Audio Mode initialization if it is running. if (mTargetAudioStatus) { setSystemAudioMode(true); - sendGiveAudioStatus(); + startAudioStatusAction(); } else { setSystemAudioMode(false); finish(); diff --git a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java index 75e4fefb1f17..5f4fc23dfe03 100644 --- a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java +++ b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java @@ -25,7 +25,6 @@ import com.android.server.hdmi.HdmiControlService.SendMessageCallback; /** * Action to update audio status (volume or mute) of audio amplifier */ -// TODO: refactor SystemAudioMode so that it uses this class instead of internal state. final class SystemAudioStatusAction extends FeatureAction { private static final String TAG = "SystemAudioStatusAction"; diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index 9ae8aed08784..9d614939df68 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -38,6 +38,7 @@ import android.media.AudioManager; import android.media.MediaMetadata; import android.media.Rating; import android.os.Bundle; +import android.os.DeadObjectException; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -63,6 +64,7 @@ import java.util.UUID; */ public class MediaSessionRecord implements IBinder.DeathRecipient { private static final String TAG = "MediaSessionRecord"; + private static final boolean DEBUG = false; /** * These are the playback states that count as currently active. @@ -506,9 +508,12 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { ISessionControllerCallback cb = mControllerCallbacks.get(i); try { cb.onPlaybackStateChanged(mPlaybackState); - } catch (RemoteException e) { - Log.w(TAG, "Removing dead callback in pushPlaybackStateUpdate.", e); + } catch (DeadObjectException e) { mControllerCallbacks.remove(i); + Log.w(TAG, "Removed dead callback in pushPlaybackStateUpdate. size=" + + mControllerCallbacks.size() + " cb=" + cb, e); + } catch (RemoteException e) { + Log.w(TAG, "unexpected exception in pushPlaybackStateUpdate.", e); } } } @@ -523,9 +528,11 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { ISessionControllerCallback cb = mControllerCallbacks.get(i); try { cb.onMetadataChanged(mMetadata); - } catch (RemoteException e) { - Log.w(TAG, "Removing dead callback in pushMetadataUpdate.", e); + } catch (DeadObjectException e) { + Log.w(TAG, "Removing dead callback in pushMetadataUpdate. " + cb, e); mControllerCallbacks.remove(i); + } catch (RemoteException e) { + Log.w(TAG, "unexpected exception in pushMetadataUpdate. " + cb, e); } } } @@ -540,9 +547,11 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { ISessionControllerCallback cb = mControllerCallbacks.get(i); try { cb.onRouteChanged(mRoute); - } catch (RemoteException e) { + } catch (DeadObjectException e) { Log.w(TAG, "Removing dead callback in pushRouteUpdate.", e); mControllerCallbacks.remove(i); + } catch (RemoteException e) { + Log.w(TAG, "unexpected exception in pushRouteUpdate.", e); } } } @@ -557,8 +566,11 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { ISessionControllerCallback cb = mControllerCallbacks.get(i); try { cb.onEvent(event, data); + } catch (DeadObjectException e) { + Log.w(TAG, "Removing dead callback in pushEvent.", e); + mControllerCallbacks.remove(i); } catch (RemoteException e) { - Log.w(TAG, "Error with callback in pushEvent.", e); + Log.w(TAG, "unexpected exception in pushEvent.", e); } } } @@ -611,6 +623,16 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { return result == null ? state : result; } + private int getControllerCbIndexForCb(ISessionControllerCallback cb) { + IBinder binder = cb.asBinder(); + for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) { + if (binder.equals(mControllerCallbacks.get(i).asBinder())) { + return i; + } + } + return -1; + } + private final RouteConnectionRecord.Listener mConnectionListener = new RouteConnectionRecord.Listener() { @Override @@ -929,8 +951,11 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { @Override public void registerCallbackListener(ISessionControllerCallback cb) { synchronized (mLock) { - if (!mControllerCallbacks.contains(cb)) { + if (getControllerCbIndexForCb(cb) < 0) { mControllerCallbacks.add(cb); + if (DEBUG) { + Log.d(TAG, "registering controller callback " + cb); + } } } } @@ -939,7 +964,13 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { public void unregisterCallbackListener(ISessionControllerCallback cb) throws RemoteException { synchronized (mLock) { - mControllerCallbacks.remove(cb); + int index = getControllerCbIndexForCb(cb); + if (index != -1) { + mControllerCallbacks.remove(index); + } + if (DEBUG) { + Log.d(TAG, "unregistering callback " + cb + ". index=" + index); + } } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index a7fc7eb1125e..90e263a5d911 100755 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -4229,6 +4229,7 @@ public class PackageManagerService extends IPackageManager.Stub { try { pp.collectCertificates(pkg, parseFlags); + pp.collectManifestDigest(pkg); } catch (PackageParserException e) { mLastScanError = e.error; return false; @@ -10272,6 +10273,7 @@ public class PackageManagerService extends IPackageManager.Stub { try { pp.collectCertificates(pkg, parseFlags); + pp.collectManifestDigest(pkg); } catch (PackageParserException e) { res.returnCode = e.error; return; diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index cbbcc58854b0..99b5b03d5256 100644 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -631,7 +631,9 @@ public final class TvInputManagerService extends SystemService { } finally { Binder.restoreCallingIdentity(identity); } - return false; + // STOPSHIP: Redesign the API around the availability change. For now, the service + // will be always available. + return true; } @Override diff --git a/telecomm/java/android/telecomm/PhoneApplication.java b/telecomm/java/android/telecomm/PhoneApplication.java deleted file mode 100644 index 1da54e0d5bbe..000000000000 --- a/telecomm/java/android/telecomm/PhoneApplication.java +++ /dev/null @@ -1,183 +0,0 @@ -package android.telecomm; - -import android.annotation.SystemApi; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.provider.Settings; -import android.text.TextUtils; -import android.util.Log; - -import com.android.internal.telecomm.ITelecommService; - -import java.util.ArrayList; -import java.util.List; - -/** - * Class for managing the primary phone application that will receive incoming calls, and be allowed - * to make emergency outgoing calls. - * - * @hide - */ -public class PhoneApplication { - private static final String TAG = PhoneApplication.class.getSimpleName(); - private static final String TELECOMM_SERVICE_NAME = "telecomm"; - - /** - * Sets the specified package name as the default phone application. The caller of this method - * needs to have permission to write to secure settings. - * - * @hide - * */ - @SystemApi - public static void setDefaultPhoneApplication(String packageName, Context context) { - // Get old package name - String oldPackageName = Settings.Secure.getString(context.getContentResolver(), - Settings.Secure.PHONE_DEFAULT_APPLICATION); - - if (packageName != null && oldPackageName != null && packageName.equals(oldPackageName)) { - // No change - return; - } - - // Only make the change if the new package belongs to a valid phone application - List<ComponentName> componentNames = getInstalledPhoneApplications(context); - ComponentName foundComponent = null; - for (ComponentName componentName : componentNames) { - if (TextUtils.equals(componentName.getPackageName(), packageName)) { - foundComponent = componentName; - break; - } - } - - if (foundComponent != null) { - // Update the secure setting. - Settings.Secure.putString(context.getContentResolver(), - Settings.Secure.PHONE_DEFAULT_APPLICATION, foundComponent.getPackageName()); - } - } - - /** - * Returns the installed phone application that will be used to receive incoming calls, and is - * allowed to make emergency calls. - * - * The application will be returned in order of preference: - * 1) User selected phone application (if still installed) - * 2) Pre-installed system dialer (if not disabled) - * 3) Null - * - * @hide - * */ - @SystemApi - public static ComponentName getDefaultPhoneApplication(Context context) { - String defaultPackageName = Settings.Secure.getString(context.getContentResolver(), - Settings.Secure.PHONE_DEFAULT_APPLICATION); - - final List<ComponentName> componentNames = getInstalledPhoneApplications(context); - if (!TextUtils.isEmpty(defaultPackageName)) { - for (ComponentName componentName : componentNames) { - if (TextUtils.equals(componentName.getPackageName(), defaultPackageName)) { - return componentName; - } - } - } - - // No user-set dialer found, fallback to system dialer - ComponentName systemDialer = null; - try { - systemDialer = getTelecommService().getSystemPhoneApplication(); - } catch (RemoteException e) { - Log.e(TAG, "Error calling ITelecommService#getSystemPhoneApplication", e); - return null; - } - - if (systemDialer == null) { - // No system dialer configured at build time - return null; - } - - // Verify that the system dialer has not been disabled. - return getComponentName(componentNames, systemDialer.getPackageName()); - } - - /** - * Returns a list of installed and available phone applications. - * - * In order to appear in the list, a phone application must implement an intent-filter with - * the DIAL intent for the following schemes: - * - * 1) Empty scheme - * 2) tel Uri scheme - * - * @hide - **/ - @SystemApi - public static List<ComponentName> getInstalledPhoneApplications(Context context) { - PackageManager packageManager = context.getPackageManager(); - - // Get the list of apps registered for the DIAL intent with empty scheme - Intent intent = new Intent(Intent.ACTION_DIAL); - List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(intent, 0); - - List<ComponentName> componentNames = new ArrayList<ComponentName> (); - - for (ResolveInfo resolveInfo : resolveInfoList) { - final ActivityInfo activityInfo = resolveInfo.activityInfo; - if (activityInfo == null) { - continue; - } - final ComponentName componentName = - new ComponentName(activityInfo.packageName, activityInfo.name); - componentNames.add(componentName); - } - - // TODO: Filter for apps that don't handle DIAL intent with tel scheme - return componentNames; - } - - /** - * Returns the {@link ComponentName} for the installed phone application for a given package - * name. - * - * @param context A valid context. - * @param packageName to retrieve the {@link ComponentName} for. - * - * @return The {@link ComponentName} for the installed phone application corresponding to the - * package name, or null if none is found. - * - * @hide - */ - @SystemApi - public static ComponentName getPhoneApplicationForPackageName(Context context, - String packageName) { - return getComponentName(getInstalledPhoneApplications(context), packageName); - } - - /** - * Returns the component from a list of application components that corresponds to the package - * name. - * - * @param componentNames A list of component names - * @param packageName The package name to look for - * @return The {@link ComponentName} that matches the provided packageName, or null if not - * found. - */ - private static ComponentName getComponentName(List<ComponentName> componentNames, - String packageName) { - for (ComponentName componentName : componentNames) { - if (TextUtils.equals(packageName, componentName.getPackageName())) { - return componentName; - } - } - return null; - } - - private static ITelecommService getTelecommService() { - return ITelecommService.Stub.asInterface(ServiceManager.getService(TELECOMM_SERVICE_NAME)); - } -} diff --git a/telecomm/java/android/telecomm/TelecommConstants.java b/telecomm/java/android/telecomm/TelecommConstants.java index 09520979050b..0a12c08cbaba 100644 --- a/telecomm/java/android/telecomm/TelecommConstants.java +++ b/telecomm/java/android/telecomm/TelecommConstants.java @@ -56,21 +56,6 @@ public final class TelecommConstants { public static final String ACTION_CALL_SERVICE_SELECTOR = CallServiceSelector.class.getName(); /** - * Activity action: Ask the user to change the default phone application. This will show a - * dialog that asks the user whether they want to replace the current default phone application - * with the one defined in {@link #EXTRA_PACKAGE_NAME}. - */ - public static final String ACTION_CHANGE_DEFAULT_PHONE = - "android.telecomm.ACTION_CHANGE_DEFAULT_PHONE"; - - /** - * The PackageName string passed in as an extra for {@link #ACTION_CHANGE_DEFAULT_PHONE}. - * - * @see #ACTION_CHANGE_DEFAULT_PHONE - */ - public static final String EXTRA_PACKAGE_NAME = "package"; - - /** * Optional extra for {@link Intent#ACTION_CALL} containing a boolean that determines whether * the speakerphone should be automatically turned on for an outgoing call. */ diff --git a/telecomm/java/android/telecomm/TelecommManager.java b/telecomm/java/android/telecomm/TelecommManager.java index 989c2cd0b19e..a97e7e499f5f 100644 --- a/telecomm/java/android/telecomm/TelecommManager.java +++ b/telecomm/java/android/telecomm/TelecommManager.java @@ -16,9 +16,7 @@ package android.telecomm; -import android.content.ComponentName; import android.content.Context; -import android.os.RemoteException; import com.android.internal.telecomm.ITelecommService; @@ -47,14 +45,4 @@ public class TelecommManager { public static TelecommManager from(Context context) { return (TelecommManager) context.getSystemService(Context.TELECOMM_SERVICE); } - - /** {@hide} */ - public ComponentName getSystemPhoneApplication() { - try { - return mService.getSystemPhoneApplication(); - } catch (RemoteException e) { - Log.e(TAG, e, "Error calling ITelecommService#getSystemPhoneApplication"); - return null; - } - } } diff --git a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl index dc2b8694c66e..c758c6d36b9e 100644 --- a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl +++ b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl @@ -17,7 +17,6 @@ package com.android.internal.telecomm; import android.telecomm.Subscription; -import android.content.ComponentName; /** * Interface used to interact with Telecomm. Mostly this is used by TelephonyManager for passing @@ -43,11 +42,6 @@ interface ITelecommService { void showCallScreen(boolean showDialpad); /** - * Returns the component name of the phone application installed on the system partition. - */ - ComponentName getSystemPhoneApplication(); - - /** * Gets a list of Subscriptions. */ List<Subscription> getSubscriptions(); diff --git a/tests/VectorDrawableTest/res/anim/trim_path_animation03.xml b/tests/VectorDrawableTest/res/anim/trim_path_animation03.xml index 72beba2f7b15..0c1073e5b2cd 100644 --- a/tests/VectorDrawableTest/res/anim/trim_path_animation03.xml +++ b/tests/VectorDrawableTest/res/anim/trim_path_animation03.xml @@ -21,6 +21,8 @@ android:duration="6000" android:propertyName="rotation" android:valueFrom="0" - android:valueTo="360"/> + android:valueTo="360" + android:interpolator="@interpolator/custom_path_interpolator" + /> </set>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/anim/trim_path_animation04.xml b/tests/VectorDrawableTest/res/anim/trim_path_animation04.xml index ff866682f348..4d0aae1c9314 100644 --- a/tests/VectorDrawableTest/res/anim/trim_path_animation04.xml +++ b/tests/VectorDrawableTest/res/anim/trim_path_animation04.xml @@ -16,11 +16,9 @@ --> <set xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator android:duration="9000" - android:propertyName="rotation" - android:valueFrom="0" - android:valueTo="360"/> - + android:propertyXName="translateX" + android:propertyYName="translateY" + android:pathData="m0,0 q 150, 300 150, 0 t 150, 0, t 150, 0 t -150 0 t -150 0 t -150 0 z" /> </set>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/drawable/animation_vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/animation_vector_drawable01.xml index b8681b6556ef..0900b7c24af7 100644 --- a/tests/VectorDrawableTest/res/drawable/animation_vector_drawable01.xml +++ b/tests/VectorDrawableTest/res/drawable/animation_vector_drawable01.xml @@ -32,5 +32,8 @@ <target android:name="rotationGroupBlue" android:animation="@anim/trim_path_animation03" /> + <target + android:name="rotationGroup" + android:animation="@anim/trim_path_animation04" /> </animated-vector>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator.xml b/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator.xml new file mode 100644 index 000000000000..0cffa0a9009b --- /dev/null +++ b/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator.xml @@ -0,0 +1,2 @@ +<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/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 00e1cd8ea6d1..e83eed7283fc 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -132,5 +132,13 @@ interface IWifiManager void enableVerboseLogging(int verbose); int getVerboseLoggingLevel(); + + int getAggressiveHandover(); + + void enableAggressiveHandover(int enabled); + + int getAllowScansWithTraffic(); + + void setAllowScansWithTraffic(int enabled); } diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index b64ad601ff19..59b48e4b8b12 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -373,19 +373,19 @@ public class WifiConfiguration implements Parcelable { public static int GOOD_RSSI_24 = -65; /** @hide **/ - public static int LOW_RSSI_24 = -75; + public static int LOW_RSSI_24 = -77; /** @hide **/ - public static int BAD_RSSI_24 = -85; + public static int BAD_RSSI_24 = -87; /** @hide **/ - public static int GOOD_RSSI_5 = -55; + public static int GOOD_RSSI_5 = -60; /** @hide **/ - public static int LOW_RSSI_5 = -65; + public static int LOW_RSSI_5 = -72; /** @hide **/ - public static int BAD_RSSI_5 = -75; + public static int BAD_RSSI_5 = -82; /** @hide **/ public static int UNWANTED_BLACKLIST_SOFT_BUMP = 4; @@ -394,7 +394,7 @@ public class WifiConfiguration implements Parcelable { public static int UNWANTED_BLACKLIST_HARD_BUMP = 8; /** @hide **/ - public static int UNBLACKLIST_THRESHOLD_24_SOFT = -75; + public static int UNBLACKLIST_THRESHOLD_24_SOFT = -77; /** @hide **/ public static int UNBLACKLIST_THRESHOLD_24_HARD = -68; @@ -415,6 +415,19 @@ public class WifiConfiguration implements Parcelable { * 5GHz band is prefered over 2.4 if the 5GHz RSSI is higher than this threshold **/ public static int A_BAND_PREFERENCE_RSSI_THRESHOLD = -65; + /** @hide + * 5GHz band is penalized if the 5GHz RSSI is lower than this threshold **/ + public static int G_BAND_PREFERENCE_RSSI_THRESHOLD = -75; + + /** @hide + * Boost given to RSSI on a home network for the purpose of calculating the score + * This adds stickiness to home networks, as defined by: + * - less than 4 known BSSIDs + * - PSK only + * - TODO: add a test to verify that all BSSIDs are behind same gateway + ***/ + public static int HOME_NETWORK_RSSI_BOOST = 5; + /** * @hide * A summary of the RSSI and Band status for that configuration diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java index 54a7df2a62cc..e46f9169f886 100644 --- a/wifi/java/android/net/wifi/WifiInfo.java +++ b/wifi/java/android/net/wifi/WifiInfo.java @@ -134,6 +134,11 @@ public class WifiInfo implements Parcelable { /** * @hide */ + public int linkStuckCount; + + /** + * @hide + */ public int lowRssiCount; /** @@ -237,6 +242,7 @@ public class WifiInfo implements Parcelable { txRetriesRate = 0; lowRssiCount = 0; badRssiCount = 0; + linkStuckCount = 0; score = 0; } @@ -267,6 +273,7 @@ public class WifiInfo implements Parcelable { score = source.score; badRssiCount = source.badRssiCount; lowRssiCount = source.lowRssiCount; + linkStuckCount = source.linkStuckCount; } } diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 141a69eb48eb..a30fb797ff40 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -2226,7 +2226,6 @@ public class WifiManager { } } - /** * Set wifi verbose log. Called from developer settings. * @hide @@ -2251,4 +2250,53 @@ public class WifiManager { return 0; } } + + /** + * Set wifi Aggressive Handover. Called from developer settings. + * @hide + */ + public void enableAggressiveHandover(int enabled) { + try { + mService.enableAggressiveHandover(enabled); + } catch (RemoteException e) { + + } + } + + /** + * Get the WiFi Handover aggressiveness.This is used by settings + * to decide what to show within the picker. + * @hide + */ + public int getAggressiveHandover() { + try { + return mService.getAggressiveHandover(); + } catch (RemoteException e) { + return 0; + } + } + + /** + * Set setting for allowing Scans when traffic is ongoing. + * @hide + */ + public void setAllowScansWithTraffic(int enabled) { + try { + mService.setAllowScansWithTraffic(enabled); + } catch (RemoteException e) { + + } + } + + /** + * Get setting for allowing Scans when traffic is ongoing. + * @hide + */ + public int getAllowScansWithTraffic() { + try { + return mService.getAllowScansWithTraffic(); + } catch (RemoteException e) { + return 0; + } + } } |