diff options
225 files changed, 3860 insertions, 2358 deletions
diff --git a/Android.mk b/Android.mk index 216d8a2d45f6..56e9df649f7b 100644 --- a/Android.mk +++ b/Android.mk @@ -344,6 +344,7 @@ LOCAL_SRC_FILES += \ telephony/java/com/android/internal/telephony/ISms.aidl \ telephony/java/com/android/internal/telephony/IWapPushManager.aidl \ telephony/java/com/android/internal/telephony/ISub.aidl \ + telephony/java/com/android/internal/telephony/IMms.aidl \ wifi/java/android/net/wifi/IWifiManager.aidl \ wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl \ wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \ @@ -361,7 +362,7 @@ LOCAL_INTERMEDIATE_SOURCES := \ $(framework_res_source_path)/com/android/internal/R.java LOCAL_NO_STANDARD_LIBRARIES := true -LOCAL_JAVA_LIBRARIES := bouncycastle conscrypt core core-junit ext okhttp +LOCAL_JAVA_LIBRARIES := core-libart conscrypt okhttp core-junit bouncycastle ext LOCAL_MODULE := framework-base @@ -589,9 +590,9 @@ framework_docs_LOCAL_INTERMEDIATE_SOURCES := \ $(framework_res_source_path)/com/android/internal/R.java framework_docs_LOCAL_API_CHECK_JAVA_LIBRARIES := \ - bouncycastle \ + core-libart \ conscrypt \ - core \ + bouncycastle \ okhttp \ ext \ framework \ @@ -633,7 +634,7 @@ framework_docs_LOCAL_DROIDDOC_OPTIONS := \ -since $(SRC_API_DIR)/17.txt 17 \ -since $(SRC_API_DIR)/18.txt 18 \ -since $(SRC_API_DIR)/19.txt 19 \ - -werror -hide 113 \ + -werror -hide 111 -hide 113 \ -overview $(LOCAL_PATH)/core/java/overview.html framework_docs_LOCAL_API_CHECK_ADDITIONAL_JAVA_DIR:= \ @@ -902,7 +903,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(ext_src_files) LOCAL_NO_STANDARD_LIBRARIES := true -LOCAL_JAVA_LIBRARIES := core +LOCAL_JAVA_LIBRARIES := core-libart LOCAL_JAVA_RESOURCE_DIRS := $(ext_res_dirs) LOCAL_MODULE_TAGS := optional LOCAL_MODULE := ext diff --git a/api/current.txt b/api/current.txt index 931ab3b94376..3b311e31ca0f 100644 --- a/api/current.txt +++ b/api/current.txt @@ -580,6 +580,7 @@ package android { field public static final int fromXScale = 16843202; // 0x10101c2 field public static final int fromYDelta = 16843208; // 0x10101c8 field public static final int fromYScale = 16843204; // 0x10101c4 + field public static final int fullBackupOnly = 16843893; // 0x1010475 field public static final int fullBright = 16842954; // 0x10100ca field public static final int fullDark = 16842950; // 0x10100c6 field public static final int functionalTest = 16842787; // 0x1010023 @@ -936,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 @@ -5248,7 +5251,10 @@ package android.app.admin { method public int getPasswordQuality(android.content.ComponentName); method public boolean getStorageEncryption(android.content.ComponentName); method public int getStorageEncryptionStatus(); + method public boolean hasAnyCaCertsInstalled(); + method public boolean hasCaCertInstalled(byte[]); method public boolean hasGrantedPolicy(android.content.ComponentName, int); + method public boolean installCaCert(android.content.ComponentName, byte[]); method public boolean isActivePasswordSufficient(); method public boolean isAdminActive(android.content.ComponentName); method public boolean isApplicationBlocked(android.content.ComponentName, java.lang.String); @@ -5286,6 +5292,7 @@ package android.app.admin { method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName); method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String); method public int setStorageEncryption(android.content.ComponentName, boolean); + method public void uninstallCaCert(android.content.ComponentName, byte[]); method public void wipeData(int); field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN"; field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.ACTION_PROVISION_MANAGED_PROFILE"; @@ -8132,6 +8139,7 @@ package android.content.pm { field public static final int FLAG_DEBUGGABLE = 2; // 0x2 field public static final int FLAG_EXTERNAL_STORAGE = 262144; // 0x40000 field public static final int FLAG_FACTORY_TEST = 16; // 0x10 + field public static final int FLAG_FULL_BACKUP_ONLY = 67108864; // 0x4000000 field public static final int FLAG_HAS_CODE = 4; // 0x4 field public static final int FLAG_INSTALLED = 8388608; // 0x800000 field public static final int FLAG_IS_DATA_ONLY = 16777216; // 0x1000000 @@ -12826,6 +12834,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 { @@ -13733,7 +13742,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 @@ -13807,6 +13818,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"; @@ -15851,6 +15863,7 @@ package android.media.tv { } public static final class TvContract.Channels implements android.media.tv.TvContract.BaseTvColumns { + method public static final java.lang.String getVideoResolution(java.lang.String); field public static final java.lang.String COLUMN_BROWSABLE = "browsable"; field public static final java.lang.String COLUMN_DESCRIPTION = "description"; field public static final java.lang.String COLUMN_DISPLAY_NAME = "display_name"; @@ -15864,6 +15877,7 @@ package android.media.tv { field public static final java.lang.String COLUMN_TRANSPORT_STREAM_ID = "transport_stream_id"; field public static final java.lang.String COLUMN_TYPE = "type"; field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number"; + field public static final java.lang.String COLUMN_VIDEO_FORMAT = "video_format"; field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/channel"; field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/channel"; field public static final android.net.Uri CONTENT_URI; @@ -15895,6 +15909,22 @@ package android.media.tv { field public static final int TYPE_SECAM = 3; // 0x3 field public static final int TYPE_S_DMB = 393472; // 0x60100 field public static final int TYPE_T_DMB = 393216; // 0x60000 + field public static final java.lang.String VIDEO_FORMAT_1080I = "VIDEO_FORMAT_1080I"; + field public static final java.lang.String VIDEO_FORMAT_1080P = "VIDEO_FORMAT_1080P"; + field public static final java.lang.String VIDEO_FORMAT_2160P = "VIDEO_FORMAT_2160P"; + field public static final java.lang.String VIDEO_FORMAT_240P = "VIDEO_FORMAT_240P"; + field public static final java.lang.String VIDEO_FORMAT_360P = "VIDEO_FORMAT_360P"; + field public static final java.lang.String VIDEO_FORMAT_4320P = "VIDEO_FORMAT_4320P"; + field public static final java.lang.String VIDEO_FORMAT_480I = "VIDEO_FORMAT_480I"; + field public static final java.lang.String VIDEO_FORMAT_480P = "VIDEO_FORMAT_480P"; + field public static final java.lang.String VIDEO_FORMAT_576I = "VIDEO_FORMAT_576I"; + field public static final java.lang.String VIDEO_FORMAT_576P = "VIDEO_FORMAT_576P"; + field public static final java.lang.String VIDEO_FORMAT_720P = "VIDEO_FORMAT_720P"; + field public static final java.lang.String VIDEO_RESOLUTION_ED = "VIDEO_RESOLUTION_ED"; + field public static final java.lang.String VIDEO_RESOLUTION_FHD = "VIDEO_RESOLUTION_FHD"; + field public static final java.lang.String VIDEO_RESOLUTION_HD = "VIDEO_RESOLUTION_HD"; + field public static final java.lang.String VIDEO_RESOLUTION_SD = "VIDEO_RESOLUTION_SD"; + field public static final java.lang.String VIDEO_RESOLUTION_UHD = "VIDEO_RESOLUTION_UHD"; } public static final class TvContract.Channels.Logo { @@ -15915,6 +15945,8 @@ package android.media.tv { field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri"; field public static final java.lang.String COLUMN_TITLE = "title"; field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number"; + field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height"; + field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width"; field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program"; field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program"; field public static final android.net.Uri CONTENT_URI; @@ -15923,17 +15955,17 @@ package android.media.tv { public static final class TvContract.Programs.Genres { method public static java.lang.String[] decode(java.lang.String); method public static java.lang.String encode(java.lang.String...); - field public static final java.lang.String ANIMAL_WILDLIFE = "Animal/Wildlife"; - field public static final java.lang.String COMEDY = "Comedy"; - field public static final java.lang.String DRAMA = "Drama"; - field public static final java.lang.String EDUCATION = "Education"; - field public static final java.lang.String FAMILY_KIDS = "Family/Kids"; - field public static final java.lang.String GAMING = "Gaming"; - field public static final java.lang.String MOVIES = "Movies"; - field public static final java.lang.String NEWS = "News"; - field public static final java.lang.String SHOPPING = "Shopping"; - field public static final java.lang.String SPORTS = "Sports"; - field public static final java.lang.String TRAVEL = "Travel"; + field public static final java.lang.String ANIMAL_WILDLIFE = "ANIMAL_WILDLIFE"; + field public static final java.lang.String COMEDY = "COMEDY"; + field public static final java.lang.String DRAMA = "DRAMA"; + field public static final java.lang.String EDUCATION = "EDUCATION"; + field public static final java.lang.String FAMILY_KIDS = "FAMILY_KIDS"; + field public static final java.lang.String GAMING = "GAMING"; + field public static final java.lang.String MOVIES = "MOVIES"; + field public static final java.lang.String NEWS = "NEWS"; + field public static final java.lang.String SHOPPING = "SHOPPING"; + field public static final java.lang.String SPORTS = "SPORTS"; + field public static final java.lang.String TRAVEL = "TRAVEL"; } public final class TvInputInfo implements android.os.Parcelable { @@ -21564,6 +21596,7 @@ package android.os { public class UserManager { method public android.os.Bundle getApplicationRestrictions(java.lang.String); method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle); + method public java.lang.String getBadgedLabelForUser(java.lang.String, android.os.UserHandle); method public long getSerialNumberForUser(android.os.UserHandle); method public int getUserCount(); method public android.os.UserHandle getUserForSerialNumber(long); @@ -23428,7 +23461,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"; @@ -31322,6 +31355,7 @@ package android.view { } public final class Display { + method public long getAppVsyncOffsetNanos(); method public void getCurrentSizeRange(android.graphics.Point, android.graphics.Point); method public int getDisplayId(); method public int getFlags(); @@ -31330,6 +31364,7 @@ package android.view { method public java.lang.String getName(); method public deprecated int getOrientation(); method public deprecated int getPixelFormat(); + method public long getPresentationDeadlineNanos(); method public void getRealMetrics(android.util.DisplayMetrics); method public void getRealSize(android.graphics.Point); method public void getRectSize(android.graphics.Rect); @@ -32562,6 +32597,7 @@ package android.view { method public void dispatchWindowSystemUiVisiblityChanged(int); method public void dispatchWindowVisibilityChanged(int); method public void draw(android.graphics.Canvas); + method public void drawableHotspotChanged(float, float); method protected void drawableStateChanged(); method public android.view.View findFocus(); method public final android.view.View findViewById(int); 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/Activity.java b/core/java/android/app/Activity.java index 90615d3649f1..91328832794e 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -5323,13 +5323,15 @@ public class Activity extends ContextThemeWrapper * drawn and it is safe to make this Activity translucent again. * @param options activity options delivered to the activity below this one. The options * are retrieved using {@link #getActivityOptions}. + * @return <code>true</code> if Window was opaque and will become translucent or + * <code>false</code> if window was translucent and no change needed to be made. * * @see #convertFromTranslucent() * @see TranslucentConversionListener * * @hide */ - public void convertToTranslucent(TranslucentConversionListener callback, + public boolean convertToTranslucent(TranslucentConversionListener callback, ActivityOptions options) { boolean drawComplete; try { @@ -5346,6 +5348,7 @@ public class Activity extends ContextThemeWrapper // Window is already translucent. mTranslucentCallback.onTranslucentConversionComplete(drawComplete); } + return mChangeCanvasToTranslucent; } /** @hide */ diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index de0396e478d7..5e17e1a1204c 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -1457,10 +1457,10 @@ final class ApplicationPackageManager extends PackageManager { * @hide */ @Override - public void addCrossProfileIntentFilter(IntentFilter filter, boolean removable, - int sourceUserId, int targetUserId) { + public void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId, int targetUserId, + int flags) { try { - mPM.addCrossProfileIntentFilter(filter, removable, sourceUserId, targetUserId); + mPM.addCrossProfileIntentFilter(filter, sourceUserId, targetUserId, flags); } catch (RemoteException e) { // Should never happen! } @@ -1470,15 +1470,6 @@ final class ApplicationPackageManager extends PackageManager { * @hide */ @Override - public void addForwardingIntentFilter(IntentFilter filter, boolean removable, int sourceUserId, - int targetUserId) { - addCrossProfileIntentFilter(filter, removable, sourceUserId, targetUserId); - } - - /** - * @hide - */ - @Override public void clearCrossProfileIntentFilters(int sourceUserId) { try { mPM.clearCrossProfileIntentFilters(sourceUserId); @@ -1487,14 +1478,6 @@ final class ApplicationPackageManager extends PackageManager { } } - /** - * @hide - */ - @Override - public void clearForwardingIntentFilters(int sourceUserId) { - clearCrossProfileIntentFilters(sourceUserId); - } - private final ContextImpl mContext; private final IPackageManager mPM; 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/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java index 365cc8e8e0cd..1d7a0ec8c98b 100644 --- a/core/java/android/app/EnterTransitionCoordinator.java +++ b/core/java/android/app/EnterTransitionCoordinator.java @@ -55,6 +55,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { private boolean mIsExitTransitionComplete; private boolean mIsReadyForTransition; private Bundle mSharedElementsBundle; + private boolean mWasOpaque; public EnterTransitionCoordinator(Activity activity, ResultReceiver resultReceiver, ArrayList<String> sharedElementNames, boolean isReturning) { @@ -191,7 +192,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { protected void prepareEnter() { mActivity.overridePendingTransition(0, 0); if (!mIsReturning) { - mActivity.convertToTranslucent(null, null); + mWasOpaque = mActivity.convertToTranslucent(null, null); Drawable background = getDecor().getBackground(); if (background != null) { getWindow().setBackgroundDrawable(null); @@ -376,7 +377,9 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { private void makeOpaque() { if (!mHasStopped && mActivity != null) { - mActivity.convertFromTranslucent(); + if (mWasOpaque) { + mActivity.convertFromTranslucent(); + } mActivity = null; } } diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java index 0d514a5bdc3a..ca4043677a70 100644 --- a/core/java/android/app/admin/DeviceAdminReceiver.java +++ b/core/java/android/app/admin/DeviceAdminReceiver.java @@ -376,7 +376,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { /** * Called when a device is entering or exiting lock task mode by a package - * authorized by {@link DevicePolicyManager#isLockTaskPermitted(ComponentName)} + * authorized by {@link DevicePolicyManager#isLockTaskPermitted(String)} * * @param context The running context as per {@link #onReceive}. * @param intent The received intent as per {@link #onReceive}. diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index af653a380025..df6be8b18785 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1507,12 +1507,11 @@ public class DevicePolicyManager { * * @return false if the certBuffer cannot be parsed or installation is * interrupted, otherwise true - * @hide */ - public boolean installCaCert(byte[] certBuffer) { + public boolean installCaCert(ComponentName who, byte[] certBuffer) { if (mService != null) { try { - return mService.installCaCert(certBuffer); + return mService.installCaCert(who, certBuffer); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1522,13 +1521,14 @@ public class DevicePolicyManager { /** * Uninstalls the given certificate from the list of User CAs, if present. - * - * @hide */ - public void uninstallCaCert(byte[] certBuffer) { + public void uninstallCaCert(ComponentName who, byte[] certBuffer) { if (mService != null) { try { - mService.uninstallCaCert(certBuffer); + final String alias = getCaCertAlias(certBuffer); + mService.uninstallCaCert(who, alias); + } catch (CertificateException e) { + Log.w(TAG, "Unable to parse certificate", e); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1537,10 +1537,8 @@ public class DevicePolicyManager { /** * Returns whether there are any user-installed CA certificates. - * - * @hide */ - public static boolean hasAnyCaCertsInstalled() { + public boolean hasAnyCaCertsInstalled() { TrustedCertificateStore certStore = new TrustedCertificateStore(); Set<String> aliases = certStore.userAliases(); return aliases != null && !aliases.isEmpty(); @@ -1548,18 +1546,10 @@ public class DevicePolicyManager { /** * Returns whether this certificate has been installed as a User CA. - * - * @hide */ public boolean hasCaCertInstalled(byte[] certBuffer) { - TrustedCertificateStore certStore = new TrustedCertificateStore(); - String alias; - byte[] pemCert; try { - CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); - X509Certificate cert = (X509Certificate) certFactory.generateCertificate( - new ByteArrayInputStream(certBuffer)); - return certStore.getCertificateAlias(cert) != null; + return getCaCertAlias(certBuffer) != null; } catch (CertificateException ce) { Log.w(TAG, "Could not parse certificate", ce); } @@ -1567,6 +1557,17 @@ public class DevicePolicyManager { } /** + * Returns the alias of a given CA certificate in the certificate store, or null if it + * doesn't exist. + */ + private static String getCaCertAlias(byte[] certBuffer) throws CertificateException { + final CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + final X509Certificate cert = (X509Certificate) certFactory.generateCertificate( + new ByteArrayInputStream(certBuffer)); + return new TrustedCertificateStore().getCertificateAlias(cert); + } + + /** * Called by an application that is administering the device to disable all cameras * on the device. After setting this, no applications will be able to access any cameras * on the device. diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index e7b77d82da30..5333ea6285cb 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -115,8 +115,8 @@ interface IDevicePolicyManager { String getProfileOwnerName(int userHandle); void setProfileEnabled(in ComponentName who); - boolean installCaCert(in byte[] certBuffer); - void uninstallCaCert(in byte[] certBuffer); + boolean installCaCert(in ComponentName admin, in byte[] certBuffer); + void uninstallCaCert(in ComponentName admin, in String alias); void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity); void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName); diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 06f4019df06d..be4e86441755 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -325,6 +325,15 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public static final int FLAG_IS_GAME = 1<<25; /** + * Value for {@link #flags}: {@code true} if the application asks that only + * full-data streaming backups of its data be performed even though it defines + * a {@link android.app.backup.BackupAgent BackupAgent}, which normally + * indicates that the app will manage its backed-up data via incremental + * key/value updates. + */ + public static final int FLAG_FULL_BACKUP_ONLY = 1<<26; + + /** * Value for {@link #flags}: set to {@code true} if the application * is permitted to hold privileged permissions. * diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 70668e11d5d6..00e7918d8f48 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -248,8 +248,8 @@ interface IPackageManager { void clearPackagePersistentPreferredActivities(String packageName, int userId); - void addCrossProfileIntentFilter(in IntentFilter filter, boolean removable, int sourceUserId, - int targetUserId); + void addCrossProfileIntentFilter(in IntentFilter intentFilter, int sourceUserId, int targetUserId, + int flags); void clearCrossProfileIntentFilters(int sourceUserId); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 8d9b8d9e0ade..9d871c544a0f 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -196,6 +196,22 @@ public abstract class PackageManager { */ public static final int MATCH_DEFAULT_ONLY = 0x00010000; + /** + * Flag for {@link addCrossProfileIntentFilter}: if the cross-profile intent has been set by the + * profile owner. + * @hide + */ + public static final int SET_BY_PROFILE_OWNER= 0x00000001; + + /** + * Flag for {@link addCrossProfileIntentFilter}: if this flag is set: + * when resolving an intent that matches the {@link CrossProfileIntentFilter}, the current + * profile will be skipped. + * Only activities in the target user can respond to the intent. + * @hide + */ + public static final int SKIP_CURRENT_PROFILE = 0x00000002; + /** @hide */ @IntDef({PERMISSION_GRANTED, PERMISSION_DENIED}) @Retention(RetentionPolicy.SOURCE) @@ -2870,15 +2886,13 @@ public abstract class PackageManager { * */ public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags) { - PackageParser packageParser = new PackageParser(archiveFilePath); - DisplayMetrics metrics = new DisplayMetrics(); - metrics.setToDefaults(); - final File sourceFile = new File(archiveFilePath); + final PackageParser parser = new PackageParser(); + final File apkFile = new File(archiveFilePath); try { - PackageParser.Package pkg = packageParser.parseMonolithicPackage(sourceFile, metrics, - 0); + PackageParser.Package pkg = parser.parseMonolithicPackage(apkFile, 0); if ((flags & GET_SIGNATURES) != 0) { - packageParser.collectCertificates(pkg, 0); + parser.collectCertificates(pkg, 0); + parser.collectManifestDigest(pkg); } PackageUserState state = new PackageUserState(); return PackageParser.generatePackageInfo(pkg, null, flags, 0, 0, null, state); @@ -3586,30 +3600,14 @@ public abstract class PackageManager { * {@link CrossProfileIntentFilter} * @hide */ - public abstract void addCrossProfileIntentFilter(IntentFilter filter, boolean removable, - int sourceUserId, int targetUserId); + public abstract void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId, + int targetUserId, int flags); /** - * @hide - * @deprecated - * TODO: remove it as soon as the code of ManagedProvisionning is updated - */ - public abstract void addForwardingIntentFilter(IntentFilter filter, boolean removable, - int sourceUserId, int targetUserId); - - /** - * Clearing removable {@link CrossProfileIntentFilter}s which have the specified user as their - * source + * Clearing {@link CrossProfileIntentFilter}s which have the specified user as their + * source, and have been set by the profile owner * @param sourceUserId - * be cleared. * @hide */ public abstract void clearCrossProfileIntentFilters(int sourceUserId); - - /** - * @hide - * @deprecated - * TODO: remove it as soon as the code of ManagedProvisionning is updated - */ - public abstract void clearForwardingIntentFilters(int sourceUserId); } diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 618c2bd646ff..0b336d011692 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -16,9 +16,14 @@ package android.content.pm; +import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME; +import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING; +import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK; +import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES; +import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION; import android.content.ComponentName; import android.content.Intent; @@ -33,6 +38,8 @@ import android.os.Bundle; import android.os.PatternMatcher; import android.os.UserHandle; import android.text.TextUtils; +import android.util.ArrayMap; +import android.util.ArraySet; import android.util.AttributeSet; import android.util.Base64; import android.util.DisplayMetrics; @@ -41,12 +48,18 @@ import android.util.Pair; import android.util.Slog; import android.util.TypedValue; -import java.io.BufferedInputStream; +import com.android.internal.util.ArrayUtils; +import com.android.internal.util.XmlUtils; + +import libcore.io.IoUtils; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; -import java.lang.ref.WeakReference; import java.security.GeneralSecurityException; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; @@ -58,21 +71,19 @@ import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; import java.util.jar.StrictJarFile; import java.util.zip.ZipEntry; -import com.android.internal.util.ArrayUtils; -import com.android.internal.util.XmlUtils; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - /** * Package archive parsing * @@ -153,17 +164,21 @@ public class PackageParser { android.os.Build.VERSION_CODES.JELLY_BEAN) }; + /** + * @deprecated callers should move to explicitly passing around source path. + */ + @Deprecated private String mArchiveSourcePath; + private String[] mSeparateProcesses; private boolean mOnlyCoreApps; + private DisplayMetrics mMetrics; + private static final int SDK_VERSION = Build.VERSION.SDK_INT; private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES; private int mParseError = PackageManager.INSTALL_SUCCEEDED; - private static final Object mSync = new Object(); - private static WeakReference<byte[]> mReadBuffer; - private static boolean sCompatibilityModeEnabled = true; private static final int PARSE_DEFAULT_INSTALL_LOCATION = PackageInfo.INSTALL_LOCATION_UNSPECIFIED; @@ -247,12 +262,9 @@ public class PackageParser { private static final String TAG = "PackageParser"; - public PackageParser(String archiveSourcePath) { - mArchiveSourcePath = archiveSourcePath; - } - - public PackageParser(File archiveSource) { - this(archiveSource.getAbsolutePath()); + public PackageParser() { + mMetrics = new DisplayMetrics(); + mMetrics.setToDefaults(); } public void setSeparateProcesses(String[] procs) { @@ -263,6 +275,10 @@ public class PackageParser { mOnlyCoreApps = onlyCoreApps; } + public void setDisplayMetrics(DisplayMetrics metrics) { + mMetrics = metrics; + } + private static final boolean isPackageFilename(File file) { return isPackageFilename(file.getName()); } @@ -480,23 +496,21 @@ public class PackageParser { return pi; } - private static Certificate[][] loadCertificates(StrictJarFile jarFile, ZipEntry je, - byte[] readBuffer) { + private static Certificate[][] loadCertificates(StrictJarFile jarFile, ZipEntry entry) + throws PackageParserException { + InputStream is = null; try { // We must read the stream for the JarEntry to retrieve // its certificates. - InputStream is = new BufferedInputStream(jarFile.getInputStream(je)); - while (is.read(readBuffer, 0, readBuffer.length) != -1) { - // not using - } - is.close(); - return je != null ? jarFile.getCertificateChains(je) : null; - } catch (IOException e) { - Slog.w(TAG, "Exception reading " + je.getName() + " in " + jarFile, e); - } catch (RuntimeException e) { - Slog.w(TAG, "Exception reading " + je.getName() + " in " + jarFile, e); + is = jarFile.getInputStream(entry); + readFullyIgnoringContents(is); + return jarFile.getCertificateChains(entry); + } catch (IOException | RuntimeException e) { + throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, + "Failed reading " + entry.getName() + " in " + jarFile, e); + } finally { + IoUtils.closeQuietly(is); } - return null; } public final static int PARSE_IS_SYSTEM = 1<<0; @@ -508,67 +522,116 @@ public class PackageParser { public final static int PARSE_IS_SYSTEM_DIR = 1<<6; public final static int PARSE_IS_PRIVILEGED = 1<<7; public final static int PARSE_GET_SIGNATURES = 1<<8; + public final static int PARSE_TRUSTED_OVERLAY = 1<<9; + + private static final Comparator<String> sSplitNameComparator = new SplitNameComparator(); + + /** + * Used to sort a set of APKs based on their split names, always placing the + * base APK (with {@code null} split name) first. + */ + private static class SplitNameComparator implements Comparator<String> { + @Override + public int compare(String lhs, String rhs) { + if (lhs == null) { + return -1; + } else if (rhs == null) { + return 1; + } else { + return lhs.compareTo(rhs); + } + } + } /** - * Parse all APK files under the given directory as a single package. + * Parse all APKs contained in the given directory, treating them as a + * single package. This also performs sanity checking, such as requiring + * identical package name and version codes, a single base APK, and unique + * split names. + * <p> + * Note that this <em>does not</em> perform signature verification; that + * must be done separately in {@link #collectCertificates(Package, int)}. */ - public Package parseSplitPackage(File apkDir, DisplayMetrics metrics, int flags, - boolean trustedOverlay) throws PackageParserException { + public Package parseSplitPackage(File apkDir, int flags) throws PackageParserException { final File[] files = apkDir.listFiles(); if (ArrayUtils.isEmpty(files)) { throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, "No packages found in split"); } - File baseFile = null; + String packageName = null; + int versionCode = 0; + + final ArrayMap<String, File> apks = new ArrayMap<>(); for (File file : files) { if (file.isFile() && isPackageFilename(file)) { - ApkLite lite = parseApkLite(file.getAbsolutePath(), 0); - if (lite == null) { - throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, - "Invalid package file: " + file); + final ApkLite lite = parseApkLite(file, 0); + + // Assert that all package names and version codes are + // consistent with the first one we encounter. + if (packageName == null) { + packageName = lite.packageName; + versionCode = lite.versionCode; + } else { + if (!packageName.equals(lite.packageName)) { + throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, + "Inconsistent package " + lite.packageName + " in " + file + + "; expected " + packageName); + } + if (versionCode != lite.versionCode) { + throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, + "Inconsistent version " + lite.versionCode + " in " + file + + "; expected " + versionCode); + } } - if (TextUtils.isEmpty(lite.splitName)) { - baseFile = file; - break; + // Assert that each split is defined only once + if (apks.put(lite.splitName, file) != null) { + throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, + "Split name " + lite.splitName + + " defined more than once; most recent was " + file); } } } + final File baseFile = apks.remove(null); if (baseFile == null) { - throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, + throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Missing base APK in " + apkDir); } - final Package pkg = parseBaseApk(baseFile, metrics, flags, trustedOverlay); + // Always apply deterministic ordering based on splitName + final int size = apks.size(); + + final String[] splitNames = apks.keySet().toArray(new String[size]); + Arrays.sort(splitNames, sSplitNameComparator); + + final File[] splitFiles = new File[size]; + for (int i = 0; i < size; i++) { + splitFiles[i] = apks.get(splitNames[i]); + } + + final Package pkg = parseBaseApk(baseFile, flags); if (pkg == null) { throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, "Failed to parse base APK: " + baseFile); } - for (File file : files) { - if (file.isFile() && isPackageFilename(file) && !file.equals(baseFile)) { - parseSplitApk(pkg, file, metrics, flags, trustedOverlay); - } - } - - // Always use a well-defined sort order - if (pkg.splitCodePaths != null) { - Arrays.sort(pkg.splitCodePaths); + for (File splitFile : splitFiles) { + parseSplitApk(pkg, splitFile, flags); } return pkg; } - public Package parseMonolithicPackage(File apkFile, DisplayMetrics metrics, int flags) - throws PackageParserException { - return parseMonolithicPackage(apkFile, metrics, flags, false); - } - - public Package parseMonolithicPackage(File apkFile, DisplayMetrics metrics, int flags, - boolean trustedOverlay) throws PackageParserException { - final Package pkg = parseBaseApk(apkFile, metrics, flags, trustedOverlay); + /** + * Parse the given APK file, treating it as as a single monolithic package. + * <p> + * Note that this <em>does not</em> perform signature verification; that + * must be done separately in {@link #collectCertificates(Package, int)}. + */ + public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException { + final Package pkg = parseBaseApk(apkFile, flags); if (pkg != null) { return pkg; } else { @@ -576,13 +639,15 @@ public class PackageParser { } } - private Package parseBaseApk(File apkFile, DisplayMetrics metrics, int flags, - boolean trustedOverlay) { + private Package parseBaseApk(File apkFile, int flags) { + final boolean trustedOverlay = (flags & PARSE_TRUSTED_OVERLAY) != 0; + mParseError = PackageManager.INSTALL_SUCCEEDED; + final String apkPath = apkFile.getAbsolutePath(); mArchiveSourcePath = apkFile.getAbsolutePath(); if (!apkFile.isFile()) { - Slog.w(TAG, "Skipping dir: " + mArchiveSourcePath); + Slog.w(TAG, "Skipping dir: " + apkPath); mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK; return null; } @@ -591,14 +656,14 @@ public class PackageParser { if ((flags&PARSE_IS_SYSTEM) == 0) { // We expect to have non-.apk files in the system dir, // so don't warn about them. - Slog.w(TAG, "Skipping non-package file: " + mArchiveSourcePath); + Slog.w(TAG, "Skipping non-package file: " + apkPath); } mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK; return null; } if (DEBUG_JAR) - Slog.d(TAG, "Scanning package: " + mArchiveSourcePath); + Slog.d(TAG, "Scanning package: " + apkPath); XmlResourceParser parser = null; AssetManager assmgr = null; @@ -606,19 +671,18 @@ public class PackageParser { boolean assetError = true; try { assmgr = new AssetManager(); - int cookie = assmgr.addAssetPath(mArchiveSourcePath); + int cookie = assmgr.addAssetPath(apkPath); if (cookie != 0) { - res = new Resources(assmgr, metrics, null); + res = new Resources(assmgr, mMetrics, null); assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Build.VERSION.RESOURCES_SDK_INT); parser = assmgr.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME); assetError = false; } else { - Slog.w(TAG, "Failed adding asset path:"+mArchiveSourcePath); + Slog.w(TAG, "Failed adding asset path:" + apkPath); } } catch (Exception e) { - Slog.w(TAG, "Unable to read AndroidManifest.xml of " - + mArchiveSourcePath, e); + Slog.w(TAG, "Unable to read AndroidManifest.xml of " + apkPath, e); } if (assetError) { if (assmgr != null) assmgr.close(); @@ -641,9 +705,9 @@ public class PackageParser { // just means to skip this app so don't make a fuss about it. if (!mOnlyCoreApps || mParseError != PackageManager.INSTALL_SUCCEEDED) { if (errorException != null) { - Slog.w(TAG, mArchiveSourcePath, errorException); + Slog.w(TAG, apkPath, errorException); } else { - Slog.w(TAG, mArchiveSourcePath + " (at " + Slog.w(TAG, apkPath + " (at " + parser.getPositionDescription() + "): " + errorText[0]); } @@ -659,14 +723,16 @@ public class PackageParser { parser.close(); assmgr.close(); - pkg.codePath = mArchiveSourcePath; + pkg.codePath = apkPath; pkg.mSignatures = null; return pkg; } - private void parseSplitApk(Package pkg, File apkFile, DisplayMetrics metrics, int flags, - boolean trustedOverlay) throws PackageParserException { + private void parseSplitApk(Package pkg, File apkFile, int flags) throws PackageParserException { + final String apkPath = apkFile.getAbsolutePath(); + mArchiveSourcePath = apkFile.getAbsolutePath(); + // TODO: expand split APK parsing pkg.splitCodePaths = ArrayUtils.appendElement(String.class, pkg.splitCodePaths, apkFile.getAbsolutePath()); @@ -678,8 +744,11 @@ 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(mArchiveSourcePath); + final StrictJarFile jarFile = new StrictJarFile(pkg.codePath); try { final ZipEntry je = jarFile.findEntry(ANDROID_MANIFEST_FILENAME); if (je != null) { @@ -688,186 +757,127 @@ public class PackageParser { } finally { jarFile.close(); } - } catch (IOException e) { + } catch (IOException | RuntimeException e) { throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, "Failed to collect manifest digest"); } } + /** + * Collect certificates from all the APKs described in the given package, + * populating {@link Package#mSignatures}. This also asserts that all APK + * contents are signed correctly and consistently. + */ public void collectCertificates(Package pkg, int flags) throws PackageParserException { - if (!collectCertificatesInternal(pkg, flags)) { - throw new PackageParserException(mParseError, "Failed to collect certificates"); - } - } - - private boolean collectCertificatesInternal(Package pkg, int flags) { + pkg.mCertificates = null; pkg.mSignatures = null; + pkg.mSigningKeys = null; - WeakReference<byte[]> readBufferRef; - byte[] readBuffer = null; - synchronized (mSync) { - readBufferRef = mReadBuffer; - if (readBufferRef != null) { - mReadBuffer = null; - readBuffer = readBufferRef.get(); - } - if (readBuffer == null) { - readBuffer = new byte[8192]; - readBufferRef = new WeakReference<byte[]>(readBuffer); + collectCertificates(pkg, new File(pkg.codePath), flags); + + if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) { + for (String splitCodePath : pkg.splitCodePaths) { + collectCertificates(pkg, new File(splitCodePath), flags); } } + } + + private static void collectCertificates(Package pkg, File apkFile, int flags) + throws PackageParserException { + final String apkPath = apkFile.getAbsolutePath(); + StrictJarFile jarFile = null; try { - StrictJarFile jarFile = new StrictJarFile(mArchiveSourcePath); - - Certificate[][] certs = null; - - if ((flags&PARSE_IS_SYSTEM) != 0) { - // If this package comes from the system image, then we - // can trust it... we'll just use the AndroidManifest.xml - // to retrieve its signatures, not validating all of the - // files. - ZipEntry jarEntry = jarFile.findEntry(ANDROID_MANIFEST_FILENAME); - certs = loadCertificates(jarFile, jarEntry, readBuffer); - if (certs == null) { - Slog.e(TAG, "Package " + pkg.packageName - + " has no certificates at entry " - + jarEntry.getName() + "; ignoring!"); - jarFile.close(); - mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES; - return false; - } - if (DEBUG_JAR) { - Slog.i(TAG, "File " + mArchiveSourcePath + ": entry=" + jarEntry - + " certs=" + (certs != null ? certs.length : 0)); - if (certs != null) { - final int N = certs.length; - for (int i=0; i<N; i++) { - Slog.i(TAG, " Public key: " - + certs[i][0].getPublicKey().getEncoded() - + " " + certs[i][0].getPublicKey()); - } - } - } - } else { - Iterator<ZipEntry> entries = jarFile.iterator(); - while (entries.hasNext()) { - final ZipEntry je = entries.next(); - if (je.isDirectory()) continue; + jarFile = new StrictJarFile(apkPath); - final String name = je.getName(); + // Always verify manifest, regardless of source + final ZipEntry manifestEntry = jarFile.findEntry(ANDROID_MANIFEST_FILENAME); + if (manifestEntry == null) { + throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, + "Package " + apkPath + " has no manifest"); + } - if (name.startsWith("META-INF/")) - continue; + final List<ZipEntry> toVerify = new ArrayList<>(); + toVerify.add(manifestEntry); - if (ANDROID_MANIFEST_FILENAME.equals(name)) { - pkg.manifestDigest = - ManifestDigest.fromInputStream(jarFile.getInputStream(je)); - } + // If we're parsing an untrusted package, verify all contents + if ((flags & PARSE_IS_SYSTEM) == 0) { + final Iterator<ZipEntry> i = jarFile.iterator(); + while (i.hasNext()) { + final ZipEntry entry = i.next(); - final Certificate[][] localCerts = loadCertificates(jarFile, je, readBuffer); - if (DEBUG_JAR) { - Slog.i(TAG, "File " + mArchiveSourcePath + " entry " + je.getName() - + ": certs=" + certs + " (" - + (certs != null ? certs.length : 0) + ")"); - } + if (entry.isDirectory()) continue; + if (entry.getName().startsWith("META-INF/")) continue; + if (entry.getName().equals(ANDROID_MANIFEST_FILENAME)) continue; - if (localCerts == null) { - Slog.e(TAG, "Package " + pkg.packageName - + " has no certificates at entry " - + je.getName() + "; ignoring!"); - jarFile.close(); - mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES; - return false; - } else if (certs == null) { - certs = localCerts; - } else { - // Ensure all certificates match. - for (int i=0; i<certs.length; i++) { - boolean found = false; - for (int j=0; j<localCerts.length; j++) { - if (certs[i] != null && - certs[i].equals(localCerts[j])) { - found = true; - break; - } - } - if (!found || certs.length != localCerts.length) { - Slog.e(TAG, "Package " + pkg.packageName - + " has mismatched certificates at entry " - + je.getName() + "; ignoring!"); - jarFile.close(); - mParseError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; - return false; - } - } - } + toVerify.add(entry); } } - jarFile.close(); - - synchronized (mSync) { - mReadBuffer = readBufferRef; - } - if (!ArrayUtils.isEmpty(certs)) { - pkg.mSignatures = convertToSignatures(certs); - } else { - Slog.e(TAG, "Package " + pkg.packageName - + " has no certificates; ignoring!"); - mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES; - return false; - } + // Verify that entries are signed consistently with the first entry + // we encountered. Note that for splits, certificates may have + // already been populated during an earlier parse of a base APK. + for (ZipEntry entry : toVerify) { + final Certificate[][] entryCerts = loadCertificates(jarFile, entry); + if (ArrayUtils.isEmpty(entryCerts)) { + throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, + "Package " + apkPath + " has no certificates at entry " + + entry.getName()); + } - // Add the signing KeySet to the system - pkg.mSigningKeys = new HashSet<PublicKey>(); - for (int i=0; i < certs.length; i++) { - pkg.mSigningKeys.add(certs[i][0].getPublicKey()); + if (pkg.mCertificates == null) { + pkg.mCertificates = entryCerts; + pkg.mSignatures = convertToSignatures(entryCerts); + pkg.mSigningKeys = new ArraySet<>(); + for (int i = 0; i < entryCerts.length; i++) { + pkg.mSigningKeys.add(entryCerts[i][0].getPublicKey()); + } + } else { + final boolean certsMatch = (pkg.mCertificates.length == entryCerts.length) + && ArrayUtils.containsAll(pkg.mCertificates, entryCerts) + && ArrayUtils.containsAll(entryCerts, pkg.mCertificates); + if (!certsMatch) { + throw new PackageParserException( + INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, "Package " + apkPath + + " has mismatched certificates at entry " + + entry.getName()); + } + } } - - } catch (CertificateEncodingException e) { - Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e); - mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING; - return false; - } catch (IOException e) { - Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e); - mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING; - return false; - } catch (SecurityException e) { - Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e); - mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING; - return false; - } catch (RuntimeException e) { - Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e); - mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION; - return false; + } catch (GeneralSecurityException | IOException | RuntimeException e) { + throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING, + "Failed to collect certificates from " + apkPath, e); + } finally { + closeQuietly(jarFile); } - - return true; } /** * Only collect certificates on the manifest; does not validate signatures * across remainder of package. */ - private static Signature[] collectCertificates(String packageFilePath) { + private static Signature[] collectManifestCertificates(File apkFile) + throws PackageParserException { + final String apkPath = apkFile.getAbsolutePath(); try { - final StrictJarFile jarFile = new StrictJarFile(packageFilePath); + final StrictJarFile jarFile = new StrictJarFile(apkPath); try { final ZipEntry jarEntry = jarFile.findEntry(ANDROID_MANIFEST_FILENAME); - if (jarEntry != null) { - final Certificate[][] certs = loadCertificates(jarFile, jarEntry, null); - return convertToSignatures(certs); + if (jarEntry == null) { + throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Package " + apkPath + " has no manifest"); } + + final Certificate[][] certs = loadCertificates(jarFile, jarEntry); + return convertToSignatures(certs); + } finally { jarFile.close(); } - } catch (GeneralSecurityException e) { - Slog.w(TAG, "Failed to collect certs from " + packageFilePath + ": " + e); - } catch (IOException e) { - Slog.w(TAG, "Failed to collect certs from " + packageFilePath + ": " + e); + } catch (GeneralSecurityException | IOException | RuntimeException e) { + throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING, + "Failed to collect certificates from " + apkPath, e); } - return null; } private static Signature[] convertToSignatures(Certificate[][] certs) @@ -879,67 +889,55 @@ public class PackageParser { return res; } - /* - * Utility method that retrieves just the package name and install - * location from the apk location at the given file path. - * @param packageFilePath file location of the apk - * @param flags Special parse flags - * @return PackageLite object with package information or null on failure. + /** + * Utility method that retrieves lightweight details about a single APK + * file, including package name, split name, and install location. + * + * @param apkFile path to a single APK + * @param flags optional parse flags, such as {@link #PARSE_GET_SIGNATURES} */ - public static ApkLite parseApkLite(String packageFilePath, int flags) { + public static ApkLite parseApkLite(File apkFile, int flags) + throws PackageParserException { + final String apkPath = apkFile.getAbsolutePath(); + AssetManager assmgr = null; - final XmlResourceParser parser; - final Resources res; + XmlResourceParser parser = null; try { assmgr = new AssetManager(); assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Build.VERSION.RESOURCES_SDK_INT); - int cookie = assmgr.addAssetPath(packageFilePath); + int cookie = assmgr.addAssetPath(apkPath); if (cookie == 0) { - return null; + throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, + "Failed to parse " + apkPath); } final DisplayMetrics metrics = new DisplayMetrics(); metrics.setToDefaults(); - res = new Resources(assmgr, metrics, null); + + final Resources res = new Resources(assmgr, metrics, null); parser = assmgr.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME); - } catch (Exception e) { - if (assmgr != null) assmgr.close(); - Slog.w(TAG, "Unable to read AndroidManifest.xml of " - + packageFilePath, e); - return null; - } - // Only collect certificates on the manifest; does not validate - // signatures across remainder of package. - final Signature[] signatures; - if ((flags & PARSE_GET_SIGNATURES) != 0) { - signatures = collectCertificates(packageFilePath); - } else { - signatures = null; - } + // Only collect certificates on the manifest; does not validate + // signatures across remainder of package. + final Signature[] signatures; + if ((flags & PARSE_GET_SIGNATURES) != 0) { + signatures = collectManifestCertificates(apkFile); + } else { + signatures = null; + } - final AttributeSet attrs = parser; - final String errors[] = new String[1]; - ApkLite packageLite = null; - try { - packageLite = parseApkLite(res, parser, attrs, flags, signatures, errors); - } catch (PackageParserException e) { - Slog.w(TAG, packageFilePath, e); - } catch (IOException e) { - Slog.w(TAG, packageFilePath, e); - } catch (XmlPullParserException e) { - Slog.w(TAG, packageFilePath, e); + final AttributeSet attrs = parser; + return parseApkLite(res, parser, attrs, flags, signatures); + + } catch (XmlPullParserException | IOException | RuntimeException e) { + throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, + "Failed to parse " + apkPath, e); } finally { if (parser != null) parser.close(); if (assmgr != null) assmgr.close(); } - if (packageLite == null) { - Slog.e(TAG, "parsePackageLite error: " + errors[0]); - return null; - } - return packageLite; } private static String validateName(String name, boolean requiresSeparator) { @@ -995,12 +993,16 @@ public class PackageParser { } } - final String splitName = attrs.getAttributeValue(null, "split"); + String splitName = attrs.getAttributeValue(null, "split"); if (splitName != null) { - final String error = validateName(splitName, true); - if (error != null) { - throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME, - "Invalid manifest split: " + error); + if (splitName.length() == 0) { + splitName = null; + } else { + final String error = validateName(splitName, true); + if (error != null) { + throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME, + "Invalid manifest split: " + error); + } } } @@ -1009,8 +1011,8 @@ public class PackageParser { } private static ApkLite parseApkLite(Resources res, XmlPullParser parser, - AttributeSet attrs, int flags, Signature[] signatures, String[] outError) - throws IOException, XmlPullParserException, PackageParserException { + AttributeSet attrs, int flags, Signature[] signatures) throws IOException, + XmlPullParserException, PackageParserException { final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs, flags); int installLocation = PARSE_DEFAULT_INSTALL_LOCATION; @@ -1043,7 +1045,7 @@ public class PackageParser { } if (parser.getDepth() == searchDepth && "package-verifier".equals(parser.getName())) { - final VerifierInfo verifier = parseVerifier(res, parser, attrs, flags, outError); + final VerifierInfo verifier = parseVerifier(res, parser, attrs, flags); if (verifier != null) { verifiers.add(verifier); } @@ -1793,7 +1795,7 @@ public class PackageParser { } } - owner.mKeySetMapping = new HashMap<String, Set<PublicKey>>(); + owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>(); for (Map.Entry<PublicKey, Set<String>> e : definedKeySets.entrySet()) { PublicKey key = e.getKey(); Set<String> keySetNames = e.getValue(); @@ -1801,7 +1803,7 @@ public class PackageParser { if (owner.mKeySetMapping.containsKey(alias)) { owner.mKeySetMapping.get(alias).add(key); } else { - Set<PublicKey> keys = new HashSet<PublicKey>(); + ArraySet<PublicKey> keys = new ArraySet<PublicKey>(); keys.add(key); owner.mKeySetMapping.put(alias, keys); } @@ -2088,6 +2090,11 @@ public class PackageParser { false)) { ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION; } + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly, + false)) { + ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY; + } } } @@ -3427,8 +3434,7 @@ public class PackageParser { } private static VerifierInfo parseVerifier(Resources res, XmlPullParser parser, - AttributeSet attrs, int flags, String[] outError) throws XmlPullParserException, - IOException { + AttributeSet attrs, int flags) { final TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestPackageVerifier); @@ -3671,7 +3677,10 @@ public class PackageParser { public String packageName; // TODO: work towards making these paths invariant + + /** Base APK */ public String codePath; + /** Split APKs, ordered by parsed splitName */ public String[] splitCodePaths; // For now we only support one application per package. @@ -3717,7 +3726,8 @@ public class PackageParser { public int mSharedUserLabel; // Signatures that were read from the package. - public Signature mSignatures[]; + public Signature[] mSignatures; + public Certificate[][] mCertificates; // For use by package manager service for quick lookup of // preferred up order. @@ -3779,8 +3789,8 @@ public class PackageParser { /** * Data used to feed the KeySetManager */ - public Set<PublicKey> mSigningKeys; - public Map<String, Set<PublicKey>> mKeySetMapping; + public ArraySet<PublicKey> mSigningKeys; + public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping; public Package(String packageName) { this.packageName = packageName; @@ -3788,6 +3798,15 @@ public class PackageParser { applicationInfo.uid = -1; } + public Collection<String> getAllCodePaths() { + ArrayList<String> paths = new ArrayList<>(); + paths.add(codePath); + if (!ArrayUtils.isEmpty(splitCodePaths)) { + Collections.addAll(paths, splitCodePaths); + } + return paths; + } + public void setPackageName(String newName) { packageName = newName; applicationInfo.packageName = newName; @@ -4390,6 +4409,33 @@ public class PackageParser { sCompatibilityModeEnabled = compatibilityModeEnabled; } + private static AtomicReference<byte[]> sBuffer = new AtomicReference<byte[]>(); + + public static long readFullyIgnoringContents(InputStream in) throws IOException { + byte[] buffer = sBuffer.getAndSet(null); + if (buffer == null) { + buffer = new byte[4096]; + } + + int n = 0; + int count = 0; + while ((n = in.read(buffer, 0, buffer.length)) != -1) { + count += n; + } + + sBuffer.set(buffer); + return count; + } + + public static void closeQuietly(StrictJarFile jarFile) { + if (jarFile != null) { + try { + jarFile.close(); + } catch (Exception ignored) { + } + } + } + public static class PackageParserException extends Exception { public final int error; @@ -4397,5 +4443,10 @@ public class PackageParser { super(detailMessage); this.error = error; } + + public PackageParserException(int error, String detailMessage, Throwable throwable) { + super(detailMessage, throwable); + this.error = error; + } } } 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/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java index 54d9c3c32e7d..aa2f0269bb45 100644 --- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java +++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java @@ -169,7 +169,6 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { } int numSurfaces = mSurfaces.size(); if (numSurfaces > 0) { - surfaces = new ArrayList<Surface>(); 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..3f9c6ed272ca 100644 --- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java +++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java @@ -50,6 +50,7 @@ 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(); @@ -84,6 +85,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 +96,14 @@ public class LegacyCameraDevice implements AutoCloseable { } } }); - - } @Override public void onConfiguring() { // Do nothing + if (DEBUG) { + Log.d(TAG, "doing onConfiguring callback."); + } } @Override @@ -108,6 +113,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 +134,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 +146,6 @@ public class LegacyCameraDevice implements AutoCloseable { } } }); - } @Override @@ -145,6 +155,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); diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java index 8bb066fd09a3..e675f870211d 100644 --- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java +++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java @@ -44,6 +44,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} @@ -91,9 +96,6 @@ public class LegacyMetadataMapper { } 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 +124,25 @@ 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; + for (Camera.Size s : jpegSizes) { + jpegStalls[i++] = new StreamConfigurationDuration(HAL_PIXEL_FORMAT_BLOB, s.width, + s.height, calculateJpegStallDuration(s)); + } + // Set stall durations for jpeg, other formats use default stall duration + m.set(SCALER_AVAILABLE_STALL_DURATIONS, jpegStalls); } private static void appendStreamConfig( @@ -136,4 +153,17 @@ public class LegacyMetadataMapper { configs.add(config); } } + + /** + * 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; + } } diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java index 7b522ffa36ce..bf250a1d7c54 100644 --- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java +++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java @@ -71,6 +71,8 @@ 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; @@ -78,6 +80,7 @@ public class RequestThreadManager { private List<Surface> mCallbackOutputs = new ArrayList<Surface>(); private GLThreadManager mGLThreadManager; private SurfaceTexture mPreviewTexture; + private Camera.Parameters mParams; private Size mIntermediateBufferSize; @@ -86,6 +89,7 @@ public class RequestThreadManager { 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 +213,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 +267,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; } @@ -312,7 +327,7 @@ public class RequestThreadManager { 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 @@ -428,6 +441,9 @@ 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; @@ -460,6 +476,7 @@ public class RequestThreadManager { nextBurst.first.produceRequestHolders(nextBurst.second); for (RequestHolder holder : requests) { mDeviceState.setCaptureStart(holder); + long timestamp = 0; try { if (holder.hasPreviewTargets()) { mReceivedPreview.close(); @@ -468,6 +485,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 +496,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 = convertResultMetadata(mParams, + holder.getRequest(), timestamp); mDeviceState.setCaptureResult(holder, result); } + if (DEBUG) { + mRequestCounter.countAndLog(); + } break; case MSG_CLEANUP: mCleanup = true; @@ -507,9 +528,11 @@ public class RequestThreadManager { }; private CameraMetadataNative convertResultMetadata(Camera.Parameters params, - CaptureRequest request) { + 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; 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/os/UserManager.java b/core/java/android/os/UserManager.java index 757f38e065de..96db772f8ee5 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -719,6 +719,26 @@ public class UserManager { /** * If the target user is a managed profile of the calling user or the caller + * is itself a managed profile, then this returns a copy of the label with + * badging for accessibility services like talkback. E.g. passing in "Email" + * and it might return "Work Email" for Email in the work profile. + * + * @param label The label to change. + * @param user The target user. + * @return A label that combines the original label and a badge as + * determined by the system. + */ + public String getBadgedLabelForUser(String label, UserHandle user) { + UserInfo userInfo = getUserIfProfile(user.getIdentifier()); + if (userInfo != null && userInfo.isManagedProfile()) { + return Resources.getSystem().getString( + R.string.managed_profile_label_badge, label); + } + return label; + } + + /** + * If the target user is a managed profile of the calling user or the caller * is itself a managed profile, then this returns a drawable to use as a small * icon to include in a view to distinguish it from the original icon. * 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/transition/Explode.java b/core/java/android/transition/Explode.java index fae527c26789..feb8efd19572 100644 --- a/core/java/android/transition/Explode.java +++ b/core/java/android/transition/Explode.java @@ -15,20 +15,16 @@ */ package android.transition; +import com.android.internal.R; + import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.AnimatorSet; -import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; -import android.graphics.Path; import android.graphics.Rect; import android.util.FloatMath; -import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; - /** * This transition tracks changes to the visibility of target views in the * start and end scenes and moves views in or out from the edges of the @@ -44,8 +40,7 @@ public class Explode extends Visibility { private static final TimeInterpolator sDecelerate = new DecelerateInterpolator(); private static final TimeInterpolator sAccelerate = new AccelerateInterpolator(); private static final String TAG = "Explode"; - - private static final String PROPNAME_SCREEN_BOUNDS = "android:out:screenBounds"; + private static final String PROPNAME_SCREEN_BOUNDS = "android:explode:screenBounds"; private int[] mTempLoc = new int[2]; @@ -56,8 +51,8 @@ public class Explode extends Visibility { private void captureValues(TransitionValues transitionValues) { View view = transitionValues.view; view.getLocationOnScreen(mTempLoc); - int left = mTempLoc[0] + Math.round(view.getTranslationX()); - int top = mTempLoc[1] + Math.round(view.getTranslationY()); + int left = mTempLoc[0]; + int top = mTempLoc[1]; int right = left + view.getWidth(); int bottom = top + view.getHeight(); transitionValues.values.put(PROPNAME_SCREEN_BOUNDS, new Rect(left, top, right, bottom)); @@ -75,27 +70,6 @@ public class Explode extends Visibility { captureValues(transitionValues); } - private Animator createAnimation(final View view, float startX, float startY, float endX, - float endY, float terminalX, float terminalY, TimeInterpolator interpolator) { - view.setTranslationX(startX); - view.setTranslationY(startY); - if (startY == endY && startX == endX) { - return null; - } - Path path = new Path(); - path.moveTo(startX, startY); - path.lineTo(endX, endY); - ObjectAnimator pathAnimator = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, - View.TRANSLATION_Y, path); - pathAnimator.setInterpolator(interpolator); - OutAnimatorListener listener = new OutAnimatorListener(view, terminalX, terminalY, - endX, endY); - pathAnimator.addListener(listener); - pathAnimator.addPauseListener(listener); - - return pathAnimator; - } - @Override public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues) { @@ -103,29 +77,43 @@ public class Explode extends Visibility { return null; } Rect bounds = (Rect) endValues.values.get(PROPNAME_SCREEN_BOUNDS); + float endX = view.getTranslationX(); + float endY = view.getTranslationY(); calculateOut(sceneRoot, bounds, mTempLoc); + float startX = endX + mTempLoc[0]; + float startY = endY + mTempLoc[1]; - final float endX = view.getTranslationX(); - final float startX = endX + mTempLoc[0]; - final float endY = view.getTranslationY(); - final float startY = endY + mTempLoc[1]; - - return createAnimation(view, startX, startY, endX, endY, endX, endY, sDecelerate); + return TranslationAnimationCreator.createAnimation(view, endValues, bounds.left, bounds.top, + startX, startY, endX, endY, sDecelerate); } @Override public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues) { + if (startValues == null) { + return null; + } Rect bounds = (Rect) startValues.values.get(PROPNAME_SCREEN_BOUNDS); + int viewPosX = bounds.left; + int viewPosY = bounds.top; + float startX = view.getTranslationX(); + float startY = view.getTranslationY(); + float endX = startX; + float endY = startY; + int[] interruptedPosition = (int[]) startValues.view.getTag(R.id.transitionPosition); + if (interruptedPosition != null) { + // We want to have the end position relative to the interrupted position, not + // the position it was supposed to start at. + endX += interruptedPosition[0] - bounds.left; + endY += interruptedPosition[1] - bounds.top; + bounds.offsetTo(interruptedPosition[0], interruptedPosition[1]); + } calculateOut(sceneRoot, bounds, mTempLoc); + endX += mTempLoc[0]; + endY += mTempLoc[1]; - final float startX = view.getTranslationX(); - final float endX = startX + mTempLoc[0]; - final float startY = view.getTranslationY(); - final float endY = startY + mTempLoc[1]; - - return createAnimation(view, startX, startY, endX, endY, startX, startY, - sAccelerate); + return TranslationAnimationCreator.createAnimation(view, startValues, + viewPosX, viewPosY, startX, startY, endX, endY, sAccelerate); } private void calculateOut(View sceneRoot, Rect bounds, int[] outVector) { @@ -153,8 +141,8 @@ public class Explode extends Visibility { if (xVector == 0 && yVector == 0) { // Random direction when View is centered on focal View. - xVector = (float)(Math.random() * 2) - 1; - yVector = (float)(Math.random() * 2) - 1; + xVector = (float) (Math.random() * 2) - 1; + yVector = (float) (Math.random() * 2) - 1; } float vectorSize = calculateDistance(xVector, yVector); xVector /= vectorSize; @@ -176,53 +164,4 @@ public class Explode extends Visibility { private static float calculateDistance(float x, float y) { return FloatMath.sqrt((x * x) + (y * y)); } - - private static class OutAnimatorListener extends AnimatorListenerAdapter { - private final View mView; - private boolean mCanceled = false; - private float mPausedX; - private float mPausedY; - private final float mTerminalX; - private final float mTerminalY; - private final float mEndX; - private final float mEndY; - - public OutAnimatorListener(View view, float terminalX, float terminalY, - float endX, float endY) { - mView = view; - mTerminalX = terminalX; - mTerminalY = terminalY; - mEndX = endX; - mEndY = endY; - } - - @Override - public void onAnimationCancel(Animator animator) { - mView.setTranslationX(mTerminalX); - mView.setTranslationY(mTerminalY); - mCanceled = true; - } - - @Override - public void onAnimationEnd(Animator animator) { - if (!mCanceled) { - mView.setTranslationX(mTerminalX); - mView.setTranslationY(mTerminalY); - } - } - - @Override - public void onAnimationPause(Animator animator) { - mPausedX = mView.getTranslationX(); - mPausedY = mView.getTranslationY(); - mView.setTranslationY(mEndX); - mView.setTranslationY(mEndY); - } - - @Override - public void onAnimationResume(Animator animator) { - mView.setTranslationX(mPausedX); - mView.setTranslationY(mPausedY); - } - } } diff --git a/core/java/android/transition/Slide.java b/core/java/android/transition/Slide.java index 8269258eaad8..0d2e4870926e 100644 --- a/core/java/android/transition/Slide.java +++ b/core/java/android/transition/Slide.java @@ -16,14 +16,7 @@ package android.transition; import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.AnimatorSet; -import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; -import android.animation.ValueAnimator; -import android.graphics.Rect; -import android.util.Log; -import android.util.Property; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; @@ -41,71 +34,60 @@ import android.view.animation.DecelerateInterpolator; */ public class Slide extends Visibility { private static final String TAG = "Slide"; - private static final TimeInterpolator sDecelerate = new DecelerateInterpolator(); private static final TimeInterpolator sAccelerate = new AccelerateInterpolator(); - + private static final String PROPNAME_SCREEN_POSITION = "android:slide:screenPosition"; private CalculateSlide mSlideCalculator = sCalculateBottom; private interface CalculateSlide { - /** Returns the translation value for view when it out of the scene */ - float getGone(ViewGroup sceneRoot, View view); - /** Returns the translation value for view when it is in the scene */ - float getHere(View view); + /** Returns the translation value for view when it goes out of the scene */ + float getGoneX(ViewGroup sceneRoot, View view); - /** Returns the property to animate translation */ - Property<View, Float> getProperty(); + /** Returns the translation value for view when it goes out of the scene */ + float getGoneY(ViewGroup sceneRoot, View view); } private static abstract class CalculateSlideHorizontal implements CalculateSlide { - @Override - public float getHere(View view) { - return view.getTranslationX(); - } @Override - public Property<View, Float> getProperty() { - return View.TRANSLATION_X; + public float getGoneY(ViewGroup sceneRoot, View view) { + return view.getTranslationY(); } } private static abstract class CalculateSlideVertical implements CalculateSlide { - @Override - public float getHere(View view) { - return view.getTranslationY(); - } @Override - public Property<View, Float> getProperty() { - return View.TRANSLATION_Y; + public float getGoneX(ViewGroup sceneRoot, View view) { + return view.getTranslationX(); } } private static final CalculateSlide sCalculateLeft = new CalculateSlideHorizontal() { @Override - public float getGone(ViewGroup sceneRoot, View view) { + public float getGoneX(ViewGroup sceneRoot, View view) { return view.getTranslationX() - sceneRoot.getWidth(); } }; private static final CalculateSlide sCalculateTop = new CalculateSlideVertical() { @Override - public float getGone(ViewGroup sceneRoot, View view) { + public float getGoneY(ViewGroup sceneRoot, View view) { return view.getTranslationY() - sceneRoot.getHeight(); } }; private static final CalculateSlide sCalculateRight = new CalculateSlideHorizontal() { @Override - public float getGone(ViewGroup sceneRoot, View view) { + public float getGoneX(ViewGroup sceneRoot, View view) { return view.getTranslationX() + sceneRoot.getWidth(); } }; private static final CalculateSlide sCalculateBottom = new CalculateSlideVertical() { @Override - public float getGone(ViewGroup sceneRoot, View view) { + public float getGoneY(ViewGroup sceneRoot, View view) { return view.getTranslationY() + sceneRoot.getHeight(); } }; @@ -125,8 +107,28 @@ public class Slide extends Visibility { setSlideEdge(slideEdge); } + private void captureValues(TransitionValues transitionValues) { + View view = transitionValues.view; + int[] position = new int[2]; + view.getLocationOnScreen(position); + transitionValues.values.put(PROPNAME_SCREEN_POSITION, position); + } + + @Override + public void captureStartValues(TransitionValues transitionValues) { + super.captureStartValues(transitionValues); + captureValues(transitionValues); + } + + @Override + public void captureEndValues(TransitionValues transitionValues) { + super.captureEndValues(transitionValues); + captureValues(transitionValues); + } + /** * Change the edge that Views appear and disappear from. + * * @param slideEdge The edge of the scene to use for Views appearing and disappearing. One of * {@link android.view.Gravity#LEFT}, {@link android.view.Gravity#TOP}, * {@link android.view.Gravity#RIGHT}, {@link android.view.Gravity#BOTTOM}. @@ -153,77 +155,35 @@ public class Slide extends Visibility { setPropagation(propagation); } - private Animator createAnimation(final View view, Property<View, Float> property, - float start, float end, float terminalValue, TimeInterpolator interpolator) { - view.setTranslationY(start); - if (start == end) { - return null; - } - final ObjectAnimator anim = ObjectAnimator.ofFloat(view, property, start, end); - - SlideAnimatorListener listener = new SlideAnimatorListener(view, terminalValue, end); - anim.addListener(listener); - anim.addPauseListener(listener); - anim.setInterpolator(interpolator); - return anim; - } - @Override public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues) { if (endValues == null) { return null; } - float end = mSlideCalculator.getHere(view); - float start = mSlideCalculator.getGone(sceneRoot, view); - return createAnimation(view, mSlideCalculator.getProperty(), start, end, end, sDecelerate); + int[] position = (int[]) endValues.values.get(PROPNAME_SCREEN_POSITION); + float endX = view.getTranslationX(); + float endY = view.getTranslationY(); + float startX = mSlideCalculator.getGoneX(sceneRoot, view); + float startY = mSlideCalculator.getGoneY(sceneRoot, view); + return TranslationAnimationCreator + .createAnimation(view, endValues, position[0], position[1], + startX, startY, endX, endY, sDecelerate); } @Override public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues) { - float start = mSlideCalculator.getHere(view); - float end = mSlideCalculator.getGone(sceneRoot, view); - - return createAnimation(view, mSlideCalculator.getProperty(), start, end, start, - sAccelerate); - } - - private static class SlideAnimatorListener extends AnimatorListenerAdapter { - private boolean mCanceled = false; - private float mPausedY; - private final View mView; - private final float mEndY; - private final float mTerminalY; - - public SlideAnimatorListener(View view, float terminalY, float endY) { - mView = view; - mTerminalY = terminalY; - mEndY = endY; - } - - @Override - public void onAnimationCancel(Animator animator) { - mView.setTranslationY(mTerminalY); - mCanceled = true; - } - - @Override - public void onAnimationEnd(Animator animator) { - if (!mCanceled) { - mView.setTranslationY(mTerminalY); - } - } - - @Override - public void onAnimationPause(Animator animator) { - mPausedY = mView.getTranslationY(); - mView.setTranslationY(mEndY); - } - - @Override - public void onAnimationResume(Animator animator) { - mView.setTranslationY(mPausedY); + if (startValues == null) { + return null; } + int[] position = (int[]) startValues.values.get(PROPNAME_SCREEN_POSITION); + float startX = view.getTranslationX(); + float startY = view.getTranslationY(); + float endX = mSlideCalculator.getGoneX(sceneRoot, view); + float endY = mSlideCalculator.getGoneY(sceneRoot, view); + return TranslationAnimationCreator + .createAnimation(view, startValues, position[0], position[1], + startX, startY, endX, endY, sAccelerate); } } diff --git a/core/java/android/transition/TranslationAnimationCreator.java b/core/java/android/transition/TranslationAnimationCreator.java new file mode 100644 index 000000000000..de71fd7a0a15 --- /dev/null +++ b/core/java/android/transition/TranslationAnimationCreator.java @@ -0,0 +1,139 @@ +/* + * 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.transition; + +import com.android.internal.R; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; +import android.animation.TimeInterpolator; +import android.graphics.Path; +import android.view.View; + +/** + * This class is used by Slide and Explode to create an animator that goes from the start + * position to the end position. It takes into account the canceled position so that it + * will not blink out or shift suddenly when the transition is interrupted. + */ +class TranslationAnimationCreator { + + /** + * Creates an animator that can be used for x and/or y translations. When interrupted, + * it sets a tag to keep track of the position so that it may be continued from position. + * + * @param view The view being moved. This may be in the overlay for onDisappear. + * @param values The values containing the view in the view hierarchy. + * @param viewPosX The x screen coordinate of view + * @param viewPosY The y screen coordinate of view + * @param startX The start translation x of view + * @param startY The start translation y of view + * @param endX The end translation x of view + * @param endY The end translation y of view + * @param interpolator The interpolator to use with this animator. + * @return An animator that moves from (startX, startY) to (endX, endY) unless there was + * a previous interruption, in which case it moves from the current position to (endX, endY). + */ + static Animator createAnimation(View view, TransitionValues values, int viewPosX, int viewPosY, + float startX, float startY, float endX, float endY, TimeInterpolator interpolator) { + float terminalX = view.getTranslationX(); + float terminalY = view.getTranslationY(); + int[] startPosition = (int[]) values.view.getTag(R.id.transitionPosition); + if (startPosition != null) { + startX = startPosition[0] - viewPosX + terminalX; + startY = startPosition[1] - viewPosY + terminalY; + } + // Initial position is at translation startX, startY, so position is offset by that amount + int startPosX = viewPosX + Math.round(startX - terminalX); + int startPosY = viewPosY + Math.round(startY - terminalY); + + view.setTranslationX(startX); + view.setTranslationY(startY); + if (startX == endX && startY == endY) { + return null; + } + Path path = new Path(); + path.moveTo(startX, startY); + path.lineTo(endX, endY); + ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, View.TRANSLATION_Y, + path); + + TransitionPositionListener listener = new TransitionPositionListener(view, values.view, + startPosX, startPosY, terminalX, terminalY); + anim.addListener(listener); + anim.addPauseListener(listener); + anim.setInterpolator(interpolator); + return anim; + } + + private static class TransitionPositionListener extends AnimatorListenerAdapter { + + private final View mViewInHierarchy; + private final View mMovingView; + private final int mStartX; + private final int mStartY; + private int[] mTransitionPosition; + private float mPausedX; + private float mPausedY; + private final float mTerminalX; + private final float mTerminalY; + + private TransitionPositionListener(View movingView, View viewInHierarchy, + int startX, int startY, float terminalX, float terminalY) { + mMovingView = movingView; + mViewInHierarchy = viewInHierarchy; + mStartX = startX - Math.round(mMovingView.getTranslationX()); + mStartY = startY - Math.round(mMovingView.getTranslationY()); + mTerminalX = terminalX; + mTerminalY = terminalY; + mTransitionPosition = (int[]) mViewInHierarchy.getTag(R.id.transitionPosition); + if (mTransitionPosition != null) { + mViewInHierarchy.setTagInternal(R.id.transitionPosition, null); + } + } + + @Override + public void onAnimationCancel(Animator animation) { + if (mTransitionPosition == null) { + mTransitionPosition = new int[2]; + } + mTransitionPosition[0] = Math.round(mStartX + mMovingView.getTranslationX()); + mTransitionPosition[1] = Math.round(mStartY + mMovingView.getTranslationY()); + mViewInHierarchy.setTagInternal(R.id.transitionPosition, mTransitionPosition); + } + + @Override + public void onAnimationEnd(Animator animator) { + mMovingView.setTranslationX(mTerminalX); + mMovingView.setTranslationY(mTerminalY); + } + + @Override + public void onAnimationPause(Animator animator) { + mPausedX = mMovingView.getTranslationX(); + mPausedY = mMovingView.getTranslationY(); + mMovingView.setTranslationX(mTerminalX); + mMovingView.setTranslationY(mTerminalY); + } + + @Override + public void onAnimationResume(Animator animator) { + mMovingView.setTranslationX(mPausedX); + mMovingView.setTranslationY(mPausedY); + } + } + +} 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/Display.java b/core/java/android/view/Display.java index 181f77e2c886..76a6f5231b2e 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -606,7 +606,6 @@ public final class Display { * <p> * Apps generally do not need to be aware of this. It's only useful for fine-grained * A/V synchronization. - * @hide */ public long getAppVsyncOffsetNanos() { synchronized (this) { @@ -625,7 +624,6 @@ public final class Display { * {@link android.media.MediaCodec#releaseOutputBuffer(int, long)}. Times are * expressed in nanoseconds, using the system monotonic clock * ({@link System#nanoTime}). - * @hide */ public long getPresentationDeadlineNanos() { synchronized (this) { 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 9156216dd619..d25ef1655e7e 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -45,7 +45,6 @@ import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; import android.graphics.Shader; -import android.graphics.PorterDuff.Mode; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.hardware.display.DisplayManagerGlobal; @@ -4822,20 +4821,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final float x = r.exactCenterX(); final float y = r.exactCenterY(); - setDrawableHotspot(x, y); - } - - /** - * Sets the hotspot position for this View's drawables. - * - * @param x hotspot x coordinate - * @param y hotspot y coordinate - * @hide - */ - protected void setDrawableHotspot(float x, float y) { - if (mBackground != null) { - mBackground.setHotspot(x, y); - } + drawableHotspotChanged(x, y); } /** @@ -6798,7 +6784,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ private void setPressed(boolean pressed, float x, float y) { if (pressed) { - setDrawableHotspot(x, y); + drawableHotspotChanged(x, y); } setPressed(pressed); @@ -9149,7 +9135,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, break; case MotionEvent.ACTION_MOVE: - setDrawableHotspot(x, y); + drawableHotspotChanged(x, y); // Be lenient about moving outside of buttons if (!pointInView(x, y, mTouchSlop)) { @@ -14254,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; } @@ -15531,6 +15518,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * This function is called whenever the drawable hotspot changes. + * <p> + * Be sure to call through to the superclass when overriding this function. + * + * @param x hotspot x coordinate + * @param y hotspot y coordinate + */ + public void drawableHotspotChanged(float x, float y) { + if (mBackground != null) { + mBackground.setHotspot(x, y); + } + } + + /** * Call this to force a view to update its drawable state. This will cause * drawableStateChanged to be called on this view. Views that are interested * in the new state should call getDrawableState. 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/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java index eb3f88234157..7e2d809b9aaa 100644 --- a/core/java/android/widget/AbsSeekBar.java +++ b/core/java/android/widget/AbsSeekBar.java @@ -24,7 +24,6 @@ import android.graphics.Canvas; import android.graphics.Insets; import android.graphics.PorterDuff; import android.graphics.Rect; -import android.graphics.PorterDuff.Mode; import android.graphics.Region.Op; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -343,7 +342,10 @@ public abstract class AbsSeekBar extends ProgressBar { @Override public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); - if (mThumb != null) mThumb.jumpToCurrentState(); + + if (mThumb != null) { + mThumb.jumpToCurrentState(); + } } @Override @@ -361,29 +363,12 @@ public abstract class AbsSeekBar extends ProgressBar { } } - /** @hide */ @Override - protected void setDrawableHotspot(float x, float y) { - super.setDrawableHotspot(x, y); + public void drawableHotspotChanged(float x, float y) { + super.drawableHotspotChanged(x, y); - final Drawable progressDrawable = getProgressDrawable(); - if (progressDrawable != null) { - progressDrawable.setHotspot(x, y); - } - - final Drawable thumb = mThumb; - if (thumb != null) { - thumb.setHotspot(x, y); - } - } - - @Override - public void invalidateDrawable(Drawable dr) { - super.invalidateDrawable(dr); - - if (dr == mThumb) { - // Handle changes to thumb width and height. - requestLayout(); + if (mThumb != null) { + mThumb.setHotspot(x, y); } } @@ -479,11 +464,11 @@ public abstract class AbsSeekBar extends ProgressBar { final Drawable background = getBackground(); if (background != null) { - final Rect bounds = mThumb.getBounds(); + final Rect bounds = thumb.getBounds(); final int offsetX = mPaddingLeft - mThumbOffset; final int offsetY = mPaddingTop; - background.setHotspotBounds(left + offsetX, bounds.top + offsetY, - right + offsetX, bounds.bottom + offsetY); + background.setHotspotBounds(left + offsetX, top + offsetY, + right + offsetX, bottom + offsetY); } // Canvas will be translated, so 0,0 is where we start drawing @@ -505,8 +490,8 @@ public abstract class AbsSeekBar extends ProgressBar { @Override protected synchronized void onDraw(Canvas canvas) { super.onDraw(canvas); - drawThumb(canvas); + } @Override diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java index 71137937a7f9..4aa2300c652c 100644 --- a/core/java/android/widget/CheckedTextView.java +++ b/core/java/android/widget/CheckedTextView.java @@ -307,10 +307,9 @@ public class CheckedTextView extends TextView implements Checkable { } } - /** @hide */ @Override - protected void setDrawableHotspot(float x, float y) { - super.setDrawableHotspot(x, y); + public void drawableHotspotChanged(float x, float y) { + super.drawableHotspotChanged(x, y); if (mCheckMarkDrawable != null) { mCheckMarkDrawable.setHotspot(x, y); diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java index 747d2b17bff3..9ba0fe1a55ba 100644 --- a/core/java/android/widget/CompoundButton.java +++ b/core/java/android/widget/CompoundButton.java @@ -24,7 +24,6 @@ import android.content.Context; import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.Canvas; -import android.graphics.PorterDuff.Mode; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; @@ -431,10 +430,9 @@ public abstract class CompoundButton extends Button implements Checkable { } } - /** @hide */ @Override - protected void setDrawableHotspot(float x, float y) { - super.setDrawableHotspot(x, y); + public void drawableHotspotChanged(float x, float y) { + super.drawableHotspotChanged(x, y); if (mButtonDrawable != null) { mButtonDrawable.setHotspot(x, y); diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java index 5a1492979e08..34f333ee3528 100644 --- a/core/java/android/widget/FrameLayout.java +++ b/core/java/android/widget/FrameLayout.java @@ -26,7 +26,6 @@ import android.graphics.Canvas; import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.Region; -import android.graphics.PorterDuff.Mode; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.Gravity; @@ -223,10 +222,9 @@ public class FrameLayout extends ViewGroup { } } - /** @hide */ @Override - protected void setDrawableHotspot(float x, float y) { - super.setDrawableHotspot(x, y); + public void drawableHotspotChanged(float x, float y) { + super.drawableHotspotChanged(x, y); if (mForeground != null) { mForeground.setHotspot(x, y); 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/ImageView.java b/core/java/android/widget/ImageView.java index 399e08719c12..5d578cabeddc 100644 --- a/core/java/android/widget/ImageView.java +++ b/core/java/android/widget/ImageView.java @@ -32,7 +32,6 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Xfermode; -import android.graphics.PorterDuff.Mode; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -1109,10 +1108,9 @@ public class ImageView extends View { } } - /** @hide */ @Override - protected void setDrawableHotspot(float x, float y) { - super.setDrawableHotspot(x, y); + public void drawableHotspotChanged(float x, float y) { + super.drawableHotspotChanged(x, y); if (mDrawable != null) { mDrawable.setHotspot(x, y); 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/ProgressBar.java b/core/java/android/widget/ProgressBar.java index 62a8becf6372..394b255618ce 100644 --- a/core/java/android/widget/ProgressBar.java +++ b/core/java/android/widget/ProgressBar.java @@ -1623,10 +1623,9 @@ public class ProgressBar extends View { } } - /** @hide */ @Override - protected void setDrawableHotspot(float x, float y) { - super.setDrawableHotspot(x, y); + public void drawableHotspotChanged(float x, float y) { + super.drawableHotspotChanged(x, y); if (mProgressDrawable != null) { mProgressDrawable.setHotspot(x, y); diff --git a/core/java/android/widget/QuickContactBadge.java b/core/java/android/widget/QuickContactBadge.java index 14d782da7d15..23fa402a7ae5 100644 --- a/core/java/android/widget/QuickContactBadge.java +++ b/core/java/android/widget/QuickContactBadge.java @@ -112,10 +112,9 @@ public class QuickContactBadge extends ImageView implements OnClickListener { } } - /** @hide */ @Override - protected void setDrawableHotspot(float x, float y) { - super.setDrawableHotspot(x, y); + public void drawableHotspotChanged(float x, float y) { + super.drawableHotspotChanged(x, y); if (mOverlay != null) { mOverlay.setHotspot(x, y); 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 03193a219d6d..cca29cf39db8 100644 --- a/core/java/android/widget/Switch.java +++ b/core/java/android/widget/Switch.java @@ -962,10 +962,9 @@ public class Switch extends CompoundButton { invalidate(); } - /** @hide */ @Override - protected void setDrawableHotspot(float x, float y) { - super.setDrawableHotspot(x, y); + public void drawableHotspotChanged(float x, float y) { + super.drawableHotspotChanged(x, y); if (mThumbDrawable != null) { mThumbDrawable.setHotspot(x, y); diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 0f51e8bb52ed..d470586d6e99 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -3503,10 +3503,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } - /** @hide */ @Override - protected void setDrawableHotspot(float x, float y) { - super.setDrawableHotspot(x, y); + public void drawableHotspotChanged(float x, float y) { + super.drawableHotspotChanged(x, y); final Drawables dr = mDrawables; if (dr != null) { 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/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java index 002573ebb068..97b1634f99cc 100644 --- a/core/java/com/android/internal/widget/SwipeDismissLayout.java +++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java @@ -45,10 +45,9 @@ public class SwipeDismissLayout extends FrameLayout { /** * Called when the layout has been swiped and the position of the window should change. * - * @param progress A number in [-1, 1] representing how far to the left - * or right the window has been swiped. Negative values are swipes - * left, and positives are right. - * @param translate A number in [-w, w], where w is the width of the + * @param progress A number in [0, 1] representing how far to the + * right the window has been swiped + * @param translate A number in [0, w], where w is the width of the * layout. This is equivalent to progress * layout.getWidth(). */ void onSwipeProgressChanged(SwipeDismissLayout layout, float progress, float translate); @@ -207,7 +206,7 @@ public class SwipeDismissLayout extends FrameLayout { private void setProgress(float deltaX) { mTranslationX = deltaX; - if (mProgressListener != null) { + if (mProgressListener != null && deltaX >= 0) { mProgressListener.onSwipeProgressChanged(this, deltaX / getWidth(), deltaX); } } 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_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/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp index 815c4a755f47..2b94b65d53fe 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -49,6 +49,14 @@ using namespace android::uirenderer::renderthread; static jmethodID gRunnableMethod; +static JNIEnv* getenv(JavaVM* vm) { + JNIEnv* env; + if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { + LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm); + } + return env; +} + class JavaTask : public RenderTask { public: JavaTask(JNIEnv* env, jobject jrunnable) { @@ -57,20 +65,13 @@ public: } virtual void run() { - env()->CallVoidMethod(mRunnable, gRunnableMethod); - env()->DeleteGlobalRef(mRunnable); + JNIEnv* env = getenv(mVm); + env->CallVoidMethod(mRunnable, gRunnableMethod); + env->DeleteGlobalRef(mRunnable); delete this; }; private: - JNIEnv* env() { - JNIEnv* env; - if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { - return 0; - } - return env; - } - JavaVM* mVm; jobject mRunnable; }; @@ -122,12 +123,34 @@ private: std::vector<OnFinishedEvent> mOnFinishedEvents; }; -class RootRenderNode : public RenderNode, public AnimationHook { +class RenderingException : public MessageHandler { public: - RootRenderNode() : RenderNode() { + RenderingException(JavaVM* vm, const std::string& message) + : mVm(vm) + , mMessage(message) { + } + + virtual void handleMessage(const Message&) { + throwException(mVm, mMessage); + } + + static void throwException(JavaVM* vm, const std::string& message) { + JNIEnv* env = getenv(vm); + jniThrowException(env, "java/lang/IllegalStateException", message.c_str()); + } + +private: + JavaVM* mVm; + std::string mMessage; +}; + +class RootRenderNode : public RenderNode, AnimationHook, ErrorHandler { +public: + RootRenderNode(JNIEnv* env) : RenderNode() { mLooper = Looper::getForThread(); LOG_ALWAYS_FATAL_IF(!mLooper.get(), "Must create RootRenderNode on a thread with a looper!"); + env->GetJavaVM(&mVm); } virtual ~RootRenderNode() {} @@ -137,10 +160,16 @@ public: mOnFinishedEvents.push_back(event); } + virtual void onError(const std::string& message) { + mLooper->sendMessage(new RenderingException(mVm, message), 0); + } + virtual void prepareTree(TreeInfo& info) { info.animationHook = this; + info.errorHandler = this; RenderNode::prepareTree(info); info.animationHook = NULL; + info.errorHandler = NULL; // post all the finished stuff if (mOnFinishedEvents.size()) { @@ -160,6 +189,7 @@ protected: private: sp<Looper> mLooper; std::vector<OnFinishedEvent> mOnFinishedEvents; + JavaVM* mVm; }; static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz, @@ -178,7 +208,7 @@ static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz, } static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) { - RootRenderNode* node = new RootRenderNode(); + RootRenderNode* node = new RootRenderNode(env); node->incStrong(0); node->setName("RootRenderNode"); return reinterpret_cast<jlong>(node); diff --git a/core/res/res/drawable-hdpi/ic_corp_badge.png b/core/res/res/drawable-hdpi/ic_corp_badge.png Binary files differdeleted file mode 100644 index c79ce92f98b0..000000000000 --- a/core/res/res/drawable-hdpi/ic_corp_badge.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/ic_corp_icon_badge.png b/core/res/res/drawable-hdpi/ic_corp_icon_badge.png Binary files differdeleted file mode 100644 index 0059e091cd1d..000000000000 --- a/core/res/res/drawable-hdpi/ic_corp_icon_badge.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/ic_corp_badge.png b/core/res/res/drawable-mdpi/ic_corp_badge.png Binary files differdeleted file mode 100644 index c1447fe9fb5e..000000000000 --- a/core/res/res/drawable-mdpi/ic_corp_badge.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/ic_corp_icon_badge.png b/core/res/res/drawable-mdpi/ic_corp_icon_badge.png Binary files differdeleted file mode 100644 index 5ff8c5d27733..000000000000 --- a/core/res/res/drawable-mdpi/ic_corp_icon_badge.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/ic_corp_badge.png b/core/res/res/drawable-xhdpi/ic_corp_badge.png Binary files differdeleted file mode 100644 index 2d3d748f772b..000000000000 --- a/core/res/res/drawable-xhdpi/ic_corp_badge.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/ic_corp_icon_badge.png b/core/res/res/drawable-xhdpi/ic_corp_icon_badge.png Binary files differdeleted file mode 100644 index dc5716d439d6..000000000000 --- a/core/res/res/drawable-xhdpi/ic_corp_icon_badge.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/ic_corp_badge.png b/core/res/res/drawable-xxhdpi/ic_corp_badge.png Binary files differdeleted file mode 100644 index 430e63b415fe..000000000000 --- a/core/res/res/drawable-xxhdpi/ic_corp_badge.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/ic_corp_icon_badge.png b/core/res/res/drawable-xxhdpi/ic_corp_icon_badge.png Binary files differdeleted file mode 100644 index cc00dd885b05..000000000000 --- a/core/res/res/drawable-xxhdpi/ic_corp_icon_badge.png +++ /dev/null diff --git a/core/res/res/drawable/ic_corp_badge.xml b/core/res/res/drawable/ic_corp_badge.xml new file mode 100644 index 000000000000..16c101b15c19 --- /dev/null +++ b/core/res/res/drawable/ic_corp_badge.xml @@ -0,0 +1,43 @@ +<!-- +Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + <size + android:width="20.0dp" + android:height="20.0dp"/> + + <viewport + android:viewportWidth="20.0" + android:viewportHeight="20.0"/> + + <path + android:pathData="M10.0,10.0m-10.0,0.0a10.0,10.0 0.0,1.0 1.0,20.0 0.0a10.0,10.0 0.0,1.0 1.0,-20.0 0.0" + android:fill="#FF5722"/> + <path + android:pathData="M11.139,12.149l-0.001,0.0L8.996,12.149l0.0,-0.571L4.738,11.578l-0.002,2.198c0.0,0.589 0.477,1.066 1.066,1.066l8.535,0.0c0.589,0.0 1.066,-0.477 1.066,-1.066l0.0,-2.198l-4.264,0.0L11.139,12.149z" + android:fill="#FFFFFF"/> + <path + android:pathData="M8.996,10.006l2.143,0.0l0.0,0.52l4.442,0.0L15.580999,7.909c0.0,-0.589 -0.477,-1.066 -1.066,-1.066l-1.877,0.0L7.544,6.843L5.606,6.843c-0.589,0.0 -1.061,0.477 -1.061,1.066l-0.003,2.617l4.453,0.0L8.996,10.006L8.996,10.006z" + android:fill="#FFFFFF"/> + <path + android:pathData="M3.367,3.456 h13.016 v13.016 h-13.016z" + android:fill="#00000000"/> + <path + android:pathData="M7.368,5.263l5.263,0.0l0.0,1.053l-5.263,0.0z" + android:fill="#FFFFFF"/> + <path + android:pathData="M8.996,12.149l2.1419992,0.0 0.0010004044,0.0 0.0,-0.5699997 -2.1429996,0.0z" + android:fill="#00000000"/> +</vector> diff --git a/core/res/res/drawable/ic_corp_icon_badge.xml b/core/res/res/drawable/ic_corp_icon_badge.xml new file mode 100644 index 000000000000..c8e49e1d5fa5 --- /dev/null +++ b/core/res/res/drawable/ic_corp_icon_badge.xml @@ -0,0 +1,54 @@ +<!-- +Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + <size + android:width="64.0dp" + android:height="64.0dp"/> + + <viewport + android:viewportWidth="64.0" + android:viewportHeight="64.0"/> + + <path + android:fill="#FF000000" + android:pathData="M49.062,50.0m-14.0,0.0a14.0,14.0 0.0,1.0 1.0,28.0 0.0a14.0,14.0 0.0,1.0 1.0,-28.0 0.0" + android:fillOpacity="0.2"/> + <path + android:fill="#FF000000" + android:pathData="M49.0,49.5m-14.0,0.0a14.0,14.0 0.0,1.0 1.0,28.0 0.0a14.0,14.0 0.0,1.0 1.0,-28.0 0.0" + android:fillOpacity="0.2"/> + <path + android:pathData="M49.0,49.0m-14.0,0.0a14.0,14.0 0.0,1.0 1.0,28.0 0.0a14.0,14.0 0.0,1.0 1.0,-28.0 0.0" + android:fill="#FF5722"/> + <path + android:pathData="M50.594,52.009l-3.0,0.0L47.594,51.0l-5.961,0.0l-0.003,3.289c0.0,0.826 0.668,1.494 1.494,1.494l11.948,0.0c0.826,0.0 1.494,-0.668 1.494,-1.494L56.566006,51.0l-5.972,0.0C50.594,51.0 50.594,52.009 50.594,52.009z" + android:fill="#FFFFFF"/> + <path + android:pathData="M47.594,49.009l3.0,0.0L50.594,50.0l6.22,0.0l0.0,-3.925c0.0,-0.826 -0.668,-1.494 -1.494,-1.494l-2.627,0.0l-7.131,-0.001l-2.713,0.0c-0.826,0.0 -1.486,0.668 -1.486,1.494L41.359,50.0l6.235,0.0L47.594,49.009z" + android:fill="#FFFFFF"/> + <path + android:pathData="M39.714,39.838 h18.221 v18.221 h-18.221z" + android:fill="#00000000"/> + <path + android:pathData="M47.594,49.009 h3.0 v0.991 h-3.0z" + android:fill="#00000000"/> + <path + android:pathData="M47.594,51.0 h3.0 v1.009 h-3.0z" + android:fill="#00000000"/> + <path + android:pathData="M46.0,43.0l6.0,0.0l0.0,1.0l-6.0,0.0z" + android:fill="#FFFFFF"/> +</vector> 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..f74a356f0523 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> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index a8735cb21f5a..4e06d9a03c5e 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -814,6 +814,14 @@ via adb. The default value of this attribute is <code>true</code>. --> <attr name="allowBackup" format="boolean" /> + <!-- Indicates that even though the application provides a <code>BackupAgent</code>, + only full-data streaming backup operations are to be performed to save the app's + data. This lets the app rely on full-data backups while still participating in + the backup and restore process via the BackupAgent's full-data backup APIs. + When this attribute is <code>true</code> the app's BackupAgent overrides of + the onBackup() and onRestore() callbacks can be empty stubs. --> + <attr name="fullBackupOnly" format="boolean" /> + <!-- Whether the application in question should be terminated after its settings have been restored during a full-system restore operation. Single-package restore operations will never cause the application to @@ -1060,6 +1068,7 @@ <attr name="testOnly" /> <attr name="backupAgent" /> <attr name="allowBackup" /> + <attr name="fullBackupOnly" /> <attr name="killAfterRestore" /> <attr name="restoreNeedsApplication" /> <attr name="restoreAnyVersion" /> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index a4f78bdfd02d..d350ef2964b5 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1464,7 +1464,7 @@ <!-- Name of the CustomDialog that is used for VPN --> <string name="config_customVpnConfirmDialogComponent" - >com.android.vpndialogs/com.android.vpndialogs.CustomDialog</string> + >com.android.vpndialogs/com.android.vpndialogs.ConfirmDialog</string> <!-- Apps that are authorized to access shared accounts, overridden by product overlays --> <string name="config_appsAuthorizedForSharedAccounts">;com.android.settings;</string> @@ -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/ids.xml b/core/res/res/values/ids.xml index 639091e14284..c64e910e955d 100644 --- a/core/res/res/values/ids.xml +++ b/core/res/res/values/ids.xml @@ -84,4 +84,5 @@ <item type="id" name="current_scene" /> <item type="id" name="scene_layoutid_cache" /> <item type="id" name="mask" /> + <item type="id" name="transitionPosition" /> </resources> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index c5ce2292bde5..f73c9586788f 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2206,6 +2206,9 @@ <public type="attr" name="buttonTintMode" /> <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-padding type="dimen" name="l_resource_pad" end="0x01050010" /> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index e31dbaf08009..c8c0d236bdd6 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -4728,6 +4728,13 @@ <!-- Accessibility announcement when a number that had been typed in is deleted [CHAR_LIMIT=NONE] --> <string name="deleted_key"><xliff:g id="key" example="4">%1$s</xliff:g> deleted</string> + <!-- + Used to wrap a label for content description for a managed profile, e.g. "Work Email" instead + of email when there are two email apps. + [CHAR LIMIT=20] + --> + <string name="managed_profile_label_badge">Work <xliff:g id="label" example="Email">%1$s</xliff:g></string> + <!-- DO NOT TRANSLATE --> <string name="time_placeholder">--</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 5f4553b49eac..7a871cc75f5f 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -218,6 +218,7 @@ <java-symbol type="id" name="pin_error_message" /> <java-symbol type="id" name="timePickerLayout" /> <java-symbol type="id" name="profile_icon" /> + <java-symbol type="id" name="transitionPosition" /> <java-symbol type="attr" name="actionModeShareDrawable" /> <java-symbol type="attr" name="alertDialogCenterButtons" /> @@ -863,6 +864,7 @@ <java-symbol type="string" name="action_bar_home_description_format" /> <java-symbol type="string" name="action_bar_home_subtitle_description_format" /> <java-symbol type="string" name="wireless_display_route_description" /> + <java-symbol type="string" name="managed_profile_label_badge" /> <java-symbol type="string" name="mediasize_unknown_portrait" /> <java-symbol type="string" name="mediasize_unknown_landscape" /> <java-symbol type="string" name="mediasize_iso_a0" /> @@ -1000,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/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java index 7251e7c3fa77..7f41ac1c5328 100644 --- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java +++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java @@ -305,11 +305,9 @@ public class PackageManagerTests extends AndroidTestCase { private PackageParser.Package parsePackage(Uri packageURI) throws PackageParserException { final String archiveFilePath = packageURI.getPath(); - PackageParser packageParser = new PackageParser(archiveFilePath); + PackageParser packageParser = new PackageParser(); File sourceFile = new File(archiveFilePath); - DisplayMetrics metrics = new DisplayMetrics(); - metrics.setToDefaults(); - PackageParser.Package pkg = packageParser.parseMonolithicPackage(sourceFile, metrics, 0); + PackageParser.Package pkg = packageParser.parseMonolithicPackage(sourceFile, 0); packageParser = null; return pkg; } 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/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml index 1eaae657e7eb..37e9b157e750 100644 --- a/data/fonts/fallback_fonts.xml +++ b/data/fonts/fallback_fonts.xml @@ -219,6 +219,21 @@ </family> <family> <fileset> + <file>NotoSansCherokee-Regular.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>NotoSansCanadianAboriginal-Regular.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>NotoSansYi-Regular.ttf</file> + </fileset> + </family> + <family> + <fileset> <file lang="zh-CN">NotoSansHans-Regular.otf</file> </fileset> </family> diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd index b648d482325c..c4d5083175d8 100644 --- a/docs/html/guide/topics/manifest/activity-element.jd +++ b/docs/html/guide/topics/manifest/activity-element.jd @@ -5,7 +5,8 @@ parent.link=manifest-intro.html <dl class="xml"> <dt>syntax:</dt> -<dd><pre class="stx"><activity android:<a href="#reparent">allowTaskReparenting</a>=["true" | "false"] +<dd><pre class="stx"><activity android:<a href="#embedded">allowEmbedded</a>=["true" | "false"] + android:<a href="#reparent">allowTaskReparenting</a>=["true" | "false"] android:<a href="#always">alwaysRetainTaskState</a>=["true" | "false"] android:<a href="#clear">clearTaskOnLaunch</a>=["true" | "false"] android:<a href="#config">configChanges</a>=["mcc", "mnc", "locale", @@ -62,6 +63,17 @@ by the system and will never be run. <dt>attributes:</dt> <dd><dl class="attr"> +<dt><a name="embedded"></a>{@code android:allowEmbedded}</dt> +<dd> + Indicate that the activity can be launched as the embedded child of another + activity. Particularly in the case where the child lives in a container + such as a Display owned by another activity. For example, activities + that are used for Wear custom notifications must declare this so + Wear can display the activity in it's context stream, which resides + in another process. + + <p>The default value of this attribute is <code>false</code>. +</dd> <dt><a name="reparent"></a>{@code android:allowTaskReparenting}</dt> <dd>Whether or not the activity can move from the task that started it to the task it has an affinity for when that task is next brought to the diff --git a/docs/html/images/tools/android-studio.png b/docs/html/images/tools/android-studio.png Binary files differdeleted file mode 100644 index 4d93a86677fb..000000000000 --- a/docs/html/images/tools/android-studio.png +++ /dev/null diff --git a/docs/html/images/tools/laptop-studio.png b/docs/html/images/tools/laptop-studio.png Binary files differnew file mode 100644 index 000000000000..3684ff07f85c --- /dev/null +++ b/docs/html/images/tools/laptop-studio.png diff --git a/docs/html/jd_extras.js b/docs/html/jd_extras.js index d8db5bf5de84..2f63700074c4 100644 --- a/docs/html/jd_extras.js +++ b/docs/html/jd_extras.js @@ -15,6 +15,17 @@ DISTRIBUTE_RESOURCES = DISTRIBUTE_RESOURCES.concat([ { + "title":"Android L Developer Preview", + "titleFriendly":"", + "summary":"<p style='font-size:18px;'>Get an early look at the next release and get your apps ready when the platform officially launches.</p>", + "url":"preview/index.html", + "group":"", + "keywords": [], + "tags": [], + "image":"preview/images/l-dev-prev.png", + "type":"" + }, + { "title":"Developer Registration", "titleFriendly":"", "summary":"Additional information about the registration process.", diff --git a/docs/html/preview/api-overview.jd b/docs/html/preview/api-overview.jd index 2fa029fb9029..8ec24708511d 100644 --- a/docs/html/preview/api-overview.jd +++ b/docs/html/preview/api-overview.jd @@ -18,7 +18,6 @@ sdk.platform.apiLevel=20 <li><a href="#ART">New Android Runtime (ART)</a></li> <li><a href="#BehaviorNotifications">If your app implements notifications...</a></li> <li><a href="#BehaviorMediaControl">If your app uses RemoteControlClient...</a></li> - <li><a href="#BehaviorFullscreen">If your app uses fullScreenIntent...</a></li> <li><a href="#BehaviorGetRecentTasks">If your app uses ActivityManager.getRecentTasks()...</a></li> </ol> </li> @@ -64,12 +63,13 @@ sdk.platform.apiLevel=20 <li><a href="#Power">Power Efficiency</a> <ol> <li><a href="#JobScheduler">Scheduling Jobs</a></li> - <li><a href="#PowerMeasurementTools">Developer tools and APIs for power measurement</a> + <li><a href="#PowerMeasurementTools">Developer tools for power measurement</a> </ol> </li> <li><a href="#Enterprise">Enterprise</a> <ol> <li><a href="#ManagedProvisioning">Managed provisioning</a></li> + <li><a href="#LockToAppMode">Lock-to-App mode</a></li> </ol> </li> <li><a href="#Printing">Printing Framework</a> @@ -99,15 +99,15 @@ Differences Report »</a> </li> </div> </div> -<p>The L Developer Preview gives you an advance look at the upcoming release for -the Android platform, -which offers new features for users and app developers. This document provides -an introduction to the most notable APIs.</p> +<p>The L Developer Preview gives you an advance look at the upcoming release +for the Android platform, which offers new features for users and app +developers. This document provides an introduction to the most notable APIs.</p> -<p>The L Developer Preview is intended for <strong>developer early adopters</strong> and -<strong>testers</strong>. If you are interested in influencing the direction of the -Android framework, <a href="{@docRoot}preview/setup-sdk.html">give the L -Developer Preview a try</a> and send us your feedback!</p> +<p>The L Developer Preview is intended for <strong>developer early +adopters</strong> and <strong>testers</strong>. If you are interested in +influencing the direction of the Android framework, +<a href="{@docRoot}preview/setup-sdk.html">give the L Developer Preview a +try</a> and send us your feedback!</p> <p class="caution"><strong>Caution:</strong> Do not not publish apps that use the L Developer Preview to the Google Play store.</p> @@ -128,8 +128,8 @@ reference</a>.</p> <h3 id="ART">New Android Runtime (ART)</h3> <p>The 4.4 release introduced a new, experimental Android runtime, ART. Under -4.4, ART was optional, and the default runtime remained Dalvik. With the L Developer Preview, ART is -now the default runtime.</p> +4.4, ART was optional, and the default runtime remained Dalvik. With the L +Developer Preview, ART is now the default runtime.</p> <p>For an overview of ART's new features, see <a href="https://source.android.com/devices/tech/dalvik/art.html">Introducing @@ -163,6 +163,15 @@ Behavior on the Android Runtime (ART)</a>. Pay particular attention if:</p> backgrounds to match the new material design widgets. Make sure that all your notifications look right with the new color scheme:</p> +<div class="figure" style="width:220px"> + <img src="images/hun-example.png" + srcset="images/hun-example@2x.png 2x" + alt="" width="220" height="372" id="figure1" /> + <p class="img-caption"> + <strong>Figure 1.</strong> Fullscreen activity showing a heads-up notification + </p> +</div> + <ul> <li>Update or remove assets that involve color.</li> @@ -179,39 +188,48 @@ notifications look right with the new color scheme:</p> <p>If you are currently adding sounds and vibrations to your notifications by using the {@link android.media.Ringtone}, {@link android.media.MediaPlayer}, or {@link android.os.Vibrator} classes, remove this code so that -the system can present notifications correctly in <a href="#DoNotDisturb">Do Not Disturb</a> mode. -Instead, use the {@link android.app.Notification.Builder} methods instead to add -sounds and vibration.</p> +the system can present notifications correctly in <a href="#DoNotDisturb">Do Not Disturb</a> mode. Instead, use the {@link android.app.Notification.Builder} methods instead to add sounds and vibration.</p> + +<p>Notifications now appear in a small floating window +(also called a <em>heads-up notification</em>) when the device is active +(that is, the device is unlocked and its screen is on). These notifications +appear similar to the compact form of your notification, except that the +heads-up notification also shows action buttons. Users can act on, or dismiss, +a heads-up notification without leaving the current app.</p> + +<p>Examples of conditions that may trigger heads-up notifications include:</p> + +<ul> + <li>The user's activity is in fullscreen mode (the app uses +{@link android.app.Notification#fullScreenIntent}), or</li> + <li>The notification has high priority and uses ringtones or + vibrations</li> +</ul> + +<p>If your app implements notifications under those scenarios, make sure that +heads-up notifications are presented correctly.</p> <h3 id="BehaviorMediaControl">If your app uses RemoteControlClient...</h3> -<p>Lockscreens in the L Developer Preview do not show transport controls for your -{@link android.media.RemoteControlClient}. Instead, your app can provide -media playback control from the lockscreen through a media notification. This +<p>Lockscreens in the L Developer Preview do not show transport controls for +your {@link android.media.RemoteControlClient}. Instead, your app can provide +media playback control from the lockscreen through a notification. This gives your app more control over the presentation of media buttons, while providing a consistent experience for users across the lockscreen and unlocked device.</p> +<p>The L Developer Preview introduces a new {@code android.app.Notification.MediaStyle} template which is recommended for this purpose. {@code MediaStyle} converts notification actions that you added with {@link android.app.Notification.Builder#addAction(int, java.lang.CharSequence, android.app.PendingIntent) Notification.Builder.addAction()} into compact buttons embedded in your app's media playback notifications.</p> + +<p>If you are using the new +{@code android.media.session.MediaSession} class (see <a href="#MediaPlaybackControl">Media Playback Control</a> below), attach your session +token with {@code Notification.MediaStyle.setMediaToken()} to inform the +system that this notification controls an ongoing media session.</p> + <p>Call {@code Notification.Builder.setVisibility(Notification.VISIBILITY_PUBLIC)} to mark a -notification as safe to display on the lockscreen (even when the lockscreen is -secured with a PIN, pattern, or password). For more information, see +notification as safe to show atop any lockscreen (secure or otherwise). For more information, see <a href="#LockscreenNotifications">Lockscreen Notifications</a>.</p> -<h3 id="BehaviorFullscreen">If your app uses fullScreenIntent...</h3> - -<p>Notifications now appear in a small floating window if all these conditions -are met:</p> - -<ul> - <li>The user’s activity is in fullscreen mode,</li> - <li>The screen is on, and</li> - <li>The device is unlocked</li> -</ul> - -<p>If your app implements fullscreen activities, make sure that -these heads-up notifications are presented correctly.</p> - <h3 id="BehaviorGetRecentTasks">If your app uses ActivityManager.getRecentTasks()...</h3> <p>With the introduction of the new <em>concurrent documents and activities tasks</em> feature in the upcoming @@ -230,7 +248,6 @@ information.</p> <h3 id="MaterialDesign">Material design support</h3> - <p>The upcoming release adds support for Android's new <em>material</em> design style. You can create apps with material design that are visually dynamic and have UI element transitions @@ -262,16 +279,17 @@ values:</p> <ul> <li>{@code VISIBILITY_PRIVATE}. Shows basic information, such as the -notification’s icon, but hides the notification’s full content. If you want to -provide a redacted public version of your notification for the system to display -on a secure lockscreen, create a public notification object and put a reference -to it in the private notification's {@code publicVersion} field.</li> -<li>{@code VISIBILITY_PUBLIC}. Shows the notification’s full content. This is - the system default if visibility is left unspecified.</li> -<li>{@code VISIBILITY_SECRET}. Shows only the most minimal information, -excluding even the notification’s icon.</li> +notification’s icon, but hides the notification’s full content.</li> +<li>{@code VISIBILITY_PUBLIC}. Shows the notification’s full content.</li> +<li>{@code VISIBILITY_SECRET}. Shows nothing, excluding even the +notification’s icon.</li> </ul> +<p>When {@code VISIBILITY_PRIVATE} is set, you can also provide a redacted +version of the notification content that hides personal details. For example, +an SMS app might display a notification that shows "You have 3 new text messages." but hides the message content and senders. To provide this alternative notification, first create the replacement notification using {@link android.app.Notification.Builder}. When you create the private notification object, attach +the replacement notification to it through the {@code Notification.Builder.setPublicVersion()} method.</p> + <h3 id="DoNotDisturb">Do Not Disturb mode</h3> <p>The L Developer Preview introduces a new <em>Do Not Disturb</em> mode. When @@ -295,7 +313,7 @@ make sure <em>Do Not Disturb</em> mode handles them properly. For example, if your app is an alarm clock, you can tag the notification as an alarm so it will wake the user up even if the device is in <em>Do Not Disturb</em> mode. For more information, see <a -href="NotificationsMetadata">Notifications metadata</a>.</p> +href="#NotificationsMetadata">Notifications metadata</a>.</p> <h3 id="NotificationsMetadata">Notifications metadata</h3> <p>The L Developer Preview uses metadata associated with your app notifications @@ -483,10 +501,9 @@ knows about your playback and can extract and show album art.</p> <h3 id="DirectorySelection">Directory selection</h3> -<p>The L Developer Preview extends the <a href="{@docRoot}guide/topics/providers/document-provider.html">Storage Access Framework</a> to let users -select an entire directory, rather than individual files, to give your app -read/write access to media files. When a directory is selected, your app also -has access to all its child directories and content.</p> +<p>The L Developer Preview extends the <a href="{@docRoot}guide/topics/providers/document-provider.html">Storage Access Framework</a> to let users select an entire directory, rather than individual files, to +give your app read/write access to media files. When a directory is selected, +your app also has access to all its child directories and content.</p> <p>To get the absolute paths to directories on external storage devices where applications can store media files, call the new @@ -498,6 +515,13 @@ considers to be a permanent part of the device, and includes emulated external storage and physical media slots such as SD cards in battery compartments.</p> +<p>You can bring up a system UI to allow the user to pick a directory subtree. +To do so, send {@code android.intent.action.OPEN_DOCUMENT_TREE} in an +{@link android.content.Intent}. If the call is successful, the system displays +the {@link android.provider.DocumentsProvider} instances installed on the +device for the user to select. When the user selects a directory from this UI, +the system returns a URI representing the selected directory tree.</p> + <p>If you want to access a document in an existing directory, call the {@code android.provider.DocumentsContract.buildDocumentViaUri()} method. Pass the method a URI representing the path to the parent directory, and the @@ -591,9 +615,9 @@ API that lets you optimize battery life by defining jobs for the system to run asynchronously at a later time or under specified conditions (such as when the device is charging). This is useful in such situations as:</p> <ul> - <li>The app has non-user-facing work that you want to defer until the unit is - plugged in.</li> - <li>The app has a task that requires network access (or requires a wifi + <li>The app has non-user-facing work that you can defer.</li> + <li>The app has work you'd prefer to do when the unit is plugged in.</li> + <li>The app has a task that requires network access (or requires a Wi-Fi connection).</li> <li>The app has a number of tasks that you want to run as a batch on a regular schedule.</li> @@ -612,6 +636,7 @@ conditions, such as:</p> <li>The device is charging</li> <li>The device is connected to an unmetered network</li> <li>The system deems the device to be idle</li> + <li>Completion with a minimum delay or within a specific deadline.</li> </ul> <p>For example, you can add code like this to run your task on an @@ -627,7 +652,7 @@ JobScheduler jobScheduler = jobScheduler.schedule(uploadTask); </pre> -<h3 id="PowerMeasurementTools">Developer tools and APIs for power measurement</h3> +<h3 id="PowerMeasurementTools">Developer tools for power measurement</h3> <p>The L Developer Preview provides several new developer tools and APIs to help you better measure and understand your app's power usage.</p> @@ -668,9 +693,9 @@ in {@code <sdk>/tools}.</p> <img src="images/battery_historian.png" srcset="images/battery_historian@2x.png 2x" alt="" width="440" height="240" - id="figure1" /> + id="figure2" /> <p class="img-caption"> - <strong>Figure 1.</strong>HTML visualization generated by the Battery + <strong>Figure 2.</strong>HTML visualization generated by the Battery Historian tool. </p> @@ -701,9 +726,9 @@ $ historian.par [-p powerfile] bugreport.txt > out.html <div class="figure" style="width:360px"> <img src="images/managed_apps_launcher.png" srcset="images/managed_apps_launcher@2x.png 2x" - alt="" width="360" height="572" id="figure2" /> + alt="" width="360" height="572" id="figure3" /> <p class="img-caption"> - <strong>Figure 2.</strong> Launcher screen showing managed apps (marked with + <strong>Figure 3.</strong> Launcher screen showing managed apps (marked with a lock badge) </p> </div> @@ -742,6 +767,36 @@ for the current user and any associated managed profiles. Your Launcher can make the managed apps visually prominent by appending a “work” badge to the icon drawable with {@code android.os.UserManager.getBadgeDrawableForUser()}.</p> +<h3 id="LockToAppMode">Lock-to-App mode</h3> +<p>The L Developer Preview introduces a new <em>Lock-to-App</em> mode that +lets you temporarily restrict users from leaving your app or being interrupted +by notifications. Once your app activates this mode, users will not be able to +see notifications, access other apps, or return to the Home screen, until your +app exits the mode.</p> + +<p>To prevent unauthorized usage, the device on which you want to activate +this mode must have managed profiles or must be fully controlled by a device administrator (see <a href="#ManagedProvisioning">Managed Provisioning</a> for more information). Furthermore, the device or managed profile owner must +authorize apps to use this mode by calling {@code android.app.admin.DevicePolicyManager.setLockTaskComponents()}.</p> + +<p>Before activating this mode in your app, verify that your activity is authorized by calling {@code DevicePolicyManager.isLockTaskPermitted()}.</p> + +<p>To activate <em>Lock-to-App</em> mode, call +{@code android.app.Activity.startLockTask()} from your authorized activity.</p> + +<p>When <em>Lock-to-App</em> mode is active, the following behavior takes +effect:</p> + +<ul> +<li>The status bar is blank, and user notifications and status information is hidden.</li> +<li>The Home and Recent Apps button is hidden.</li> +<li>Other apps may not launch new activities.</li> +<li>The current app may start new activities, as long as doing so does not +create new tasks.</li> +</ul> + +<p>The device will remain in this mode until an authorized activity calls +{@code Activity.stopLockTask()}. + <h2 id="Printing">Printing Framework</h2> <h3 id="PDFRender">Render PDF as bitmap</h3> @@ -752,7 +807,7 @@ accessed) on which the system writes the the printable content. Your app can obtain a page for rendering with {@code openPage()}, then call {@code render()} to turn the opened {@code PdfRenderer.Page} into a bitmap. You can also set additional parameters if you only want to convert a portion of the document into -a bitmap image (for example, to implement <a href="http://en.wikipedia.org/wiki/Tiled_rendering">tile rendering</a> in order to zoom in on the document).</p> +a bitmap image (for example, to implement <a href="http://en.wikipedia.org/wiki/Tiled_rendering">tiled rendering</a> in order to zoom in on the document).</p> <h2 id="TestingA11y">Testing & Accessibility </h2> @@ -796,8 +851,7 @@ your app needs.</p> <ul> <li>{@code FEATURE_LEANBACK}. Declares that your app must be installed only on -devices that support the <a href="{@docRoot}training/tv}">Android TV</a> user -interface. Example: +devices that support the <a href="{@docRoot}training/tv/index.html}">Android TV</a>user interface. Example: <pre> <uses-feature android:name="android.software.leanback" android:required="true" /> diff --git a/docs/html/preview/images/hun-example.png b/docs/html/preview/images/hun-example.png Binary files differnew file mode 100644 index 000000000000..9613a928ec71 --- /dev/null +++ b/docs/html/preview/images/hun-example.png diff --git a/docs/html/preview/images/hun-example@2x.png b/docs/html/preview/images/hun-example@2x.png Binary files differnew file mode 100644 index 000000000000..3cb8f5b3dea0 --- /dev/null +++ b/docs/html/preview/images/hun-example@2x.png diff --git a/docs/html/preview/images/l-dev-prev.png b/docs/html/preview/images/l-dev-prev.png Binary files differnew file mode 100644 index 000000000000..95bad8c4becc --- /dev/null +++ b/docs/html/preview/images/l-dev-prev.png diff --git a/docs/html/preview/images/managed_apps_launcher@2.png b/docs/html/preview/images/managed_apps_launcher@2x.png Binary files differindex d298fd2deb28..d298fd2deb28 100644 --- a/docs/html/preview/images/managed_apps_launcher@2.png +++ b/docs/html/preview/images/managed_apps_launcher@2x.png diff --git a/docs/html/preview/index.jd b/docs/html/preview/index.html index e44e9f30a0d1..368db843209b 100644 --- a/docs/html/preview/index.jd +++ b/docs/html/preview/index.html @@ -1,13 +1,143 @@ -page.title=Android L Developer Preview -page.viewport_width=970 -fullpage=true -no_footer_links=true -page.type=about -page.metaDescription=Test and build your apps against the next version of Android to ensure they're ready when the platform officially launches. -page.image={@docRoot}preview/images/hero.jpg -@jd:body +<!DOCTYPE html> -<style> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<html> +<head> + + +<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> +<meta name="viewport" content="width=970" /> + +<meta name="Description" content="Test and build your apps against the next version of Android to ensure they're ready when the platform officially launches."> +<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" /> +<title>Android L Developer Preview | Android Developers</title> + +<!-- STYLESHEETS --> +<link rel="stylesheet" +href="//fonts.googleapis.com/css?family=Roboto+Condensed"> +<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" + title="roboto"> +<link href="/assets/css/default.css" rel="stylesheet" type="text/css"> + + + +<!-- JAVASCRIPT --> +<script src="//www.google.com/jsapi" type="text/javascript"></script> +<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script> +<script type="text/javascript"> + var toRoot = "/"; + var metaTags = []; + var devsite = false; +</script> +<script src="/assets/js/docs.js" type="text/javascript"></script> + +<script> + (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ + (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), + m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) + })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); + + ga('create', 'UA-5831155-1', 'android.com'); + ga('create', 'UA-49880327-2', 'android.com', {'name': 'universal'}); // New tracker); + ga('send', 'pageview'); + ga('universal.send', 'pageview'); // Send page view for new tracker. +</script> + +</head> + +<body class="gc-documentation + +" itemscope itemtype="http://schema.org/Article"> + + +<a name="top"></a> +<div id="body-content"> +<div class="fullpage" > +<div id="jd-content"> + <div class="jd-descr" itemprop="articleBody"> + <style> .fullpage>#footer, #jd-content>.content-footer.wrap { display:none; @@ -23,61 +153,36 @@ page.image={@docRoot}preview/images/hero.jpg } </style> -<div class="landing-body-content"> - <div class="landing-hero-container"> - <div class="landing-section preview-hero"> - <div class="landing-hero-scrim"></div> - <div class="landing-hero-wrap"> - <div class="vertical-center-outer"> - <div class="vertical-center-inner"> - - <div class="col-12"> - <div class="landing-section-header"> - - <div class="landing-h1 hero">L Developer Preview</div> - <div class="landing-subhead hero"> - <p>An early look at the next release</p> - </div> - <div class="landing-hero-description"> - <p>Test and build your apps against the next<br /> - version of Android to ensure they're ready<br/> - when the platform officially launches.</p> - </div> - - <div class="landing-body"> - <a href="/preview/setup-sdk.html" class="landing-button landing-primary" style="margin-top: 40px;"> - Get Started - </a> - </div> - </div> - - </div> - </div> - </div> <!-- end .wrap --> - <div class="landing-scroll-down-affordance"> - <a class="landing-down-arrow" href="#extending-android-to-landingables"> - <img src="/wear/images/carrot.png" alt="Scroll down to read more"> - </a> - </div> - </div> <!-- end .landing-section .landing-hero --> - </div> <!-- end .landing-hero-container --> - - <div class="landing-rest-of-page"> - <div class="landing-section" id="extending-android-to-landingables"> + <div class="landing-section" style="padding-top:30px"> <div class="wrap"> <div class="landing-section-header"> - <div class="landing-h1">See What's New</div> + <div class="landing-h1">Android L Developer Preview</div> <div class="landing-subhead"> - Take advantage of all the new capabilities, which are focused on design and performance. + Get an early look at the next release and get your apps ready when the + platform officially launches. + </div> + + <img src="/preview/images/l-dev-prev.png" style=" margin:10px 0 0 100px" width="700px"/> + <div class="col-6" style="margin-left:630px; margin-top:-40px"> + <a href="/preview/setup-sdk.html" class="landing-button landing-secondary" style="position:absolute;z-index:100;float:right;margin-top: 0px; background-color:#09c">Get Started</a><!-- + <p>Set up your environment and check out all the docs to get up and running.</p>--> + + </div> </div> + </div> <!-- end .wrap --> + </div> <!-- end .landing-section --> - <div class="landing-body"> + + +<div class="landing-section landing-gray-background" style="margin-top:-80px; padding-bottom:20px"> + <div class="wrap"> + <div class="cols"> +<div class="landing-body" style="margin-top:-80px" > <div class="landing-breakout cols"> <div class="col-4"> - <img src="/preview/images/material.png" style="opacity:.6" alt=""> <p>A New UI Design</p> <p class="landing-small"> Create a consistent experience across mobile and the web with @@ -88,19 +193,16 @@ page.image={@docRoot}preview/images/hero.jpg </p> </div> <div class="col-4"> - <img src="/preview/images/art.png" alt=""> <p>A Rehauled Runtime</p> <p class="landing-small"> Test your apps and get them ready for <b>ART</b> (<b>A</b>ndroid <b>R</b>un<b>t</b>ime), the default runtime in the next release. - </p> <p class="landing-small"> <a href="/preview/api-overview.html#ART">Learn about ART</a> </p> </div> <div class="col-4"> - <img src="/preview/images/notifications.png" alt=""> <p style="width:230px">Enhanced Notifications</p> <p class="landing-small"> Get more control over where notifications appear, @@ -111,7 +213,6 @@ page.image={@docRoot}preview/images/hero.jpg </p> </div> <div class="col-4"> - <img src="/preview/images/volta.png" alt=""> <p>Project Volta</p> <p class="landing-small"> We've tuned the platform to be more energy efficient and @@ -122,44 +223,17 @@ page.image={@docRoot}preview/images/hero.jpg </p> </div> </div> - <p>See the <a href="{@docRoot}preview/api-overview.html">API overview</a> for more information + <p style="margin-left:20px">See the <a href="/preview/api-overview.html">API overview</a> for more information on the rest of the new and updated features.</p> </div> - </div> <!-- end .wrap --> - </div> <!-- end .landing-section --> - - - - <div class="landing-section landing-gray-background"> - <div class="wrap"> - <div class="landing-section-header"> - <div class="landing-h1">Get Your Apps Ready</div> - <div class="landing-subhead"> - <p>We're giving you an early look at the SDK, so you can test your apps and build in new features.</p> - </div> - </div> - <div class="landing-body"> - <p>You'll get the system images for the Nexus 5, Nexus 7 (v2), - and the emulator to take the new platform for a spin. In addition, you'll have - access to all the APIs with a preview build of the SDK. - </p> - - <p>Check out the getting started, developer guides, and reference documentation - for all the information you need to get up and running.</p> - - <a href="/preview/setup-sdk.html" class="landing-button landing-secondary" style="margin-top: 20px;"> - Get Started - </a> - </div> - </div> - </div> + </div></div></div> <div class="landing-section"> <div class="wrap"> <div class="cols"> <div class="landing-body"> <div class="col-3-wide"> - <a target="_blank" href="http://submit-bugs!"> - <img class="landing-social-image" src="{@docRoot}preview/images/bugs.png" alt=""> + <a target="_blank" href="https://code.google.com/p/android-developer-preview/"> + <img class="landing-social-image" src="/preview/images/bugs.png" alt=""> </a> <div class="landing-social-copy"> <p>Issue Tracker</p> @@ -167,7 +241,7 @@ page.image={@docRoot}preview/images/hero.jpg Let us know when you encounter problems, so we can fix them and make the platform better for you and your users. </p><p class="landing-small"> - <a target="_blank" href="http://submit-bugs!"> + <a target="_blank" href="https://code.google.com/p/android-developer-preview/"> Report Issues</a> </p> <p></p> @@ -189,8 +263,8 @@ page.image={@docRoot}preview/images/hero.jpg </div> </div> <div class="col-3-wide"> - <a target="_blank" href="{@docRoot}preview/release-notes.html"> - <img class="landing-social-image" src="{@docRoot}preview/images/updates.png" alt=""> + <a target="_blank" href="/preview/support.html"> + <img class="landing-social-image" src="/preview/images/updates.png" alt=""> </a> <div class="landing-social-copy"> <p>Support and Updates</p> @@ -200,13 +274,13 @@ page.image={@docRoot}preview/images/hero.jpg for news about the changes. </p> <p class="landing-small"> - <a target="_blank" href="{@docRoot}preview/support.html">Get Support</a> + <a target="_blank" href="/preview/support.html">Get Support</a> </p> </div> </div> </div> </div> - </div> <!-- end .wrap --> + </div> </div> <div class="content-footer wrap" itemscope="" itemtype="http://schema.org/SiteNavigationElement"> @@ -233,4 +307,55 @@ page.image={@docRoot}preview/images/hero.jpg }, 1000, "easeOutQuint"); e.preventDefault(); }); - </script>
\ No newline at end of file + </script> + </div> + + <div class="content-footer wrap" + itemscope itemtype="http://schema.org/SiteNavigationElement"> + + <div class="paging-links layout-content-col col-10"> + + </div> + <div class="layout-content-col plus-container col-2" > + <style>#___plusone_0 {float:right !important;}</style> + <div class="g-plusone" data-size="medium"></div> + + </div> + + </div> + + + + + </div> <!-- end jd-content --> + +<div id="footer" class="wrap" style="width:940px"> + + + <div id="copyright"> + + Except as noted, this content is + licensed under <a href="http://creativecommons.org/licenses/by/2.5/"> + Creative Commons Attribution 2.5</a>. For details and + restrictions, see the <a href="/license.html">Content + License</a>. + </div> + + +</div> <!-- end footer --> +</div><!-- end doc-content --> + +</div> <!-- end body-content --> + + + + + + <script src="https://developer.android.com/ytblogger_lists_unified.js" type="text/javascript"></script> + <script src="/jd_lists_unified.js" type="text/javascript"></script> + <script src="/jd_extras.js" type="text/javascript"></script> + <script src="/jd_collections.js" type="text/javascript"></script> + <script src="/jd_tag_helpers.js" type="text/javascript"></script> + +</body> +</html>
\ No newline at end of file diff --git a/docs/html/sdk/installing/studio.jd b/docs/html/sdk/installing/studio.jd index 8ac61638b0a4..894514a70c9a 100644 --- a/docs/html/sdk/installing/studio.jd +++ b/docs/html/sdk/installing/studio.jd @@ -186,7 +186,7 @@ This is the Android Software Development Kit License Agreement <div id="main"> <div class="figure" style="width:400px;margin-top:-75px"> -<img src="{@docRoot}images/tools/android-studio.png" height="330" width="400" style="margin-bottom:20px" /> +<img src="{@docRoot}images/tools/laptop-studio.png" height="366" width="400" style="margin-bottom:20px" /> <a class="big button subtitle" id="download-ide-button" href="" style="display:none;width:368px;margin:0 auto;display:block;font-size:18px" ></a> @@ -218,7 +218,7 @@ capabilities you expect from IntelliJ, Android Studio offers:</p> <li>Lint tools to catch performance, usability, version compatibility, and other problems.</li> <li>ProGuard and app-signing capabilities.</li> <li>Built-in support for <a - href="http://android-developers.blogspot.com/2013/06/adding-backend-to-your-app-in-android.html" + href="https://developers.google.com/cloud/devtools/android_studio_templates/" class="external-link">Google Cloud Platform</a>, making it easy to integrate Google Cloud Messaging and App Engine. </ul> 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/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index 8be6eb745c09..38b8aafe824d 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -65,8 +65,6 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { private long mExitAnimationEnd; private Drawable mLastDrawable; - private Insets mInsets = Insets.NONE; - // overrides from Drawable @Override @@ -118,7 +116,10 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { */ @Override public Insets getOpticalInsets() { - return mInsets; + if (mCurrDrawable != null) { + return mCurrDrawable.getOpticalInsets(); + } + return Insets.NONE; } @Override @@ -203,9 +204,6 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { } if (mCurrDrawable != null) { mCurrDrawable.setBounds(bounds); - - // Must obtain optical insets after setting bounds. - mInsets = mCurrDrawable.getOpticalInsets(); } } @@ -422,15 +420,9 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { d.setBounds(getBounds()); d.setLayoutDirection(getLayoutDirection()); d.setAutoMirrored(mDrawableContainerState.mAutoMirrored); - - // Must obtain optical insets after setting bounds. - mInsets = d.getOpticalInsets(); - } else { - mInsets = Insets.NONE; } } else { mCurrDrawable = null; - mInsets = Insets.NONE; mCurIndex = -1; } diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java index 345400e399da..2d4936582a4a 100644 --- a/graphics/java/android/graphics/drawable/Ripple.java +++ b/graphics/java/android/graphics/drawable/Ripple.java @@ -142,14 +142,16 @@ class Ripple { } private void clampStartingPosition() { - final float dX = mStartingX - mBounds.exactCenterX(); - final float dY = mStartingY - mBounds.exactCenterY(); + final float cX = mBounds.exactCenterX(); + final float cY = mBounds.exactCenterY(); + final float dX = mStartingX - cX; + final float dY = mStartingY - cY; final float r = mOuterRadius; if (dX * dX + dY * dY > r * r) { // Point is outside the circle, clamp to the circumference. final double angle = Math.atan2(dY, dX); - mClampedStartingX = (float) (Math.cos(angle) * r); - mClampedStartingY = (float) (Math.sin(angle) * r); + mClampedStartingX = cX + (float) (Math.cos(angle) * r); + mClampedStartingY = cY + (float) (Math.sin(angle) * r); } else { mClampedStartingX = mStartingX; mClampedStartingY = mStartingY; 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/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/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java index 9d6d76e37118..0da2b9989444 100644 --- a/keystore/java/android/security/KeyChain.java +++ b/keystore/java/android/security/KeyChain.java @@ -23,7 +23,9 @@ import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.os.Looper; +import android.os.Process; import android.os.RemoteException; +import android.os.UserHandle; import java.io.ByteArrayInputStream; import java.io.Closeable; import java.security.InvalidKeyException; @@ -437,6 +439,14 @@ public final class KeyChain { * Caller should call unbindService on the result when finished. */ public static KeyChainConnection bind(Context context) throws InterruptedException { + return bindAsUser(context, Process.myUserHandle()); + } + + /** + * @hide + */ + public static KeyChainConnection bindAsUser(Context context, UserHandle user) + throws InterruptedException { if (context == null) { throw new NullPointerException("context == null"); } @@ -459,9 +469,10 @@ public final class KeyChain { Intent intent = new Intent(IKeyChainService.class.getName()); ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0); intent.setComponent(comp); - boolean isBound = context.bindService(intent, - keyChainServiceConnection, - Context.BIND_AUTO_CREATE); + boolean isBound = context.bindServiceAsUser(intent, + keyChainServiceConnection, + Context.BIND_AUTO_CREATE, + user); if (!isBound) { throw new AssertionError("could not bind to KeyChainService"); } diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h index 233f3f0a31b8..d578ef58a6be 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -1118,8 +1118,8 @@ public: const DeferredDisplayState& state) { DrawStrokableOp::onDefer(renderer, deferInfo, state); if (!mPaint->getPathEffect()) { - renderer.getCaches().tessellationCache.precacheRoundRect(state.mMatrix, - mLocalBounds.getWidth(), mLocalBounds.getHeight(), mRx, mRy, mPaint); + renderer.getCaches().tessellationCache.precacheRoundRect(state.mMatrix, *mPaint, + mLocalBounds.getWidth(), mLocalBounds.getHeight(), mRx, mRy); } } diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 0e47c6e2b92d..fc4d40bec43f 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -308,6 +308,10 @@ status_t DisplayListRenderer::drawOval(float left, float top, float right, float status_t DisplayListRenderer::drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) { + if (fabs(sweepAngle) > 360.0f) { + return drawOval(left, top, right, bottom, paint); + } + paint = refPaint(paint); addDrawOp(new (alloc()) DrawArcOp(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint)); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 8f3872a42a8b..6397478bec60 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -2556,8 +2556,8 @@ status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float return drawShape(left, top, texture, p); } - const VertexBuffer* vertexBuffer = mCaches.tessellationCache.getRoundRect(*currentTransform(), - right - left, bottom - top, rx, ry, p); + const VertexBuffer* vertexBuffer = mCaches.tessellationCache.getRoundRect( + *currentTransform(), *p, right - left, bottom - top, rx, ry); return drawVertexBuffer(left, top, *vertexBuffer, p); } @@ -2611,10 +2611,6 @@ status_t OpenGLRenderer::drawArc(float left, float top, float right, float botto return DrawGlInfo::kStatusDone; } - if (fabs(sweepAngle) >= 360.0f) { - return drawOval(left, top, right, bottom, p); - } - // TODO: support fills (accounting for concavity if useCenter && sweepAngle > 180) if (p->getStyle() != SkPaint::kStroke_Style || p->getPathEffect() != 0 || useCenter) { mCaches.activeTexture(0); diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 05f4edf6e75e..3d93383e2c49 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -20,6 +20,7 @@ #include "RenderNode.h" #include <algorithm> +#include <string> #include <SkCanvas.h> #include <algorithm> @@ -158,7 +159,10 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { applyLayerPropertiesToLayer(info); damageSelf(info); } else if (mLayer->layer.getWidth() != getWidth() || mLayer->layer.getHeight() != getHeight()) { - LayerRenderer::resizeLayer(mLayer, getWidth(), getHeight()); + if (!LayerRenderer::resizeLayer(mLayer, getWidth(), getHeight())) { + LayerRenderer::destroyLayer(mLayer); + mLayer = 0; + } damageSelf(info); } @@ -166,6 +170,15 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { info.damageAccumulator->peekAtDirty(&dirty); info.damageAccumulator->popTransform(); + if (!mLayer) { + if (info.errorHandler) { + std::string msg = "Unable to create layer for "; + msg += getName(); + info.errorHandler->onError(msg); + } + return; + } + if (!dirty.isEmpty()) { mLayer->updateDeferred(this, dirty.fLeft, dirty.fTop, dirty.fRight, dirty.fBottom); } diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp index ef3d0d765ba2..08b54ff0f619 100644 --- a/libs/hwui/TessellationCache.cpp +++ b/libs/hwui/TessellationCache.cpp @@ -39,6 +39,8 @@ namespace uirenderer { TessellationCache::Description::Description() : type(kNone) + , scaleX(1.0f) + , scaleY(1.0f) , aa(false) , cap(SkPaint::kDefault_Cap) , style(SkPaint::kFill_Style) @@ -46,21 +48,13 @@ TessellationCache::Description::Description() memset(&shape, 0, sizeof(Shape)); } -TessellationCache::Description::Description(Type type) +TessellationCache::Description::Description(Type type, const Matrix4& transform, const SkPaint& paint) : type(type) - , aa(false) - , cap(SkPaint::kDefault_Cap) - , style(SkPaint::kFill_Style) - , strokeWidth(1.0f) { - memset(&shape, 0, sizeof(Shape)); -} - -TessellationCache::Description::Description(Type type, const SkPaint* paint) - : type(type) - , aa(paint->isAntiAlias()) - , cap(paint->getStrokeCap()) - , style(paint->getStyle()) - , strokeWidth(paint->getStrokeWidth()) { + , aa(paint.isAntiAlias()) + , cap(paint.getStrokeCap()) + , style(paint.getStyle()) + , strokeWidth(paint.getStrokeWidth()) { + PathTessellator::extractTessellationScales(transform, &scaleX, &scaleY); memset(&shape, 0, sizeof(Shape)); } @@ -70,10 +64,20 @@ hash_t TessellationCache::Description::hash() const { hash = JenkinsHashMix(hash, cap); hash = JenkinsHashMix(hash, style); hash = JenkinsHashMix(hash, android::hash_type(strokeWidth)); + hash = JenkinsHashMix(hash, android::hash_type(scaleX)); + hash = JenkinsHashMix(hash, android::hash_type(scaleY)); hash = JenkinsHashMixBytes(hash, (uint8_t*) &shape, sizeof(Shape)); return JenkinsHashWhiten(hash); } +void TessellationCache::Description::setupMatrixAndPaint(Matrix4* matrix, SkPaint* paint) const { + matrix->loadScale(scaleX, scaleY, 1.0f); + paint->setAntiAlias(aa); + paint->setStrokeCap(cap); + paint->setStyle(style); + paint->setStrokeWidth(strokeWidth); +} + TessellationCache::ShadowDescription::ShadowDescription() : nodeKey(NULL) { memset(&matrixData, 0, 16 * sizeof(float)); @@ -96,20 +100,15 @@ hash_t TessellationCache::ShadowDescription::hash() const { class TessellationCache::TessellationTask : public Task<VertexBuffer*> { public: - TessellationTask(Tessellator tessellator, const Description& description, - const SkPaint* paint) + TessellationTask(Tessellator tessellator, const Description& description) : tessellator(tessellator) - , description(description) - , paint(*paint) { + , description(description) { } ~TessellationTask() {} Tessellator tessellator; Description description; - - //copied, since input paint may not be immutable - const SkPaint paint; }; class TessellationCache::TessellationProcessor : public TaskProcessor<VertexBuffer*> { @@ -121,7 +120,7 @@ public: virtual void onProcess(const sp<Task<VertexBuffer*> >& task) { TessellationTask* t = static_cast<TessellationTask*>(task.get()); ATRACE_NAME("shape tessellation"); - VertexBuffer* buffer = t->tessellator(t->description, t->paint); + VertexBuffer* buffer = t->tessellator(t->description); t->setResult(buffer); } }; @@ -416,21 +415,12 @@ void TessellationCache::getShadowBuffers(const Matrix4* drawTransform, const Rec // Tessellation precaching /////////////////////////////////////////////////////////////////////////////// -static VertexBuffer* tessellatePath(const SkPath& path, const SkPaint* paint, - float scaleX, float scaleY) { - VertexBuffer* buffer = new VertexBuffer(); - Matrix4 matrix; - matrix.loadScale(scaleX, scaleY, 1); - PathTessellator::tessellatePath(path, paint, matrix, *buffer); - return buffer; -} - TessellationCache::Buffer* TessellationCache::getOrCreateBuffer( - const Description& entry, Tessellator tessellator, const SkPaint* paint) { + const Description& entry, Tessellator tessellator) { Buffer* buffer = mCache.get(entry); if (!buffer) { // not cached, enqueue a task to fill the buffer - sp<TessellationTask> task = new TessellationTask(tessellator, entry, paint); + sp<TessellationTask> task = new TessellationTask(tessellator, entry); buffer = new Buffer(task); if (mProcessor == NULL) { @@ -442,43 +432,49 @@ TessellationCache::Buffer* TessellationCache::getOrCreateBuffer( return buffer; } +static VertexBuffer* tessellatePath(const TessellationCache::Description& description, + const SkPath& path) { + Matrix4 matrix; + SkPaint paint; + description.setupMatrixAndPaint(&matrix, &paint); + VertexBuffer* buffer = new VertexBuffer(); + PathTessellator::tessellatePath(path, &paint, matrix, *buffer); + return buffer; +} + /////////////////////////////////////////////////////////////////////////////// -// Rounded rects +// RoundRect /////////////////////////////////////////////////////////////////////////////// -static VertexBuffer* tessellateRoundRect(const TessellationCache::Description& description, - const SkPaint& paint) { - SkRect rect = SkRect::MakeWH(description.shape.roundRect.mWidth, - description.shape.roundRect.mHeight); - float rx = description.shape.roundRect.mRx; - float ry = description.shape.roundRect.mRy; - if (paint.getStyle() == SkPaint::kStrokeAndFill_Style) { - float outset = paint.getStrokeWidth() / 2; +static VertexBuffer* tessellateRoundRect(const TessellationCache::Description& description) { + SkRect rect = SkRect::MakeWH(description.shape.roundRect.width, + description.shape.roundRect.height); + float rx = description.shape.roundRect.rx; + float ry = description.shape.roundRect.ry; + if (description.style == SkPaint::kStrokeAndFill_Style) { + float outset = description.strokeWidth / 2; rect.outset(outset, outset); rx += outset; ry += outset; } SkPath path; path.addRoundRect(rect, rx, ry); - return tessellatePath(path, &paint, - description.shape.roundRect.mScaleX, description.shape.roundRect.mScaleY); + return tessellatePath(description, path); } -TessellationCache::Buffer* TessellationCache::getRoundRectBuffer(const Matrix4& transform, - float width, float height, float rx, float ry, const SkPaint* paint) { - Description entry(Description::kRoundRect, paint); - entry.shape.roundRect.mWidth = width; - entry.shape.roundRect.mHeight = height; - entry.shape.roundRect.mRx = rx; - entry.shape.roundRect.mRy = ry; - PathTessellator::extractTessellationScales(transform, - &entry.shape.roundRect.mScaleX, &entry.shape.roundRect.mScaleY); - - return getOrCreateBuffer(entry, &tessellateRoundRect, paint); +TessellationCache::Buffer* TessellationCache::getRoundRectBuffer( + const Matrix4& transform, const SkPaint& paint, + float width, float height, float rx, float ry) { + Description entry(Description::kRoundRect, transform, paint); + entry.shape.roundRect.width = width; + entry.shape.roundRect.height = height; + entry.shape.roundRect.rx = rx; + entry.shape.roundRect.ry = ry; + return getOrCreateBuffer(entry, &tessellateRoundRect); } -const VertexBuffer* TessellationCache::getRoundRect(const Matrix4& transform, - float width, float height, float rx, float ry, const SkPaint* paint) { - return getRoundRectBuffer(transform, width, height, rx, ry, paint)->getVertexBuffer(); +const VertexBuffer* TessellationCache::getRoundRect(const Matrix4& transform, const SkPaint& paint, + float width, float height, float rx, float ry) { + return getRoundRectBuffer(transform, paint, width, height, rx, ry)->getVertexBuffer(); } }; // namespace uirenderer diff --git a/libs/hwui/TessellationCache.h b/libs/hwui/TessellationCache.h index d4ff9434cee8..688a69959a57 100644 --- a/libs/hwui/TessellationCache.h +++ b/libs/hwui/TessellationCache.h @@ -50,30 +50,28 @@ public: enum Type { kNone, kRoundRect, - kAmbientShadow, - kSpotShadow }; Type type; + float scaleX; + float scaleY; bool aa; SkPaint::Cap cap; SkPaint::Style style; float strokeWidth; union Shape { struct RoundRect { - float mScaleX; - float mScaleY; - float mWidth; - float mHeight; - float mRx; - float mRy; + float width; + float height; + float rx; + float ry; } roundRect; } shape; Description(); - Description(Type type); - Description(Type type, const SkPaint* paint); + Description(Type type, const Matrix4& transform, const SkPaint& paint); hash_t hash() const; + void setupMatrixAndPaint(Matrix4* matrix, SkPaint* paint) const; }; struct ShadowDescription { @@ -123,12 +121,12 @@ public: // TODO: precache/get for Oval, Lines, Points, etc. - void precacheRoundRect(const Matrix4& transform, - float width, float height, float rx, float ry, const SkPaint* paint) { - getRoundRectBuffer(transform, width, height, rx, ry, paint); + void precacheRoundRect(const Matrix4& transform, const SkPaint& paint, + float width, float height, float rx, float ry) { + getRoundRectBuffer(transform, paint, width, height, rx, ry); } - const VertexBuffer* getRoundRect(const Matrix4& transform, - float width, float height, float rx, float ry, const SkPaint* paint); + const VertexBuffer* getRoundRect(const Matrix4& transform, const SkPaint& paint, + float width, float height, float rx, float ry); void precacheShadows(const Matrix4* drawTransform, const Rect& localClip, bool opaque, const SkPath* casterPerimeter, @@ -146,14 +144,14 @@ private: class TessellationTask; class TessellationProcessor; + typedef VertexBuffer* (*Tessellator)(const Description&); - typedef VertexBuffer* (*Tessellator)(const Description&, const SkPaint&); + Buffer* getRectBuffer(const Matrix4& transform, const SkPaint& paint, + float width, float height); + Buffer* getRoundRectBuffer(const Matrix4& transform, const SkPaint& paint, + float width, float height, float rx, float ry); - Buffer* getRoundRectBuffer(const Matrix4& transform, - float width, float height, float rx, float ry, const SkPaint* paint); - - Buffer* getOrCreateBuffer(const Description& entry, - Tessellator tessellator, const SkPaint* paint); + Buffer* getOrCreateBuffer(const Description& entry, Tessellator tessellator); uint32_t mSize; uint32_t mMaxSize; diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h index 0fc0cef76fef..f67e43406815 100644 --- a/libs/hwui/TreeInfo.h +++ b/libs/hwui/TreeInfo.h @@ -16,6 +16,8 @@ #ifndef TREEINFO_H #define TREEINFO_H +#include <string> + #include <utils/Timers.h> #include "DamageAccumulator.h" @@ -35,6 +37,13 @@ protected: ~AnimationHook() {} }; +class ErrorHandler { +public: + virtual void onError(const std::string& message) = 0; +protected: + ~ErrorHandler() {} +}; + // This would be a struct, but we want to PREVENT_COPY_AND_ASSIGN class TreeInfo { PREVENT_COPY_AND_ASSIGN(TreeInfo); @@ -65,6 +74,7 @@ public: , prepareTextures(mode == MODE_FULL) , damageAccumulator(NullDamageAccumulator::instance()) , renderer(0) + , errorHandler(0) {} const TraversalMode mode; @@ -78,6 +88,7 @@ public: // The renderer that will be drawing the next frame. Use this to push any // layer updates or similar. May be NULL. OpenGLRenderer* renderer; + ErrorHandler* errorHandler; struct Out { Out() diff --git a/libs/hwui/thread/Task.h b/libs/hwui/thread/Task.h index 9a211a238bbc..30b6ff2c3d83 100644 --- a/libs/hwui/thread/Task.h +++ b/libs/hwui/thread/Task.h @@ -17,8 +17,6 @@ #ifndef ANDROID_HWUI_TASK_H #define ANDROID_HWUI_TASK_H -#define ATRACE_TAG ATRACE_TAG_VIEW - #include <utils/RefBase.h> #include <utils/Trace.h> @@ -40,7 +38,7 @@ public: virtual ~Task() { } T getResult() const { - ATRACE_NAME("waitForTask"); + ScopedTrace tracer(ATRACE_TAG_VIEW, "waitForTask"); return mFuture->get(); } 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 2f1e11efb0f7..d35225ab66e2 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -1616,26 +1616,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. @@ -2534,6 +2514,9 @@ public class AudioManager { // from AudioManager. AudioSystem is an internal class used by AudioManager and AudioService. /** @hide + * The audio device code for representing "no device." */ + public static final int DEVICE_NONE = AudioSystem.DEVICE_NONE; + /** @hide * The audio output device code for the small speaker at the front of the device used * when placing calls. Does not refer to an in-ear headphone without attached microphone, * such as earbuds, earphones, or in-ear monitors (IEM). Those would be handled as a @@ -2971,7 +2954,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..48479a434415 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); @@ -4482,22 +4464,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/AudioSystem.java b/media/java/android/media/AudioSystem.java index 9fbcd186bdd7..63ed10c3fcf5 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -225,6 +225,7 @@ public class AudioSystem // audio device definitions: must be kept in sync with values in system/core/audio.h // + public static final int DEVICE_NONE = 0x0; // reserved bits public static final int DEVICE_BIT_IN = 0x80000000; public static final int DEVICE_BIT_DEFAULT = 0x40000000; 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..169631e2e63e 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); 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/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java index bbe650d12c1c..7e9d27970702 100644 --- a/media/java/android/media/tv/TvContract.java +++ b/media/java/android/media/tv/TvContract.java @@ -22,7 +22,9 @@ import android.content.ContentUris; import android.net.Uri; import android.provider.BaseColumns; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * <p> @@ -380,6 +382,81 @@ public final class TvContract { /** The service type for radio channels that have audio only. */ public static final int SERVICE_TYPE_AUDIO = 0x2; + /** The video format for 240p. */ + public static final String VIDEO_FORMAT_240P = "VIDEO_FORMAT_240P"; + + /** The video format for 360p. */ + public static final String VIDEO_FORMAT_360P = "VIDEO_FORMAT_360P"; + + /** The video format for 480i. */ + public static final String VIDEO_FORMAT_480I = "VIDEO_FORMAT_480I"; + + /** The video format for 480p. */ + public static final String VIDEO_FORMAT_480P = "VIDEO_FORMAT_480P"; + + /** The video format for 576i. */ + public static final String VIDEO_FORMAT_576I = "VIDEO_FORMAT_576I"; + + /** The video format for 576p. */ + public static final String VIDEO_FORMAT_576P = "VIDEO_FORMAT_576P"; + + /** The video format for 720p. */ + public static final String VIDEO_FORMAT_720P = "VIDEO_FORMAT_720P"; + + /** The video format for 1080i. */ + public static final String VIDEO_FORMAT_1080I = "VIDEO_FORMAT_1080I"; + + /** The video format for 1080p. */ + public static final String VIDEO_FORMAT_1080P = "VIDEO_FORMAT_1080P"; + + /** The video format for 2160p. */ + public static final String VIDEO_FORMAT_2160P = "VIDEO_FORMAT_2160P"; + + /** The video format for 4320p. */ + public static final String VIDEO_FORMAT_4320P = "VIDEO_FORMAT_4320P"; + + /** The video resolution for standard-definition. */ + public static final String VIDEO_RESOLUTION_SD = "VIDEO_RESOLUTION_SD"; + + /** The video resolution for enhanced-definition. */ + public static final String VIDEO_RESOLUTION_ED = "VIDEO_RESOLUTION_ED"; + + /** The video resolution for high-definition. */ + public static final String VIDEO_RESOLUTION_HD = "VIDEO_RESOLUTION_HD"; + + /** The video resolution for full high-definition. */ + public static final String VIDEO_RESOLUTION_FHD = "VIDEO_RESOLUTION_FHD"; + + /** The video resolution for ultra high-definition. */ + public static final String VIDEO_RESOLUTION_UHD = "VIDEO_RESOLUTION_UHD"; + + private static final Map<String, String> VIDEO_FORMAT_TO_RESOLUTION_MAP = + new HashMap<String, String>(); + + static { + VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_480I, VIDEO_RESOLUTION_SD); + VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_480P, VIDEO_RESOLUTION_ED); + VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_576I, VIDEO_RESOLUTION_SD); + VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_576P, VIDEO_RESOLUTION_ED); + VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_720P, VIDEO_RESOLUTION_HD); + VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_1080I, VIDEO_RESOLUTION_HD); + VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_1080P, VIDEO_RESOLUTION_FHD); + VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_2160P, VIDEO_RESOLUTION_UHD); + VIDEO_FORMAT_TO_RESOLUTION_MAP.put(VIDEO_FORMAT_4320P, VIDEO_RESOLUTION_UHD); + } + + /** + * Returns the video resolution (definition) for a given video format. + * + * @param videoFormat The video format defined in {@link Channels}. + * @return the corresponding video resolution string. {@code null} if the resolution string + * is not defined for the given video format. + * @see #COLUMN_VIDEO_FORMAT + */ + public static final String getVideoResolution(String videoFormat) { + return VIDEO_FORMAT_TO_RESOLUTION_MAP.get(videoFormat); + } + /** * The name of the {@link TvInputService} subclass that provides this TV channel. This * should be a fully qualified class name (such as, "com.example.project.TvInputService"). @@ -513,6 +590,24 @@ public final class TvContract { public static final String COLUMN_DESCRIPTION = "description"; /** + * The typical video format for programs from this TV channel. + * <p> + * This is primarily used to filter out channels based on video format by applications. The + * value should match one of the followings: {@link #VIDEO_FORMAT_240P}, + * {@link #VIDEO_FORMAT_360P}, {@link #VIDEO_FORMAT_480I}, {@link #VIDEO_FORMAT_480P}, + * {@link #VIDEO_FORMAT_576I}, {@link #VIDEO_FORMAT_576P}, {@link #VIDEO_FORMAT_720P}, + * {@link #VIDEO_FORMAT_1080I}, {@link #VIDEO_FORMAT_1080P}, {@link #VIDEO_FORMAT_2160P}, + * {@link #VIDEO_FORMAT_4320P}. Note that the actual video resolution of each program from a + * given channel can vary thus one should use {@link Programs#COLUMN_VIDEO_WIDTH} and + * {@link Programs#COLUMN_VIDEO_HEIGHT} to get more accurate video resolution. + * </p><p> + * Type: TEXT + * </p><p> + * @see #getVideoResolution + */ + public static final String COLUMN_VIDEO_FORMAT = "video_format"; + + /** * The flag indicating whether this TV channel is browsable or not. * <p> * A value of 1 indicates the channel is included in the channel list that applications use @@ -719,6 +814,32 @@ public final class TvContract { public static final String COLUMN_LONG_DESCRIPTION = "long_description"; /** + * The width of the video for this TV program, in the unit of pixels. + * <p> + * Together with {@link #COLUMN_VIDEO_HEIGHT} this is used to determine the video resolution + * of the current TV program. Can be empty if it is not known initially or the program does + * not convey any video such as the programs from type {@link Channels#SERVICE_TYPE_AUDIO} + * channels. + * </p><p> + * Type: INTEGER + * </p> + */ + public static final String COLUMN_VIDEO_WIDTH = "video_width"; + + /** + * The height of the video for this TV program, in the unit of pixels. + * <p> + * Together with {@link #COLUMN_VIDEO_WIDTH} this is used to determine the video resolution + * of the current TV program. Can be empty if it is not known initially or the program does + * not convey any video such as the programs from type {@link Channels#SERVICE_TYPE_AUDIO} + * channels. + * </p><p> + * Type: INTEGER + * </p> + */ + public static final String COLUMN_VIDEO_HEIGHT = "video_height"; + + /** * The comma-separated audio languages of this TV program. * <p> * This is used to describe available audio languages included in the program. Use @@ -778,37 +899,37 @@ public final class TvContract { /** Canonical genres for TV programs. */ public static final class Genres { /** The genre for Family/Kids. */ - public static final String FAMILY_KIDS = "Family/Kids"; + public static final String FAMILY_KIDS = "FAMILY_KIDS"; /** The genre for Sports. */ - public static final String SPORTS = "Sports"; + public static final String SPORTS = "SPORTS"; /** The genre for Shopping. */ - public static final String SHOPPING = "Shopping"; + public static final String SHOPPING = "SHOPPING"; /** The genre for Movies. */ - public static final String MOVIES = "Movies"; + public static final String MOVIES = "MOVIES"; /** The genre for Comedy. */ - public static final String COMEDY = "Comedy"; + public static final String COMEDY = "COMEDY"; /** The genre for Travel. */ - public static final String TRAVEL = "Travel"; + public static final String TRAVEL = "TRAVEL"; /** The genre for Drama. */ - public static final String DRAMA = "Drama"; + public static final String DRAMA = "DRAMA"; /** The genre for Education. */ - public static final String EDUCATION = "Education"; + public static final String EDUCATION = "EDUCATION"; /** The genre for Animal/Wildlife. */ - public static final String ANIMAL_WILDLIFE = "Animal/Wildlife"; + public static final String ANIMAL_WILDLIFE = "ANIMAL_WILDLIFE"; /** The genre for News. */ - public static final String NEWS = "News"; + public static final String NEWS = "NEWS"; /** The genre for Gaming. */ - public static final String GAMING = "Gaming"; + public static final String GAMING = "GAMING"; private Genres() {} diff --git a/media/java/android/media/tv/TvInputHardwareInfo.java b/media/java/android/media/tv/TvInputHardwareInfo.java index 4beb9607232d..e5f9889aca61 100644 --- a/media/java/android/media/tv/TvInputHardwareInfo.java +++ b/media/java/android/media/tv/TvInputHardwareInfo.java @@ -16,6 +16,7 @@ package android.media.tv; +import android.media.AudioManager; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; @@ -56,14 +57,11 @@ public final class TvInputHardwareInfo implements Parcelable { private int mDeviceId; private int mType; - // TODO: Add audio port & audio address for audio service. - // TODO: Add HDMI handle for HDMI service. + private int mAudioType; + private String mAudioAddress; + private int mHdmiPortId; - public TvInputHardwareInfo() { } - - public TvInputHardwareInfo(int deviceId, int type) { - mDeviceId = deviceId; - mType = type; + private TvInputHardwareInfo() { } public int getDeviceId() { @@ -74,6 +72,21 @@ public final class TvInputHardwareInfo implements Parcelable { return mType; } + public int getAudioType() { + return mAudioType; + } + + public String getAudioAddress() { + return mAudioAddress; + } + + public int getHdmiPortId() { + if (mType != TV_INPUT_TYPE_HDMI) { + throw new IllegalStateException(); + } + return mHdmiPortId; + } + // Parcelable @Override public int describeContents() { @@ -84,10 +97,78 @@ public final class TvInputHardwareInfo implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mDeviceId); dest.writeInt(mType); + dest.writeInt(mAudioType); + dest.writeString(mAudioAddress); + if (mType == TV_INPUT_TYPE_HDMI) { + dest.writeInt(mHdmiPortId); + } } public void readFromParcel(Parcel source) { mDeviceId = source.readInt(); mType = source.readInt(); + mAudioType = source.readInt(); + mAudioAddress = source.readString(); + if (mType == TV_INPUT_TYPE_HDMI) { + mHdmiPortId = source.readInt(); + } + } + + public static final class Builder { + private Integer mDeviceId = null; + private Integer mType = null; + private int mAudioType = AudioManager.DEVICE_NONE; + private String mAudioAddress = ""; + private Integer mHdmiPortId = null; + + public Builder() { + } + + public Builder deviceId(int deviceId) { + mDeviceId = deviceId; + return this; + } + + public Builder type(int type) { + mType = type; + return this; + } + + public Builder audioType(int audioType) { + mAudioType = audioType; + return this; + } + + public Builder audioAddress(String audioAddress) { + mAudioAddress = audioAddress; + return this; + } + + public Builder hdmiPortId(int hdmiPortId) { + mHdmiPortId = hdmiPortId; + return this; + } + + public TvInputHardwareInfo build() { + if (mDeviceId == null || mType == null) { + throw new UnsupportedOperationException(); + } + if ((mType == TV_INPUT_TYPE_HDMI && mHdmiPortId == null) || + (mType != TV_INPUT_TYPE_HDMI && mHdmiPortId != null)) { + throw new UnsupportedOperationException(); + } + + TvInputHardwareInfo info = new TvInputHardwareInfo(); + info.mDeviceId = mDeviceId; + info.mType = mType; + info.mAudioType = mAudioType; + if (info.mAudioType != AudioManager.DEVICE_NONE) { + info.mAudioAddress = mAudioAddress; + } + if (mHdmiPortId != null) { + info.mHdmiPortId = mHdmiPortId; + } + return info; + } } } diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java index 2ed3d731b97f..52db30a82fba 100644 --- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java +++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java @@ -27,6 +27,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageInfoLite; import android.content.pm.PackageManager; import android.content.pm.PackageParser; +import android.content.pm.PackageParser.PackageParserException; import android.content.res.ObbInfo; import android.content.res.ObbScanner; import android.net.Uri; @@ -157,6 +158,7 @@ public class DefaultContainerService extends IntentService { * @return Returns PackageInfoLite object containing * the package info and recommended app location. */ + @Override public PackageInfoLite getMinimalPackageInfo(final String packagePath, int flags, long threshold, String abiOverride) { PackageInfoLite ret = new PackageInfoLite(); @@ -167,14 +169,13 @@ public class DefaultContainerService extends IntentService { return ret; } - DisplayMetrics metrics = new DisplayMetrics(); - metrics.setToDefaults(); - - PackageParser.ApkLite pkg = PackageParser.parseApkLite(packagePath, 0); - if (pkg == null) { + final File apkFile = new File(packagePath); + final PackageParser.ApkLite pkg; + try { + pkg = PackageParser.parseApkLite(apkFile, 0); + } catch (PackageParserException e) { Slog.w(TAG, "Failed to parse package"); - final File apkFile = new File(packagePath); if (!apkFile.exists()) { ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_URI; } else { 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/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/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-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/colors.xml b/packages/SystemUI/res/values/colors.xml index 8c1a9c710dd4..3bd86891e5e1 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -46,9 +46,7 @@ <color name="keyguard_overflow_content_color">#ff686868</color> <!-- The default recents task bar background color. --> - <color name="recents_task_bar_default_background_color">#e6444444</color> - <!-- The default recents task bar text color. --> - <color name="recents_task_bar_default_text_color">#ffeeeeee</color> + <color name="recents_task_bar_default_background_color">#ffe6e6e6</color> <!-- The recents task bar light text color to be drawn on top of dark backgrounds. --> <color name="recents_task_bar_light_text_color">#ffeeeeee</color> <!-- The recents task bar dark text color to be drawn on top of light backgrounds. --> diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 88ff726c9551..9ea346b38185 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -277,13 +277,21 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView !mFullScreenshotView.cancelAnimateOnEnterRecents(mFinishRunnable)) { // If we have a focused task, then launch that task if (!mRecentsView.launchFocusedTask()) { - // If there are any tasks, then launch the first task - if (!mRecentsView.launchFirstTask()) { - // We really shouldn't hit this, but if we do, just animate out (aka. finish) + if (mConfig.launchedFromHome) { + // Just start the animation out of recents ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this, null, mFinishRunnable, null); mRecentsView.startExitToHomeAnimation( new ViewAnimation.TaskViewExitContext(exitTrigger)); + } else { + // Otherwise, try and launch the first task + if (!mRecentsView.launchFirstTask()) { + // If there are no tasks, then just finish recents + ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this, + null, mFinishRunnable, null); + mRecentsView.startExitToHomeAnimation( + new ViewAnimation.TaskViewExitContext(exitTrigger)); + } } } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java index 63ef773a124b..10978ca59bc5 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java @@ -81,7 +81,6 @@ public class RecentsConfiguration { /** Task bar colors */ public int taskBarViewDefaultBackgroundColor; - public int taskBarViewDefaultTextColor; public int taskBarViewLightTextColor; public int taskBarViewDarkTextColor; public int taskBarViewHighlightColor; @@ -202,8 +201,6 @@ public class RecentsConfiguration { // Task bar colors taskBarViewDefaultBackgroundColor = res.getColor(R.color.recents_task_bar_default_background_color); - taskBarViewDefaultTextColor = - res.getColor(R.color.recents_task_bar_default_text_color); taskBarViewLightTextColor = res.getColor(R.color.recents_task_bar_light_text_color); taskBarViewDarkTextColor = diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java index bf2576016857..1ef58add7206 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java @@ -151,16 +151,14 @@ class TaskBarView extends FrameLayout { mActivityDescription.setText(t.activityLabel); // Try and apply the system ui tint int tint = t.colorPrimary; - if (Constants.DebugFlags.App.EnableTaskBarThemeColors && tint != 0) { - setBackgroundColor(tint); - mActivityDescription.setTextColor(Utilities.getIdealColorForBackgroundColor(tint, - mConfig.taskBarViewLightTextColor, mConfig.taskBarViewDarkTextColor)); - mDismissButton.setImageDrawable(Utilities.getIdealResourceForBackgroundColor(tint, - mLightDismissDrawable, mDarkDismissDrawable)); - } else { - setBackgroundColor(mConfig.taskBarViewDefaultBackgroundColor); - mActivityDescription.setTextColor(mConfig.taskBarViewDefaultTextColor); + if (!Constants.DebugFlags.App.EnableTaskBarThemeColors || tint == 0) { + tint = mConfig.taskBarViewDefaultBackgroundColor; } + setBackgroundColor(tint); + mActivityDescription.setTextColor(Utilities.getIdealColorForBackgroundColor(tint, + mConfig.taskBarViewLightTextColor, mConfig.taskBarViewDarkTextColor)); + mDismissButton.setImageDrawable(Utilities.getIdealResourceForBackgroundColor(tint, + mLightDismissDrawable, mDarkDismissDrawable)); } /** Unbinds the bar view from the task */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index 6c12218b9c4a..55f93354544c 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -973,7 +973,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal int getExitTransformsForFilterAnimation(ArrayList<Task> curTasks, ArrayList<TaskViewTransform> curTaskTransforms, ArrayList<Task> tasks, ArrayList<TaskViewTransform> taskTransforms, - HashMap<TaskView, Pair<Integer, TaskViewTransform>> childViewTransformsOut, + HashMap<TaskView, TaskViewTransform> childViewTransformsOut, ArrayList<TaskView> childrenToRemoveOut) { // Animate all of the existing views out of view (if they are not in the visible range in // the new stack) or to their final positions in the new stack @@ -1003,9 +1003,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal (int) tv.getTranslationY())); } - int startDelay = offset * - Constants.Values.TaskStackView.FilterStartDelay; - childViewTransformsOut.put(tv, new Pair(startDelay, toTransform)); + toTransform.startDelay = offset * Constants.Values.TaskStackView.FilterStartDelay; + childViewTransformsOut.put(tv, toTransform); offset++; } return mConfig.filteringCurrentViewsAnimDuration; @@ -1017,7 +1016,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal */ int getEnterTransformsForFilterAnimation(ArrayList<Task> tasks, ArrayList<TaskViewTransform> taskTransforms, - HashMap<TaskView, Pair<Integer, TaskViewTransform>> childViewTransformsOut) { + HashMap<TaskView, TaskViewTransform> childViewTransformsOut) { int offset = 0; int movement = 0; int taskCount = tasks.size(); @@ -1035,9 +1034,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal tv.prepareTaskTransformForFilterTaskHidden(fromTransform); tv.updateViewPropertiesToTaskTransform(fromTransform, 0); - int startDelay = offset * - Constants.Values.TaskStackView.FilterStartDelay; - childViewTransformsOut.put(tv, new Pair(startDelay, toTransform)); + toTransform.startDelay = offset * Constants.Values.TaskStackView.FilterStartDelay; + childViewTransformsOut.put(tv, toTransform); // Use the movement of the new views to calculate the duration of the animation movement = Math.max(movement, @@ -1057,8 +1055,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal // Calculate the transforms to animate out all the existing views if they are not in the // new visible range (or to their final positions in the stack if they are) final ArrayList<TaskView> childrenToRemove = new ArrayList<TaskView>(); - final HashMap<TaskView, Pair<Integer, TaskViewTransform>> childViewTransforms = - new HashMap<TaskView, Pair<Integer, TaskViewTransform>>(); + final HashMap<TaskView, TaskViewTransform> childViewTransforms = + new HashMap<TaskView, TaskViewTransform>(); int duration = getExitTransformsForFilterAnimation(curTasks, curTaskTransforms, tasks, taskTransforms, childViewTransforms, childrenToRemove); @@ -1073,10 +1071,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal // Animate all the views to their final transforms for (final TaskView tv : childViewTransforms.keySet()) { - Pair<Integer, TaskViewTransform> t = childViewTransforms.get(tv); + TaskViewTransform t = childViewTransforms.get(tv); tv.animate().cancel(); tv.animate() - .setStartDelay(t.first) .withEndAction(new Runnable() { @Override public void run() { @@ -1093,15 +1090,14 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal int duration = getEnterTransformsForFilterAnimation(tasks, taskTransforms, childViewTransforms); for (final TaskView tv : childViewTransforms.keySet()) { - Pair<Integer, TaskViewTransform> t = childViewTransforms.get(tv); - tv.animate().setStartDelay(t.first); - tv.updateViewPropertiesToTaskTransform(t.second, duration); + TaskViewTransform t = childViewTransforms.get(tv); + tv.updateViewPropertiesToTaskTransform(t, duration); } } } } }); - tv.updateViewPropertiesToTaskTransform(t.second, duration); + tv.updateViewPropertiesToTaskTransform(t, duration); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java index 0b191622a716..cfba74cba904 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -202,7 +202,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On if (useLayers) { anim.withLayer(); } - anim.setStartDelay(0) + anim.setStartDelay(toTransform.startDelay) .setDuration(duration) .setInterpolator(mConfig.fastOutSlowInInterpolator) .start(); @@ -248,6 +248,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On // Fade the view out and slide it away toTransform.alpha = 0f; toTransform.translationY += 200; + toTransform.translationZ = 0; } /** @@ -585,19 +586,25 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On } @Override - public void onClick(View v) { - if (v == mBarView.mApplicationIcon) { - mCb.onTaskIconClicked(this); - } else if (v == mBarView.mDismissButton) { - // Animate out the view and call the callback - final TaskView tv = this; - startDeleteTaskAnimation(new Runnable() { - @Override - public void run() { - mCb.onTaskDismissed(tv); + public void onClick(final View v) { + // We purposely post the handler delayed to allow for the touch feedback to draw + final TaskView tv = this; + postDelayed(new Runnable() { + @Override + public void run() { + if (v == mBarView.mApplicationIcon) { + mCb.onTaskIconClicked(tv); + } else if (v == mBarView.mDismissButton) { + // Animate out the view and call the callback + startDeleteTaskAnimation(new Runnable() { + @Override + public void run() { + mCb.onTaskDismissed(tv); + } + }); } - }); - } + } + }, 125); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java index 1947e3015cfb..b351b0351530 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java @@ -21,6 +21,7 @@ import android.graphics.Rect; /* The transform state for a task view */ public class TaskViewTransform { + public int startDelay = 0; public int translationY = 0; public int translationZ = 0; public float scale = 1f; @@ -35,6 +36,7 @@ public class TaskViewTransform { } public TaskViewTransform(TaskViewTransform o) { + startDelay = o.startDelay; translationY = o.translationY; translationZ = o.translationZ; scale = o.scale; @@ -47,6 +49,7 @@ public class TaskViewTransform { /** Resets the current transform */ public void reset() { + startDelay = 0; translationY = 0; translationZ = 0; scale = 1f; @@ -76,8 +79,8 @@ public class TaskViewTransform { @Override public String toString() { - return "TaskViewTransform y: " + translationY + " z: " + translationZ + " scale: " + scale + - " alpha: " + alpha + " visible: " + visible + " rect: " + rect + + return "TaskViewTransform delay: " + startDelay + " y: " + translationY + " z: " + translationZ + + " scale: " + scale + " alpha: " + alpha + " visible: " + visible + " rect: " + rect + " dismissAlpha: " + dismissAlpha; } } diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java index 2191b54b6bc4..d9588e8b0fa4 100644 --- a/rs/java/android/renderscript/Allocation.java +++ b/rs/java/android/renderscript/Allocation.java @@ -770,10 +770,11 @@ public class Allocation extends BaseObj { mRS.validate(); int eSize = mType.mElement.getBytesSize(); final byte[] data = fp.getData(); + int data_length = fp.getPos(); - int count = data.length / eSize; - if ((eSize * count) != data.length) { - throw new RSIllegalArgumentException("Field packer length " + data.length + + int count = data_length / eSize; + if ((eSize * count) != data_length) { + throw new RSIllegalArgumentException("Field packer length " + data_length + " not divisible by element size " + eSize + "."); } copy1DRangeFromUnchecked(xoff, count, data); @@ -797,16 +798,17 @@ public class Allocation extends BaseObj { } final byte[] data = fp.getData(); + int data_length = fp.getPos(); int eSize = mType.mElement.mElements[component_number].getBytesSize(); eSize *= mType.mElement.mArraySizes[component_number]; - if (data.length != eSize) { - throw new RSIllegalArgumentException("Field packer sizelength " + data.length + + if (data_length != eSize) { + throw new RSIllegalArgumentException("Field packer sizelength " + data_length + " does not match component size " + eSize + "."); } mRS.nAllocationElementData1D(getIDSafe(), xoff, mSelectedLOD, - component_number, data, data.length); + component_number, data, data_length); } private void data1DChecks(int off, int count, int len, int dataSize) { diff --git a/rs/java/android/renderscript/Element.java b/rs/java/android/renderscript/Element.java index 55b671d40bb7..c6b5b0d99ea2 100644 --- a/rs/java/android/renderscript/Element.java +++ b/rs/java/android/renderscript/Element.java @@ -140,17 +140,17 @@ public class Element extends BaseObj { MATRIX_3X3 (17, 36), MATRIX_2X2 (18, 16), - RS_ELEMENT (1000, 4), - RS_TYPE (1001, 4), - RS_ALLOCATION (1002, 4), - RS_SAMPLER (1003, 4), - RS_SCRIPT (1004, 4), - RS_MESH (1005, 4), - RS_PROGRAM_FRAGMENT (1006, 4), - RS_PROGRAM_VERTEX (1007, 4), - RS_PROGRAM_RASTER (1008, 4), - RS_PROGRAM_STORE (1009, 4), - RS_FONT (1010, 4); + RS_ELEMENT (1000), + RS_TYPE (1001), + RS_ALLOCATION (1002), + RS_SAMPLER (1003), + RS_SCRIPT (1004), + RS_MESH (1005), + RS_PROGRAM_FRAGMENT (1006), + RS_PROGRAM_VERTEX (1007), + RS_PROGRAM_RASTER (1008), + RS_PROGRAM_STORE (1009), + RS_FONT (1010); int mID; int mSize; @@ -158,6 +158,14 @@ public class Element extends BaseObj { mID = id; mSize = size; } + + DataType(int id) { + mID = id; + mSize = 4; + if (RenderScript.sPointerSize == 8) { + mSize = 32; + } + } } /** diff --git a/rs/java/android/renderscript/FieldPacker.java b/rs/java/android/renderscript/FieldPacker.java index c9bba699250e..f39aa5fbe0f0 100644 --- a/rs/java/android/renderscript/FieldPacker.java +++ b/rs/java/android/renderscript/FieldPacker.java @@ -75,7 +75,7 @@ public class FieldPacker { mPos = 0; } public void reset(int i) { - if ((i < 0) || (i >= mLen)) { + if ((i < 0) || (i > mLen)) { throw new RSIllegalArgumentException("out of range argument: " + i); } mPos = i; @@ -605,6 +605,15 @@ public class FieldPacker { return mData; } + /** + * Get the actual length used for the FieldPacker. + * + * @hide + */ + public int getPos() { + return mPos; + } + private final byte mData[]; private int mPos; private int mLen; diff --git a/rs/java/android/renderscript/ProgramVertexFixedFunction.java b/rs/java/android/renderscript/ProgramVertexFixedFunction.java index 5173af27a44f..45840aee04a5 100644 --- a/rs/java/android/renderscript/ProgramVertexFixedFunction.java +++ b/rs/java/android/renderscript/ProgramVertexFixedFunction.java @@ -245,6 +245,9 @@ public class ProgramVertexFixedFunction extends ProgramVertex { for(int i = 0; i < 16; i ++) { mIOBuffer.addF32(m.mMat[i]); } + // Reset the buffer back to the end, since we want to flush all of + // the contents back (and not just what we wrote now). + mIOBuffer.reset(mIOBuffer.getData().length); mAlloc.setFromFieldPacker(0, mIOBuffer); } 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/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index e07463d83fac..9264186c6329 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -3005,13 +3005,15 @@ public final class ActivityStackSupervisor implements DisplayListener { } void setLockTaskModeLocked(TaskRecord task) { - final Message lockTaskMsg = Message.obtain(); if (task == null) { - // Take out of lock task mode. - lockTaskMsg.arg1 = mLockTaskModeTask.userId; - lockTaskMsg.what = LOCK_TASK_END_MSG; - mLockTaskModeTask = null; - mHandler.sendMessage(lockTaskMsg); + // Take out of lock task mode if necessary + if (mLockTaskModeTask != null) { + final Message lockTaskMsg = Message.obtain(); + lockTaskMsg.arg1 = mLockTaskModeTask.userId; + lockTaskMsg.what = LOCK_TASK_END_MSG; + mLockTaskModeTask = null; + mHandler.sendMessage(lockTaskMsg); + } return; } if (isLockTaskModeViolation(task)) { @@ -3021,6 +3023,8 @@ public final class ActivityStackSupervisor implements DisplayListener { mLockTaskModeTask = task; findTaskToMoveToFrontLocked(task, 0, null); resumeTopActivitiesLocked(); + + final Message lockTaskMsg = Message.obtain(); lockTaskMsg.obj = mLockTaskModeTask.intent.getComponent().getPackageName(); lockTaskMsg.arg1 = mLockTaskModeTask.userId; lockTaskMsg.what = LOCK_TASK_START_MSG; diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index 353f6036bcfc..e61bad918264 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -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,7 +458,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { final void addCecDevice(HdmiCecDeviceInfo info) { assertRunOnServiceThread(); addDeviceInfo(info); - + mService.invokeDeviceEventListeners(info, true); // TODO: announce new device detection. } @@ -466,10 +469,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..050ba46c0edd 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 @@ -171,8 +176,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); } @@ -663,15 +667,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 +700,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/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index 0e9a9cc5da51..cab27282ff1b 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import android.app.AppGlobals; import android.app.job.JobInfo; import android.app.job.JobScheduler; import android.app.job.JobService; @@ -31,8 +32,8 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.IPackageManager; import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ServiceInfo; import android.os.Binder; import android.os.Handler; @@ -616,10 +617,13 @@ public class JobSchedulerService extends com.android.server.SystemService // job that runs one of the app's services, as well as verifying that the // named service properly requires the BIND_JOB_SERVICE permission private void enforceValidJobRequest(int uid, JobInfo job) { - final PackageManager pm = getContext().getPackageManager(); + final IPackageManager pm = AppGlobals.getPackageManager(); final ComponentName service = job.getService(); try { - ServiceInfo si = pm.getServiceInfo(service, 0); + ServiceInfo si = pm.getServiceInfo(service, 0, UserHandle.getUserId(uid)); + if (si == null) { + throw new IllegalArgumentException("No such service " + service); + } if (si.applicationInfo.uid != uid) { throw new IllegalArgumentException("uid " + uid + " cannot schedule job in " + service.getPackageName()); @@ -628,8 +632,8 @@ public class JobSchedulerService extends com.android.server.SystemService throw new IllegalArgumentException("Scheduled service " + service + " does not require android.permission.BIND_JOB_SERVICE permission"); } - } catch (NameNotFoundException e) { - throw new IllegalArgumentException("No such service: " + service); + } catch (RemoteException e) { + // Can't happen; the Package Manager is in this same process } } 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/CrossProfileIntentFilter.java b/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java index 3d432dcd5536..3ce19c1fe43a 100644 --- a/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java +++ b/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java @@ -32,36 +32,32 @@ import android.os.UserHandle; */ class CrossProfileIntentFilter extends IntentFilter { private static final String ATTR_TARGET_USER_ID = "targetUserId"; - private static final String ATTR_USER_ID_DEST = "userIdDest";//Old name. Kept for compatibility. - private static final String ATTR_REMOVABLE = "removable"; + private static final String ATTR_FLAGS = "flags"; private static final String ATTR_FILTER = "filter"; private static final String TAG = "CrossProfileIntentFilter"; // If the intent matches the IntentFilter, then it can be forwarded to this userId. final int mTargetUserId; - boolean mRemovable; + final int mFlags; - CrossProfileIntentFilter(IntentFilter filter, boolean removable, int targetUserId) { + CrossProfileIntentFilter(IntentFilter filter, int targetUserId, int flags) { super(filter); mTargetUserId = targetUserId; - mRemovable = removable; + mFlags = flags; } public int getTargetUserId() { return mTargetUserId; } - public boolean isRemovable() { - return mRemovable; + public int getFlags() { + return mFlags; } CrossProfileIntentFilter(XmlPullParser parser) throws XmlPullParserException, IOException { String targetUserIdString = parser.getAttributeValue(null, ATTR_TARGET_USER_ID); if (targetUserIdString == null) { - targetUserIdString = parser.getAttributeValue(null, ATTR_USER_ID_DEST); - } - if (targetUserIdString == null) { String msg = "Missing element under " + TAG +": " + ATTR_TARGET_USER_ID + " at " + parser.getPositionDescription(); PackageManagerService.reportSettingsProblem(Log.WARN, msg); @@ -69,9 +65,14 @@ class CrossProfileIntentFilter extends IntentFilter { } else { mTargetUserId = Integer.parseInt(targetUserIdString); } - String removableString = parser.getAttributeValue(null, ATTR_REMOVABLE); - if (removableString != null) { - mRemovable = Boolean.parseBoolean(removableString); + String flagsString = parser.getAttributeValue(null, ATTR_FLAGS); + if (flagsString == null) { + String msg = "Missing element under " + TAG +": " + ATTR_FLAGS + " at " + + parser.getPositionDescription(); + PackageManagerService.reportSettingsProblem(Log.WARN, msg); + mFlags = 0; + } else { + mFlags = Integer.parseInt(flagsString); } int outerDepth = parser.getDepth(); String tagName = parser.getName(); @@ -104,7 +105,7 @@ class CrossProfileIntentFilter extends IntentFilter { public void writeToXml(XmlSerializer serializer) throws IOException { serializer.attribute(null, ATTR_TARGET_USER_ID, Integer.toString(mTargetUserId)); - serializer.attribute(null, ATTR_REMOVABLE, Boolean.toString(mRemovable)); + serializer.attribute(null, ATTR_FLAGS, Integer.toString(mFlags)); serializer.startTag(null, ATTR_FILTER); super.writeToXml(serializer); serializer.endTag(null, ATTR_FILTER); diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index dd3377142364..89ab2aeda45e 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -29,6 +29,7 @@ import android.content.pm.PackageInstallerParams; import android.content.pm.PackageManager; import android.content.pm.PackageParser; import android.content.pm.PackageParser.ApkLite; +import android.content.pm.PackageParser.PackageParserException; import android.content.pm.Signature; import android.os.Build; import android.os.Bundle; @@ -50,14 +51,10 @@ import com.android.internal.content.NativeLibraryHelper; import com.android.internal.util.ArrayUtils; import com.android.internal.util.Preconditions; -import libcore.io.IoUtils; import libcore.io.Libcore; -import libcore.io.Streams; import java.io.File; import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; @@ -297,11 +294,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { // Verify that all staged packages are internally consistent for (File file : files) { - final ApkLite info = PackageParser.parseApkLite(file.getAbsolutePath(), - PackageParser.PARSE_GET_SIGNATURES); - if (info == null) { + final ApkLite info; + try { + info = PackageParser.parseApkLite(file, PackageParser.PARSE_GET_SIGNATURES); + } catch (PackageParserException e) { throw new InstallFailedException(INSTALL_FAILED_INVALID_APK, - "Failed to parse " + file); + "Failed to parse " + file + ": " + e); } if (!seenSplits.add(info.splitName)) { @@ -356,11 +354,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { "Missing existing base package for " + mPackageName); } - final ApkLite info = PackageParser.parseApkLite(app.sourceDir, - PackageParser.PARSE_GET_SIGNATURES); - if (info == null) { + final ApkLite info; + try { + info = PackageParser.parseApkLite(new File(app.sourceDir), + PackageParser.PARSE_GET_SIGNATURES); + } catch (PackageParserException e) { throw new InstallFailedException(INSTALL_FAILED_INVALID_APK, - "Failed to parse existing base " + app.sourceDir); + "Failed to parse existing base " + app.sourceDir + ": " + e); } assertPackageConsistent("Existing base", info.packageName, info.versionCode, diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index dc7645576896..90e263a5d911 100755 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -147,6 +147,7 @@ import android.util.LogPrinter; import android.util.PrintStreamPrinter; import android.util.Slog; import android.util.SparseArray; +import android.util.SparseBooleanArray; import android.util.Xml; import android.view.Display; @@ -3347,7 +3348,7 @@ public class PackageManagerService extends IPackageManager.Stub { } /* - * Returns if intent can be forwarded from the userId from to dest + * Returns if intent can be forwarded from the sourceUserId to the targetUserId */ @Override public boolean canForwardTo(Intent intent, String resolvedType, int sourceUserId, @@ -3367,9 +3368,9 @@ public class PackageManagerService extends IPackageManager.Stub { private List<CrossProfileIntentFilter> getMatchingCrossProfileIntentFilters(Intent intent, String resolvedType, int userId) { - CrossProfileIntentResolver cpir = mSettings.mCrossProfileIntentResolvers.get(userId); - if (cpir != null) { - return cpir.queryIntent(intent, resolvedType, false, userId); + CrossProfileIntentResolver resolver = mSettings.mCrossProfileIntentResolvers.get(userId); + if (resolver != null) { + return resolver.queryIntent(intent, resolvedType, false, userId); } return null; } @@ -3402,36 +3403,24 @@ public class PackageManagerService extends IPackageManager.Stub { synchronized (mPackages) { final String pkgName = intent.getPackage(); if (pkgName == null) { - List<ResolveInfo> result = - mActivities.queryIntent(intent, resolvedType, flags, userId); - // Checking if we can forward the intent to another user - List<CrossProfileIntentFilter> cpifs = + List<ResolveInfo> result; + List<CrossProfileIntentFilter> matchingFilters = getMatchingCrossProfileIntentFilters(intent, resolvedType, userId); - if (cpifs != null) { - CrossProfileIntentFilter crossProfileIntentFilterWithResult = null; - HashSet<Integer> alreadyTriedUserIds = new HashSet<Integer>(); - for (CrossProfileIntentFilter cpif : cpifs) { - int targetUserId = cpif.getTargetUserId(); - // Two {@link CrossProfileIntentFilter}s can have the same targetUserId and - // match the same an intent. For performance reasons, it is better not to - // run queryIntent twice for the same userId - if (!alreadyTriedUserIds.contains(targetUserId)) { - List<ResolveInfo> resultUser = mActivities.queryIntent(intent, - resolvedType, flags, targetUserId); - if (resultUser != null) { - crossProfileIntentFilterWithResult = cpif; - // As soon as there is a match in another user, we add the - // intentForwarderActivity to the list of ResolveInfo. - break; - } - alreadyTriedUserIds.add(targetUserId); - } - } - if (crossProfileIntentFilterWithResult != null) { - ResolveInfo forwardingResolveInfo = createForwardingResolveInfo( - crossProfileIntentFilterWithResult, userId); - result.add(forwardingResolveInfo); - } + // Check for results that need to skip the current profile. + ResolveInfo resolveInfo = querySkipCurrentProfileIntents(matchingFilters, intent, + resolvedType, flags, userId); + if (resolveInfo != null) { + result = new ArrayList<ResolveInfo>(1); + result.add(resolveInfo); + return result; + } + // Check for results in the current profile. + result = mActivities.queryIntent(intent, resolvedType, flags, userId); + // Check for cross profile results. + resolveInfo = queryCrossProfileIntents( + matchingFilters, intent, resolvedType, flags, userId); + if (resolveInfo != null) { + result.add(resolveInfo); } return result; } @@ -3444,10 +3433,68 @@ public class PackageManagerService extends IPackageManager.Stub { } } - private ResolveInfo createForwardingResolveInfo(CrossProfileIntentFilter cpif, + private ResolveInfo querySkipCurrentProfileIntents( + List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType, + int flags, int sourceUserId) { + if (matchingFilters != null) { + int size = matchingFilters.size(); + for (int i = 0; i < size; i ++) { + CrossProfileIntentFilter filter = matchingFilters.get(i); + if ((filter.getFlags() & PackageManager.SKIP_CURRENT_PROFILE) != 0) { + // Checking if there are activities in the target user that can handle the + // intent. + ResolveInfo resolveInfo = checkTargetCanHandle(filter, intent, resolvedType, + flags, sourceUserId); + if (resolveInfo != null) { + return createForwardingResolveInfo(filter, sourceUserId); + } + } + } + } + return null; + } + + // Return matching ResolveInfo if any for skip current profile intent filters. + private ResolveInfo queryCrossProfileIntents( + List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType, + int flags, int sourceUserId) { + if (matchingFilters != null) { + // Two {@link CrossProfileIntentFilter}s can have the same targetUserId and + // match the same intent. For performance reasons, it is better not to + // run queryIntent twice for the same userId + SparseBooleanArray alreadyTriedUserIds = new SparseBooleanArray(); + int size = matchingFilters.size(); + for (int i = 0; i < size; i++) { + CrossProfileIntentFilter filter = matchingFilters.get(i); + int targetUserId = filter.getTargetUserId(); + if ((filter.getFlags() & PackageManager.SKIP_CURRENT_PROFILE) == 0 + && !alreadyTriedUserIds.get(targetUserId)) { + // Checking if there are activities in the target user that can handle the + // intent. + ResolveInfo resolveInfo = checkTargetCanHandle(filter, intent, resolvedType, + flags, sourceUserId); + if (resolveInfo != null) return resolveInfo; + alreadyTriedUserIds.put(targetUserId, true); + } + } + } + return null; + } + + private ResolveInfo checkTargetCanHandle(CrossProfileIntentFilter filter, Intent intent, + String resolvedType, int flags, int sourceUserId) { + List<ResolveInfo> resultTargetUser = mActivities.queryIntent(intent, + resolvedType, flags, filter.getTargetUserId()); + if (resultTargetUser != null) { + return createForwardingResolveInfo(filter, sourceUserId); + } + return null; + } + + private ResolveInfo createForwardingResolveInfo(CrossProfileIntentFilter filter, int sourceUserId) { String className; - int targetUserId = cpif.getTargetUserId(); + int targetUserId = filter.getTargetUserId(); if (targetUserId == UserHandle.USER_OWNER) { className = FORWARD_INTENT_TO_USER_OWNER; } else { @@ -3463,7 +3510,7 @@ public class PackageManagerService extends IPackageManager.Stub { forwardingResolveInfo.preferredOrder = 0; forwardingResolveInfo.match = 0; forwardingResolveInfo.isDefault = true; - forwardingResolveInfo.filter = cpif; + forwardingResolveInfo.filter = filter; return forwardingResolveInfo; } @@ -4182,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; @@ -4199,14 +4247,18 @@ public class PackageManagerService extends IPackageManager.Stub { String scanPath = scanFile.getPath(); if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanPath); parseFlags |= mDefParseFlags; - PackageParser pp = new PackageParser(scanPath); + PackageParser pp = new PackageParser(); pp.setSeparateProcesses(mSeparateProcesses); pp.setOnlyCoreApps(mOnlyCore); + pp.setDisplayMetrics(mMetrics); + + if ((scanMode & SCAN_TRUSTED_OVERLAY) != 0) { + parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY; + } final PackageParser.Package pkg; try { - pkg = pp.parseMonolithicPackage(scanFile, mMetrics, parseFlags, - (scanMode & SCAN_TRUSTED_OVERLAY) != 0); + pkg = pp.parseMonolithicPackage(scanFile, parseFlags); } catch (PackageParserException e) { mLastScanError = e.error; return null; @@ -4637,12 +4689,7 @@ public class PackageManagerService extends IPackageManager.Stub { } if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) { - final ArrayList<String> paths = new ArrayList<>(); - paths.add(pkg.codePath); - if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) { - Collections.addAll(paths, pkg.splitCodePaths); - } - + final Collection<String> paths = pkg.getAllCodePaths(); for (String path : paths) { try { boolean isDexOptNeededInternal = DexFile.isDexOptNeededInternal(path, @@ -4832,10 +4879,7 @@ public class PackageManagerService extends IPackageManager.Stub { } } if (p != null) { - usesLibraryFiles.add(p.codePath); - if (!ArrayUtils.isEmpty(p.splitCodePaths)) { - Collections.addAll(usesLibraryFiles, p.splitCodePaths); - } + usesLibraryFiles.addAll(p.getAllCodePaths()); } } @@ -5674,7 +5718,8 @@ public class PackageManagerService extends IPackageManager.Stub { try { ksm.addSigningKeySetToPackage(pkg.packageName, pkg.mSigningKeys); if (pkg.mKeySetMapping != null) { - for (Map.Entry<String, Set<PublicKey>> entry : pkg.mKeySetMapping.entrySet()) { + for (Map.Entry<String, ArraySet<PublicKey>> entry : + pkg.mKeySetMapping.entrySet()) { if (entry.getValue() != null) { ksm.addDefinedKeySetToPackage(pkg.packageName, entry.getValue(), entry.getKey()); @@ -9713,7 +9758,7 @@ public class PackageManagerService extends IPackageManager.Stub { return PackageManager.INSTALL_SUCCEEDED; } - }; + } static String getAsecPackageName(String packageCid) { int idx = packageCid.lastIndexOf("-"); @@ -10206,13 +10251,13 @@ public class PackageManagerService extends IPackageManager.Stub { int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) | (onSd ? PackageParser.PARSE_ON_SDCARD : 0); - PackageParser pp = new PackageParser(tmpPackageFile.getPath()); + PackageParser pp = new PackageParser(); pp.setSeparateProcesses(mSeparateProcesses); + pp.setDisplayMetrics(mMetrics); final PackageParser.Package pkg; try { - pkg = pp.parseMonolithicPackage(tmpPackageFile, mMetrics, - parseFlags); + pkg = pp.parseMonolithicPackage(tmpPackageFile, parseFlags); } catch (PackageParserException e) { res.returnCode = e.error; return; @@ -10228,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; @@ -11542,17 +11588,18 @@ public class PackageManagerService extends IPackageManager.Stub { } @Override - public void addCrossProfileIntentFilter(IntentFilter filter, boolean removable, - int sourceUserId, int targetUserId) { + public void addCrossProfileIntentFilter(IntentFilter intentFilter, int sourceUserId, + int targetUserId, int flags) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); - if (filter.countActions() == 0) { + if (intentFilter.countActions() == 0) { Slog.w(TAG, "Cannot set a crossProfile intent filter with no filter actions"); return; } synchronized (mPackages) { - mSettings.editCrossProfileIntentResolverLPw(sourceUserId).addFilter( - new CrossProfileIntentFilter(filter, removable, targetUserId)); + CrossProfileIntentFilter filter = new CrossProfileIntentFilter(intentFilter, + targetUserId, flags); + mSettings.editCrossProfileIntentResolverLPw(sourceUserId).addFilter(filter); mSettings.writePackageRestrictionsLPr(sourceUserId); } } @@ -11562,12 +11609,14 @@ public class PackageManagerService extends IPackageManager.Stub { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); synchronized (mPackages) { - CrossProfileIntentResolver cpir = + CrossProfileIntentResolver resolver = mSettings.editCrossProfileIntentResolverLPw(sourceUserId); HashSet<CrossProfileIntentFilter> set = - new HashSet<CrossProfileIntentFilter>(cpir.filterSet()); - for (CrossProfileIntentFilter cpif : set) { - if (cpif.isRemovable()) cpir.removeFilter(cpif); + new HashSet<CrossProfileIntentFilter>(resolver.filterSet()); + for (CrossProfileIntentFilter filter : set) { + if ((filter.getFlags() & PackageManager.SET_BY_PROFILE_OWNER) != 0) { + resolver.removeFilter(filter); + } } mSettings.writePackageRestrictionsLPr(sourceUserId); } diff --git a/services/core/java/com/android/server/tv/TvInputHal.java b/services/core/java/com/android/server/tv/TvInputHal.java index 34168a82141a..1535e7a9a934 100644 --- a/services/core/java/com/android/server/tv/TvInputHal.java +++ b/services/core/java/com/android/server/tv/TvInputHal.java @@ -94,8 +94,7 @@ final class TvInputHal { } // Called from native - private void deviceAvailableFromNative(int deviceId, int type) { - final TvInputHardwareInfo info = new TvInputHardwareInfo(deviceId, type); + private void deviceAvailableFromNative(final TvInputHardwareInfo info) { mHandler.post(new Runnable() { @Override public void run() { @@ -105,23 +104,21 @@ final class TvInputHal { }); } - private void deviceUnavailableFromNative(int deviceId) { - final int id = deviceId; + private void deviceUnavailableFromNative(final int deviceId) { mHandler.post(new Runnable() { @Override public void run() { - mCallback.onDeviceUnavailable(id); + mCallback.onDeviceUnavailable(deviceId); } }); } - private void streamConfigsChangedFromNative(int deviceId) { - final int id = deviceId; + private void streamConfigsChangedFromNative(final int deviceId) { mHandler.post(new Runnable() { @Override public void run() { - retrieveStreamConfigs(id); - mCallback.onStreamConfigurationChanged(id, mStreamConfigs); + retrieveStreamConfigs(deviceId); + mCallback.onStreamConfigurationChanged(deviceId, mStreamConfigs); } }); } diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java index d72ed9e3f73e..1146f0fc3f8d 100644 --- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java +++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java @@ -17,6 +17,11 @@ package com.android.server.tv; import android.content.Context; +import android.media.AudioDevicePort; +import android.media.AudioManager; +import android.media.AudioPatch; +import android.media.AudioPort; +import android.media.AudioPortConfig; import android.media.tv.ITvInputHardware; import android.media.tv.ITvInputHardwareCallback; import android.media.tv.TvInputHardwareInfo; @@ -48,11 +53,13 @@ class TvInputHardwareManager implements TvInputHal.Callback { private final List<TvInputHardwareInfo> mInfoList = new ArrayList<TvInputHardwareInfo>(); private final Context mContext; private final Set<Integer> mActiveHdmiSources = new HashSet<Integer>(); + private final AudioManager mAudioManager; private final Object mLock = new Object(); public TvInputHardwareManager(Context context) { mContext = context; + mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); // TODO(hdmi): mHdmiManager = mContext.getSystemService(...); // TODO(hdmi): mHdmiClient = mHdmiManager.getTvClient(); mHal.init(); @@ -258,12 +265,48 @@ class TvInputHardwareManager implements TvInputHal.Callback { private boolean mReleased = false; private final Object mImplLock = new Object(); + private final AudioDevicePort mAudioSource; + private final AudioDevicePort mAudioSink; + private AudioPatch mAudioPatch = null; + public TvInputHardwareImpl(TvInputHardwareInfo info) { mInfo = info; + AudioDevicePort audioSource = null; + AudioDevicePort audioSink = null; + if (mInfo.getAudioType() != AudioManager.DEVICE_NONE) { + ArrayList<AudioPort> devicePorts = new ArrayList<AudioPort>(); + if (mAudioManager.listAudioDevicePorts(devicePorts) == AudioManager.SUCCESS) { + // Find source + for (AudioPort port : devicePorts) { + AudioDevicePort devicePort = (AudioDevicePort) port; + if (devicePort.type() == mInfo.getAudioType() && + devicePort.address().equals(mInfo.getAudioAddress())) { + audioSource = devicePort; + break; + } + } + // Find sink + // TODO: App may want to specify sink device? + int sinkDevices = mAudioManager.getDevicesForStream(AudioManager.STREAM_MUSIC); + for (AudioPort port : devicePorts) { + AudioDevicePort devicePort = (AudioDevicePort) port; + if (devicePort.type() == sinkDevices) { + audioSink = devicePort; + break; + } + } + } + } + mAudioSource = audioSource; + mAudioSink = audioSink; } public void release() { synchronized (mImplLock) { + if (mAudioPatch != null) { + mAudioManager.releaseAudioPatch(mAudioPatch); + mAudioPatch = null; + } mReleased = true; } } @@ -288,6 +331,22 @@ class TvInputHardwareManager implements TvInputHal.Callback { } } } + if (mAudioSource != null && mAudioSink != null) { + if (surface != null) { + AudioPortConfig sourceConfig = mAudioSource.activeConfig(); + AudioPortConfig sinkConfig = mAudioSink.activeConfig(); + AudioPatch[] audioPatchArray = new AudioPatch[] { mAudioPatch }; + // TODO: build config if activeConfig() == null + mAudioManager.createAudioPatch( + audioPatchArray, + new AudioPortConfig[] { sourceConfig }, + new AudioPortConfig[] { sinkConfig }); + mAudioPatch = audioPatchArray[0]; + } else { + mAudioManager.releaseAudioPatch(mAudioPatch); + mAudioPatch = null; + } + } return mHal.setSurface(mInfo.getDeviceId(), surface, config) == TvInputHal.SUCCESS; } } @@ -299,7 +358,7 @@ class TvInputHardwareManager implements TvInputHal.Callback { throw new IllegalStateException("Device already released."); } } - // TODO + // TODO: Use AudioGain? } @Override diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp index afe629defa71..9cecdf0612d9 100644 --- a/services/core/jni/com_android_server_tv_TvInputHal.cpp +++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp @@ -54,6 +54,18 @@ static struct { jmethodID build; } gTvStreamConfigBuilderClassInfo; +static struct { + jclass clazz; + + jmethodID constructor; + jmethodID deviceId; + jmethodID type; + jmethodID hdmiPortId; + jmethodID audioType; + jmethodID audioAddress; + jmethodID build; +} gTvInputHardwareInfoBuilderClassInfo; + //////////////////////////////////////////////////////////////////////////////// class JTvInputHal { @@ -209,7 +221,6 @@ const tv_stream_config_t* JTvInputHal::getStreamConfigs(int deviceId, int* numCo return configs; } - // static void JTvInputHal::notify( tv_input_device_t* dev, tv_input_event_t* event, void* data) { @@ -232,11 +243,36 @@ void JTvInputHal::notify( void JTvInputHal::onDeviceAvailable(const tv_input_device_info_t& info) { JNIEnv* env = AndroidRuntime::getJNIEnv(); mConnections.add(info.device_id, Connection()); + + jobject builder = env->NewObject( + gTvInputHardwareInfoBuilderClassInfo.clazz, + gTvInputHardwareInfoBuilderClassInfo.constructor); + env->CallObjectMethod( + builder, gTvInputHardwareInfoBuilderClassInfo.deviceId, info.device_id); + env->CallObjectMethod( + builder, gTvInputHardwareInfoBuilderClassInfo.type, info.type); + if (info.type == TV_INPUT_TYPE_HDMI) { + env->CallObjectMethod( + builder, gTvInputHardwareInfoBuilderClassInfo.hdmiPortId, info.hdmi.port_id); + } + env->CallObjectMethod( + builder, gTvInputHardwareInfoBuilderClassInfo.audioType, info.audio_type); + if (info.audio_type != AUDIO_DEVICE_NONE) { + jstring audioAddress = env->NewStringUTF(info.audio_address); + env->CallObjectMethod( + builder, gTvInputHardwareInfoBuilderClassInfo.audioAddress, audioAddress); + env->DeleteLocalRef(audioAddress); + } + + jobject infoObject = env->CallObjectMethod(builder, gTvInputHardwareInfoBuilderClassInfo.build); + env->CallVoidMethod( mThiz, gTvInputHalClassInfo.deviceAvailable, - info.device_id, - info.type); + infoObject); + + env->DeleteLocalRef(builder); + env->DeleteLocalRef(infoObject); } void JTvInputHal::onDeviceUnavailable(int deviceId) { @@ -339,7 +375,8 @@ int register_android_server_tv_TvInputHal(JNIEnv* env) { FIND_CLASS(clazz, "com/android/server/tv/TvInputHal"); GET_METHOD_ID( - gTvInputHalClassInfo.deviceAvailable, clazz, "deviceAvailableFromNative", "(II)V"); + gTvInputHalClassInfo.deviceAvailable, clazz, + "deviceAvailableFromNative", "(Landroid/media/tv/TvInputHardwareInfo;)V"); GET_METHOD_ID( gTvInputHalClassInfo.deviceUnavailable, clazz, "deviceUnavailableFromNative", "(I)V"); GET_METHOD_ID( @@ -382,6 +419,40 @@ int register_android_server_tv_TvInputHal(JNIEnv* env) { gTvStreamConfigBuilderClassInfo.clazz, "build", "()Landroid/media/tv/TvStreamConfig;"); + FIND_CLASS(gTvInputHardwareInfoBuilderClassInfo.clazz, + "android/media/tv/TvInputHardwareInfo$Builder"); + gTvInputHardwareInfoBuilderClassInfo.clazz = + jclass(env->NewGlobalRef(gTvInputHardwareInfoBuilderClassInfo.clazz)); + + GET_METHOD_ID( + gTvInputHardwareInfoBuilderClassInfo.constructor, + gTvInputHardwareInfoBuilderClassInfo.clazz, + "<init>", "()V"); + GET_METHOD_ID( + gTvInputHardwareInfoBuilderClassInfo.deviceId, + gTvInputHardwareInfoBuilderClassInfo.clazz, + "deviceId", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); + GET_METHOD_ID( + gTvInputHardwareInfoBuilderClassInfo.type, + gTvInputHardwareInfoBuilderClassInfo.clazz, + "type", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); + GET_METHOD_ID( + gTvInputHardwareInfoBuilderClassInfo.hdmiPortId, + gTvInputHardwareInfoBuilderClassInfo.clazz, + "hdmiPortId", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); + GET_METHOD_ID( + gTvInputHardwareInfoBuilderClassInfo.audioType, + gTvInputHardwareInfoBuilderClassInfo.clazz, + "audioType", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); + GET_METHOD_ID( + gTvInputHardwareInfoBuilderClassInfo.audioAddress, + gTvInputHardwareInfoBuilderClassInfo.clazz, + "audioAddress", "(Ljava/lang/String;)Landroid/media/tv/TvInputHardwareInfo$Builder;"); + GET_METHOD_ID( + gTvInputHardwareInfoBuilderClassInfo.build, + gTvInputHardwareInfoBuilderClassInfo.clazz, + "build", "()Landroid/media/tv/TvInputHardwareInfo;"); + return 0; } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 5cf571330593..2801f4f84151 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -1322,7 +1322,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private void manageMonitoringCertificateNotification(Intent intent) { final NotificationManager notificationManager = getNotificationManager(); - final boolean hasCert = DevicePolicyManager.hasAnyCaCertsInstalled(); + final boolean hasCert = !(new TrustedCertificateStore().userAliases().isEmpty()); if (! hasCert) { if (intent.getAction().equals(KeyChain.ACTION_STORAGE_CHANGED)) { for (UserInfo user : mUserManager.getUsers()) { @@ -2382,13 +2382,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return !"".equals(state); } - public boolean installCaCert(byte[] certBuffer) throws RemoteException { - mContext.enforceCallingOrSelfPermission(MANAGE_CA_CERTIFICATES, null); - KeyChainConnection keyChainConnection = null; + public boolean installCaCert(ComponentName who, byte[] certBuffer) throws RemoteException { + if (who == null) { + mContext.enforceCallingOrSelfPermission(MANAGE_CA_CERTIFICATES, null); + } else { + synchronized (this) { + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + } + } + byte[] pemCert; try { X509Certificate cert = parseCert(certBuffer); - pemCert = Credentials.convertToPem(cert); + pemCert = Credentials.convertToPem(cert); } catch (CertificateException ce) { Log.e(LOG_TAG, "Problem converting cert", ce); return false; @@ -2396,20 +2402,24 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Log.e(LOG_TAG, "Problem reading cert", ioe); return false; } + + final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId()); + final long id = Binder.clearCallingIdentity(); try { - keyChainConnection = KeyChain.bind(mContext); + final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle); try { keyChainConnection.getService().installCaCertificate(pemCert); return true; + } catch (RemoteException e) { + Log.e(LOG_TAG, "installCaCertsToKeyChain(): ", e); } finally { - if (keyChainConnection != null) { - keyChainConnection.close(); - keyChainConnection = null; - } + keyChainConnection.close(); } } catch (InterruptedException e1) { Log.w(LOG_TAG, "installCaCertsToKeyChain(): ", e1); Thread.currentThread().interrupt(); + } finally { + Binder.restoreCallingIdentity(id); } return false; } @@ -2421,34 +2431,31 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { certBuffer)); } - public void uninstallCaCert(final byte[] certBuffer) { - mContext.enforceCallingOrSelfPermission(MANAGE_CA_CERTIFICATES, null); - TrustedCertificateStore certStore = new TrustedCertificateStore(); - String alias = null; - try { - X509Certificate cert = parseCert(certBuffer); - alias = certStore.getCertificateAlias(cert); - } catch (CertificateException ce) { - Log.e(LOG_TAG, "Problem creating X509Certificate", ce); - return; - } catch (IOException ioe) { - Log.e(LOG_TAG, "Problem reading certificate", ioe); - return; + public void uninstallCaCert(ComponentName who, String alias) { + if (who == null) { + mContext.enforceCallingOrSelfPermission(MANAGE_CA_CERTIFICATES, null); + } else { + synchronized (this) { + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + } } + + final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId()); + final long id = Binder.clearCallingIdentity(); try { - KeyChainConnection keyChainConnection = KeyChain.bind(mContext); - IKeyChainService service = keyChainConnection.getService(); + final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle); try { - service.deleteCaCertificate(alias); + keyChainConnection.getService().deleteCaCertificate(alias); } catch (RemoteException e) { Log.e(LOG_TAG, "from CaCertUninstaller: ", e); } finally { keyChainConnection.close(); - keyChainConnection = null; } } catch (InterruptedException ie) { Log.w(LOG_TAG, "CaCertUninstaller: ", ie); Thread.currentThread().interrupt(); + } finally { + Binder.restoreCallingIdentity(id); } } @@ -3454,12 +3461,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { long id = Binder.clearCallingIdentity(); try { if ((flags & DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED) != 0) { - pm.addCrossProfileIntentFilter(filter, true /*removable*/, callingUserId, - UserHandle.USER_OWNER); + pm.addCrossProfileIntentFilter(filter, callingUserId, UserHandle.USER_OWNER, + PackageManager.SET_BY_PROFILE_OWNER); } if ((flags & DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT) != 0) { - pm.addCrossProfileIntentFilter(filter, true /*removable*/, UserHandle.USER_OWNER, - callingUserId); + pm.addCrossProfileIntentFilter(filter, UserHandle.USER_OWNER, callingUserId, + PackageManager.SET_BY_PROFILE_OWNER); } } catch (RemoteException re) { // Shouldn't happen @@ -3480,6 +3487,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { long id = Binder.clearCallingIdentity(); try { pm.clearCrossProfileIntentFilters(callingUserId); + // If we want to support multiple managed profiles, we will have to only remove + // those that have callingUserId as their target. pm.clearCrossProfileIntentFilters(UserHandle.USER_OWNER); } catch (RemoteException re) { // Shouldn't happen diff --git a/telecomm/java/android/telecomm/TelecommManager.java b/telecomm/java/android/telecomm/TelecommManager.java index a97e7e499f5f..989c2cd0b19e 100644 --- a/telecomm/java/android/telecomm/TelecommManager.java +++ b/telecomm/java/android/telecomm/TelecommManager.java @@ -16,7 +16,9 @@ package android.telecomm; +import android.content.ComponentName; import android.content.Context; +import android.os.RemoteException; import com.android.internal.telecomm.ITelecommService; @@ -45,4 +47,14 @@ 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/telephony/java/com/android/internal/telephony/IMms.aidl b/telephony/java/com/android/internal/telephony/IMms.aidl new file mode 100644 index 000000000000..a745420a983d --- /dev/null +++ b/telephony/java/com/android/internal/telephony/IMms.aidl @@ -0,0 +1,47 @@ +/* + * 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.internal.telephony; + +import android.app.PendingIntent; + +/** + * Service interface to handle MMS API requests + */ +interface IMms { + /** + * Send an MMS message + * + * @param callingPkg the package name of the calling app + * @param pdu the MMS message encoded in standard MMS PDU format + * @param locationUrl the optional location url for where this message should be sent to + * @param sentIntent if not NULL this <code>PendingIntent</code> is + * broadcast when the message is successfully sent, or failed + */ + void sendMessage(String callingPkg, in byte[] pdu, String locationUrl, + in PendingIntent sentIntent); + + /** + * Download an MMS message using known location and transaction id + * + * @param callingPkg the package name of the calling app + * @param locationUrl the location URL of the MMS message to be downloaded, usually obtained + * from the MMS WAP push notification + * @param downloadedIntent if not NULL this <code>PendingIntent</code> is + * broadcast when the message is downloaded, or the download is failed + */ + void downloadMessage(String callingPkg, String locationUrl, in PendingIntent downloadedIntent); +} diff --git a/test-runner/Android.mk b/test-runner/Android.mk index 0d9e4f10e607..b12795c737c5 100644 --- a/test-runner/Android.mk +++ b/test-runner/Android.mk @@ -20,7 +20,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-java-files-under, src) -LOCAL_JAVA_LIBRARIES := core core-junit framework +LOCAL_JAVA_LIBRARIES := core-libart core-junit framework LOCAL_STATIC_JAVA_LIBRARIES := junit-runner LOCAL_MODULE:= android.test.runner diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java index 17db1b40cc45..a3b32b3e9f41 100644 --- a/test-runner/src/android/test/mock/MockPackageManager.java +++ b/test-runner/src/android/test/mock/MockPackageManager.java @@ -707,17 +707,8 @@ public class MockPackageManager extends PackageManager { * @hide */ @Override - public void addCrossProfileIntentFilter(IntentFilter filter, boolean removable, - int sourceUserId, int targetUserId) { - throw new UnsupportedOperationException(); - } - - /** - * @hide - */ - @Override - public void addForwardingIntentFilter(IntentFilter filter, boolean removable, int sourceUserId, - int targetUserId) { + public void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId, int targetUserId, + int flags) { throw new UnsupportedOperationException(); } @@ -729,14 +720,6 @@ public class MockPackageManager extends PackageManager { throw new UnsupportedOperationException(); } - /** - * @hide - */ - @Override - public void clearForwardingIntentFilters(int sourceUserId) { - throw new UnsupportedOperationException(); - } - /** {@hide} */ public PackageInstaller getPackageInstaller() { throw new UnsupportedOperationException(); diff --git a/tests/JobSchedulerTestApp/res/layout/activity_main.xml b/tests/JobSchedulerTestApp/res/layout/activity_main.xml index 7f4961b94040..d3429ff3cf21 100644 --- a/tests/JobSchedulerTestApp/res/layout/activity_main.xml +++ b/tests/JobSchedulerTestApp/res/layout/activity_main.xml @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" - android:layout_height="wrap_content" + android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical"> @@ -54,6 +54,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/constraints" + android:layout_margin="15dp" android:textSize="18dp"/> <LinearLayout android:layout_width="match_parent" @@ -83,43 +84,81 @@ </RadioGroup> </LinearLayout> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content"> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/timing"/> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginLeft="15dp" - android:textSize="17dp" - android:text="@string/delay"/> - <EditText - android:id="@+id/delay_time" - android:layout_width="60dp" - android:layout_height="wrap_content" - android:inputType="number"/> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/deadline" - android:textSize="17dp"/> - <EditText - android:id="@+id/deadline_time" - android:layout_width="60dp" - android:layout_height="wrap_content" - android:inputType="number"/> - </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content"> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/timing"/> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="15dp" + android:textSize="17dp" + android:text="@string/delay"/> + <EditText + android:id="@+id/delay_time" + android:layout_width="60dp" + android:layout_height="wrap_content" + android:inputType="number"/> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/deadline" + android:textSize="17dp"/> + <EditText + android:id="@+id/deadline_time" + android:layout_width="60dp" + android:layout_height="wrap_content" + android:inputType="number"/> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content"> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/charging_caption" + android:layout_marginRight="15dp"/> + <CheckBox + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/checkbox_charging" + android:text="@string/charging_text"/> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content"> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/idle_caption" + android:layout_marginRight="15dp"/> + <CheckBox + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/checkbox_idle" + android:text="@string/idle_mode_text"/> + </LinearLayout> </LinearLayout> <Button android:id="@+id/schedule_button" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_margin="40dp" + android:layout_marginTop="20dp" + android:layout_marginLeft="40dp" + android:layout_marginRight="40dp" android:onClick="scheduleJob" android:text="@string/schedule_job_button_text"/> + <Button + android:id="@+id/cancel_button" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="40dp" + android:layout_marginRight="40dp" + android:onClick="cancelAllJobs" + android:text="@string/cancel_all_jobs_button_text"/> </LinearLayout> -</LinearLayout> +</ScrollView> diff --git a/tests/JobSchedulerTestApp/res/values/strings.xml b/tests/JobSchedulerTestApp/res/values/strings.xml index 824d4b198446..eebfb1968aea 100644 --- a/tests/JobSchedulerTestApp/res/values/strings.xml +++ b/tests/JobSchedulerTestApp/res/values/strings.xml @@ -20,9 +20,13 @@ limitations under the License. <string name="onstarttask">onStartTask</string> <string name="defaultparamtext">task params will show up here.</string> <string name="schedule_job_button_text">Schedule Job</string> + <string name="cancel_all_jobs_button_text">Cancel all</string> <string name="app_name">Job Scheduler Test</string> <string name="finish_job_button_text">taskFinished</string> - <string name="manual_sync_text">Manual Sync</string> + <string name="idle_mode_text">Requires device in idle mode.</string> + <string name="charging_caption">Charging:</string> + <string name="charging_text">Requires device plugged in.</string> + <string name="idle_caption">Idle:</string> <string name="constraints">Constraints</string> <string name="connectivity">Connectivity:</string> <string name="any">Any</string> diff --git a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java index 15050efc5eab..e15929d9026c 100644 --- a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java +++ b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java @@ -19,7 +19,9 @@ package com.android.demo.jobSchedulerApp; import android.app.Activity; import android.app.job.JobInfo; import android.app.job.JobParameters; +import android.app.job.JobScheduler; import android.content.ComponentName; +import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.os.Bundle; @@ -28,6 +30,7 @@ import android.os.Message; import android.os.Messenger; import android.text.TextUtils; import android.view.View; +import android.widget.CheckBox; import android.widget.EditText; import android.widget.RadioButton; import android.widget.TextView; @@ -60,7 +63,8 @@ public class MainActivity extends Activity { mDeadlineEditText = (EditText) findViewById(R.id.deadline_time); mWiFiConnectivityRadioButton = (RadioButton) findViewById(R.id.checkbox_unmetered); mAnyConnectivityRadioButton = (RadioButton) findViewById(R.id.checkbox_any); - + mRequiresChargingCheckBox = (CheckBox) findViewById(R.id.checkbox_charging); + mRequiresIdleCheckbox = (CheckBox) findViewById(R.id.checkbox_idle); mServiceComponent = new ComponentName(this, TestJobService.class); // Start service and provide it a way to communicate with us. Intent startServiceIntent = new Intent(this, TestJobService.class); @@ -79,6 +83,9 @@ public class MainActivity extends Activity { EditText mDeadlineEditText; RadioButton mWiFiConnectivityRadioButton; RadioButton mAnyConnectivityRadioButton; + CheckBox mRequiresChargingCheckBox; + CheckBox mRequiresIdleCheckbox; + ComponentName mServiceComponent; /** Service object to interact scheduled jobs. */ TestJobService mTestService; @@ -124,24 +131,32 @@ public class MainActivity extends Activity { String delay = mDelayEditText.getText().toString(); if (delay != null && !TextUtils.isEmpty(delay)) { - builder.setMinimumLatency(Long.valueOf(delay)); + builder.setMinimumLatency(Long.valueOf(delay) * 1000); } String deadline = mDeadlineEditText.getText().toString(); if (deadline != null && !TextUtils.isEmpty(deadline)) { - builder.setOverrideDeadline(Long.valueOf(deadline)); + builder.setOverrideDeadline(Long.valueOf(deadline) * 1000); } - boolean requiresUnmetered = mWiFiConnectivityRadioButton.isSelected(); - boolean requiresAnyConnectivity = mAnyConnectivityRadioButton.isSelected(); + boolean requiresUnmetered = mWiFiConnectivityRadioButton.isChecked(); + boolean requiresAnyConnectivity = mAnyConnectivityRadioButton.isChecked(); if (requiresUnmetered) { builder.setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED); } else if (requiresAnyConnectivity) { builder.setRequiredNetworkCapabilities(JobInfo.NetworkType.ANY); } + builder.setRequiresDeviceIdle(mRequiresIdleCheckbox.isChecked()); + builder.setRequiresCharging(mRequiresChargingCheckBox.isChecked()); mTestService.scheduleJob(builder.build()); } + public void cancelAllJobs(View v) { + JobScheduler tm = + (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); + tm.cancelAll(); + } + /** * UI onclick listener to call jobFinished() in our service. */ 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/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk index 08486e643431..19428313b116 100644 --- a/tools/layoutlib/Android.mk +++ b/tools/layoutlib/Android.mk @@ -30,8 +30,8 @@ LOCAL_JAVACFLAGS := -source 6 -target 6 built_framework_dep := $(call java-lib-deps,framework-base) built_framework_classes := $(call java-lib-files,framework-base) -built_core_dep := $(call java-lib-deps,core) -built_core_classes := $(call java-lib-files,core) +built_core_dep := $(call java-lib-deps,core-libart) +built_core_classes := $(call java-lib-files,core-libart) built_ext_dep := $(call java-lib-deps,ext) built_ext_classes := $(call java-lib-files,ext) 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..777471dc5f57 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -376,7 +376,7 @@ public class WifiConfiguration implements Parcelable { public static int LOW_RSSI_24 = -75; /** @hide **/ - public static int BAD_RSSI_24 = -85; + public static int BAD_RSSI_24 = -87; /** @hide **/ public static int GOOD_RSSI_5 = -55; @@ -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,10 @@ 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 * 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; + } + } } |