Merge "When a window is first shown only draw once while animating." into jb-dev
diff --git a/Android.mk b/Android.mk
index 7ebf4b5..678ae55 100644
--- a/Android.mk
+++ b/Android.mk
@@ -198,6 +198,7 @@
media/java/android/media/IMediaScannerService.aidl \
media/java/android/media/IRemoteControlClient.aidl \
media/java/android/media/IRemoteControlDisplay.aidl \
+ media/java/android/media/IRingtonePlayer.aidl \
telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl \
telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
telephony/java/com/android/internal/telephony/ITelephony.aidl \
diff --git a/api/16.txt b/api/16.txt
index a04faf0..1fc3b54 100644
--- a/api/16.txt
+++ b/api/16.txt
@@ -24979,7 +24979,7 @@
method public void setMimeType(java.lang.String);
}
- public class WebSettings {
+ public abstract class WebSettings {
method public boolean enableSmoothTransition();
method public boolean getAllowContentAccess();
method public boolean getAllowFileAccess();
diff --git a/api/current.txt b/api/current.txt
index 9303937..284b11c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3871,6 +3871,7 @@
}
public class SearchManager implements android.content.DialogInterface.OnCancelListener android.content.DialogInterface.OnDismissListener {
+ method public android.content.ComponentName getGlobalSearchActivity();
method public android.app.SearchableInfo getSearchableInfo(android.content.ComponentName);
method public java.util.List<android.app.SearchableInfo> getSearchablesInGlobalSearch();
method public deprecated void onCancel(android.content.DialogInterface);
@@ -3894,6 +3895,7 @@
field public static final java.lang.String INTENT_ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS";
field public static final java.lang.String INTENT_ACTION_SEARCH_SETTINGS_CHANGED = "android.search.action.SETTINGS_CHANGED";
field public static final java.lang.String INTENT_ACTION_WEB_SEARCH_SETTINGS = "android.search.action.WEB_SEARCH_SETTINGS";
+ field public static final java.lang.String INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED = "android.search.action.GLOBAL_SEARCH_ACTIVITY_CHANGED";
field public static final char MENU_KEY = 115; // 0x0073 's'
field public static final int MENU_KEYCODE = 47; // 0x2f
field public static final java.lang.String QUERY = "query";
@@ -24491,12 +24493,12 @@
method public void startLayoutAnimation();
method public void startViewTransition(android.view.View);
method public void updateViewLayout(android.view.View, android.view.ViewGroup.LayoutParams);
+ field public static final int CLIP_BOUNDS = 0; // 0x0
field protected static final int CLIP_TO_PADDING_MASK = 34; // 0x22
- field public static final int COMPONENT_BOUNDS = 0; // 0x0
field public static final int FOCUS_AFTER_DESCENDANTS = 262144; // 0x40000
field public static final int FOCUS_BEFORE_DESCENDANTS = 131072; // 0x20000
field public static final int FOCUS_BLOCK_DESCENDANTS = 393216; // 0x60000
- field public static final int LAYOUT_BOUNDS = 1; // 0x1
+ field public static final int OPTICAL_BOUNDS = 1; // 0x1
field public static final int PERSISTENT_ALL_CACHES = 3; // 0x3
field public static final int PERSISTENT_ANIMATION_CACHE = 1; // 0x1
field public static final int PERSISTENT_NO_CACHE = 0; // 0x0
diff --git a/cmds/svc/src/com/android/commands/svc/Svc.java b/cmds/svc/src/com/android/commands/svc/Svc.java
index 1cd4c0d..0fbba11 100644
--- a/cmds/svc/src/com/android/commands/svc/Svc.java
+++ b/cmds/svc/src/com/android/commands/svc/Svc.java
@@ -94,6 +94,7 @@
COMMAND_HELP,
new PowerCommand(),
new DataCommand(),
- new WifiCommand()
+ new WifiCommand(),
+ new UsbCommand()
};
}
diff --git a/cmds/svc/src/com/android/commands/svc/UsbCommand.java b/cmds/svc/src/com/android/commands/svc/UsbCommand.java
new file mode 100644
index 0000000..b8d8d95
--- /dev/null
+++ b/cmds/svc/src/com/android/commands/svc/UsbCommand.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.commands.svc;
+
+import android.content.Context;;
+import android.hardware.usb.IUsbManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemProperties;
+
+public class UsbCommand extends Svc.Command {
+ public UsbCommand() {
+ super("usb");
+ }
+
+ public String shortHelp() {
+ return "Control Usb state";
+ }
+
+ public String longHelp() {
+ return shortHelp() + "\n"
+ + "\n"
+ + "usage: svc usb setFunction [function]\n"
+ + " Set the current usb function.\n\n"
+ + " svc usb getFunction\n"
+ + " Gets the list of currently enabled functions\n";
+ }
+
+ public void run(String[] args) {
+ boolean validCommand = false;
+ if (args.length >= 2) {
+ if ("setFunction".equals(args[1])) {
+ IUsbManager usbMgr = IUsbManager.Stub.asInterface(ServiceManager.getService(
+ Context.USB_SERVICE));
+ try {
+ usbMgr.setCurrentFunction((args.length >=3 ? args[2] : null), false);
+ } catch (RemoteException e) {
+ System.err.println("Error communicating with UsbManager: " + e);
+ }
+ return;
+ } else if ("getFunction".equals(args[1])) {
+ System.err.println(SystemProperties.get("sys.usb.config"));
+ return;
+ }
+ }
+ System.err.println(longHelp());
+ }
+}
diff --git a/core/java/android/animation/TimeAnimator.java b/core/java/android/animation/TimeAnimator.java
index a79f2a3..088d20d 100644
--- a/core/java/android/animation/TimeAnimator.java
+++ b/core/java/android/animation/TimeAnimator.java
@@ -14,16 +14,6 @@
@Override
boolean animationFrame(long currentTime) {
- if (mPlayingState == STOPPED) {
- mPlayingState = RUNNING;
- if (mSeekTime < 0) {
- mStartTime = currentTime;
- } else {
- mStartTime = currentTime - mSeekTime;
- // Now that we're playing, reset the seek time
- mSeekTime = -1;
- }
- }
if (mListener != null) {
long totalTime = currentTime - mStartTime;
long deltaTime = (mPreviousTime < 0) ? 0 : (currentTime - mPreviousTime);
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 2154b14..326f27c 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -56,11 +56,6 @@
private static float sDurationScale = 1.0f;
/**
- * Messages sent to timing handler: START is sent when an animation first begins.
- */
- static final int ANIMATION_START = 0;
-
- /**
* Values used with internal variable mPlayingState to indicate the current state of an
* animation.
*/
@@ -504,7 +499,7 @@
mPlayingState = SEEKED;
}
mStartTime = currentTime - playTime;
- animationFrame(currentTime);
+ doAnimationFrame(currentTime);
}
/**
@@ -528,8 +523,9 @@
* the same times for calculating their values, which makes synchronizing
* animations possible.
*
+ * The handler uses the Choreographer for executing periodic callbacks.
*/
- private static class AnimationHandler extends Handler implements Runnable {
+ private static class AnimationHandler implements Runnable {
// The per-thread list of all active animations
private final ArrayList<ValueAnimator> mAnimations = new ArrayList<ValueAnimator>();
@@ -552,34 +548,13 @@
}
/**
- * The START message is sent when an animation's start() method is called.
- * It cannot start synchronously when start() is called
- * because the call may be on the wrong thread, and it would also not be
- * synchronized with other animations because it would not start on a common
- * timing pulse. So each animation sends a START message to the handler, which
- * causes the handler to place the animation on the active animations queue and
- * start processing frames for that animation.
+ * Start animating on the next frame.
*/
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case ANIMATION_START:
- // If there are already active animations, or if another ANIMATION_START
- // message was processed during this frame, then the pending list may already
- // have been cleared. If that's the case, we've already processed the
- // active animations for this frame - don't do it again.
- if (mPendingAnimations.size() > 0) {
- doAnimationFrame();
- }
- break;
- }
+ public void start() {
+ scheduleAnimation();
}
- private void doAnimationFrame() {
- // currentTime holds the common time for all animations processed
- // during this frame
- long currentTime = AnimationUtils.currentAnimationTimeMillis();
-
+ private void doAnimationFrame(long frameTime) {
// mPendingAnimations holds any animations that have requested to be started
// We're going to clear mPendingAnimations, but starting animation may
// cause more to be added to the pending list (for example, if one animation
@@ -605,7 +580,7 @@
int numDelayedAnims = mDelayedAnims.size();
for (int i = 0; i < numDelayedAnims; ++i) {
ValueAnimator anim = mDelayedAnims.get(i);
- if (anim.delayedAnimationFrame(currentTime)) {
+ if (anim.delayedAnimationFrame(frameTime)) {
mReadyAnims.add(anim);
}
}
@@ -626,7 +601,7 @@
int i = 0;
while (i < numAnims) {
ValueAnimator anim = mAnimations.get(i);
- if (anim.animationFrame(currentTime)) {
+ if (anim.doAnimationFrame(frameTime)) {
mEndingAnims.add(anim);
}
if (mAnimations.size() == numAnims) {
@@ -652,10 +627,8 @@
// If there are still active or delayed animations, schedule a future call to
// onAnimate to process the next frame of the animations.
- if (!mAnimationScheduled
- && (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty())) {
- mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, this, null);
- mAnimationScheduled = true;
+ if (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty()) {
+ scheduleAnimation();
}
}
@@ -663,7 +636,14 @@
@Override
public void run() {
mAnimationScheduled = false;
- doAnimationFrame();
+ doAnimationFrame(mChoreographer.getFrameTime());
+ }
+
+ private void scheduleAnimation() {
+ if (!mAnimationScheduled) {
+ mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, this, null);
+ mAnimationScheduled = true;
+ }
}
}
@@ -935,7 +915,7 @@
mRunning = true;
notifyStartListeners();
}
- animationHandler.sendEmptyMessage(ANIMATION_START);
+ animationHandler.start();
}
@Override
@@ -1098,17 +1078,6 @@
*/
boolean animationFrame(long currentTime) {
boolean done = false;
-
- if (mPlayingState == STOPPED) {
- mPlayingState = RUNNING;
- if (mSeekTime < 0) {
- mStartTime = currentTime;
- } else {
- mStartTime = currentTime - mSeekTime;
- // Now that we're playing, reset the seek time
- mSeekTime = -1;
- }
- }
switch (mPlayingState) {
case RUNNING:
case SEEKED:
@@ -1144,6 +1113,31 @@
}
/**
+ * Processes a frame of the animation, adjusting the start time if needed.
+ *
+ * @param frameTime The frame time.
+ * @return true if the animation has ended.
+ */
+ final boolean doAnimationFrame(long frameTime) {
+ if (mPlayingState == STOPPED) {
+ mPlayingState = RUNNING;
+ if (mSeekTime < 0) {
+ mStartTime = frameTime;
+ } else {
+ mStartTime = frameTime - mSeekTime;
+ // Now that we're playing, reset the seek time
+ mSeekTime = -1;
+ }
+ }
+ // The frame time might be before the start time during the first frame of
+ // an animation. The "current time" must always be on or after the start
+ // time to avoid animating frames at negative time intervals. In practice, this
+ // is very rare and only happens when seeking backwards.
+ final long currentTime = Math.max(frameTime, mStartTime);
+ return animationFrame(currentTime);
+ }
+
+ /**
* Returns the current animation fraction, which is the elapsed/interpolated fraction used in
* the most recent frame update on the animation.
*
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 4add7f4..ab245f5 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2714,7 +2714,7 @@
onCreateNavigateUpTaskStack(b);
onPrepareNavigateUpTaskStack(b);
b.startActivities();
- finish();
+ finishAffinity();
} else {
navigateUpTo(upIntent);
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 0a996df..69689c9 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
+import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
@@ -213,7 +214,7 @@
/**
* Use this constant as the value for audioStreamType to request that
* the default stream type for notifications be used. Currently the
- * default stream type is STREAM_RING.
+ * default stream type is {@link AudioManager#STREAM_NOTIFICATION}.
*/
public static final int STREAM_DEFAULT = -1;
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 2ff45fb..691ee30 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -395,11 +395,7 @@
/**
* Intent action to be broadcast to inform that the global search provider
- * has changed. Normal components will have no need to handle this intent since
- * they should be using API methods from this class to access the global search
- * activity
- *
- * @hide
+ * has changed.
*/
public final static String INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED
= "android.search.action.GLOBAL_SEARCH_ACTIVITY_CHANGED";
@@ -590,8 +586,6 @@
/**
* Gets the name of the global search activity.
- *
- * @hide
*/
public ComponentName getGlobalSearchActivity() {
try {
diff --git a/core/java/android/content/CancellationSignal.java b/core/java/android/content/CancellationSignal.java
index 2dbbe54..dcaeeb7 100644
--- a/core/java/android/content/CancellationSignal.java
+++ b/core/java/android/content/CancellationSignal.java
@@ -25,6 +25,7 @@
private boolean mIsCanceled;
private OnCancelListener mOnCancelListener;
private ICancellationSignal mRemote;
+ private boolean mCancelInProgress;
/**
* Creates a cancellation signal, initially not canceled.
@@ -59,18 +60,32 @@
* If the operation has not yet started, then it will be canceled as soon as it does.
*/
public void cancel() {
+ final OnCancelListener listener;
+ final ICancellationSignal remote;
synchronized (this) {
- if (!mIsCanceled) {
- mIsCanceled = true;
- if (mOnCancelListener != null) {
- mOnCancelListener.onCancel();
+ if (mIsCanceled) {
+ return;
+ }
+ mIsCanceled = true;
+ mCancelInProgress = true;
+ listener = mOnCancelListener;
+ remote = mRemote;
+ }
+
+ try {
+ if (listener != null) {
+ listener.onCancel();
+ }
+ if (remote != null) {
+ try {
+ remote.cancel();
+ } catch (RemoteException ex) {
}
- if (mRemote != null) {
- try {
- mRemote.cancel();
- } catch (RemoteException ex) {
- }
- }
+ }
+ } finally {
+ synchronized (this) {
+ mCancelInProgress = false;
+ notifyAll();
}
}
}
@@ -86,38 +101,62 @@
* If {@link CancellationSignal#cancel} has already been called, then the provided
* listener is invoked immediately.
*
- * The listener is called while holding the cancellation signal's lock which is
- * also held while registering or unregistering the listener. Because of the lock,
- * it is not possible for the listener to run after it has been unregistered.
- * This design choice makes it easier for clients of {@link CancellationSignal} to
- * prevent race conditions related to listener registration and unregistration.
+ * This method is guaranteed that the listener will not be called after it
+ * has been removed.
*
* @param listener The cancellation listener, or null to remove the current listener.
*/
public void setOnCancelListener(OnCancelListener listener) {
synchronized (this) {
+ waitForCancelFinishedLocked();
+
+ if (mOnCancelListener == listener) {
+ return;
+ }
mOnCancelListener = listener;
- if (mIsCanceled && listener != null) {
- listener.onCancel();
+ if (!mIsCanceled || listener == null) {
+ return;
}
}
+ listener.onCancel();
}
/**
* Sets the remote transport.
*
+ * If {@link CancellationSignal#cancel} has already been called, then the provided
+ * remote transport is canceled immediately.
+ *
+ * This method is guaranteed that the remote transport will not be called after it
+ * has been removed.
+ *
* @param remote The remote transport, or null to remove.
*
* @hide
*/
public void setRemote(ICancellationSignal remote) {
synchronized (this) {
+ waitForCancelFinishedLocked();
+
+ if (mRemote == remote) {
+ return;
+ }
mRemote = remote;
- if (mIsCanceled && remote != null) {
- try {
- remote.cancel();
- } catch (RemoteException ex) {
- }
+ if (!mIsCanceled || remote == null) {
+ return;
+ }
+ }
+ try {
+ remote.cancel();
+ } catch (RemoteException ex) {
+ }
+ }
+
+ private void waitForCancelFinishedLocked() {
+ while (mCancelInProgress) {
+ try {
+ wait();
+ } catch (InterruptedException ex) {
}
}
}
diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java
index 5c8e38bf..a175662 100644
--- a/core/java/android/database/sqlite/SQLiteConnectionPool.java
+++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java
@@ -594,6 +594,7 @@
(connectionFlags & CONNECTION_FLAG_PRIMARY_CONNECTION_AFFINITY) != 0;
final ConnectionWaiter waiter;
+ final int nonce;
synchronized (mLock) {
throwIfClosedLocked();
@@ -636,73 +637,75 @@
mConnectionWaiterQueue = waiter;
}
- if (cancellationSignal != null) {
- final int nonce = waiter.mNonce;
- cancellationSignal.setOnCancelListener(new CancellationSignal.OnCancelListener() {
- @Override
- public void onCancel() {
- synchronized (mLock) {
- cancelConnectionWaiterLocked(waiter, nonce);
- }
- }
- });
- }
+ nonce = waiter.mNonce;
}
- // Park the thread until a connection is assigned or the pool is closed.
- // Rethrow an exception from the wait, if we got one.
- long busyTimeoutMillis = CONNECTION_POOL_BUSY_MILLIS;
- long nextBusyTimeoutTime = waiter.mStartTime + busyTimeoutMillis;
- for (;;) {
- // Detect and recover from connection leaks.
- if (mConnectionLeaked.compareAndSet(true, false)) {
+ // Set up the cancellation listener.
+ if (cancellationSignal != null) {
+ cancellationSignal.setOnCancelListener(new CancellationSignal.OnCancelListener() {
+ @Override
+ public void onCancel() {
+ synchronized (mLock) {
+ if (waiter.mNonce == nonce) {
+ cancelConnectionWaiterLocked(waiter);
+ }
+ }
+ }
+ });
+ }
+ try {
+ // Park the thread until a connection is assigned or the pool is closed.
+ // Rethrow an exception from the wait, if we got one.
+ long busyTimeoutMillis = CONNECTION_POOL_BUSY_MILLIS;
+ long nextBusyTimeoutTime = waiter.mStartTime + busyTimeoutMillis;
+ for (;;) {
+ // Detect and recover from connection leaks.
+ if (mConnectionLeaked.compareAndSet(true, false)) {
+ synchronized (mLock) {
+ wakeConnectionWaitersLocked();
+ }
+ }
+
+ // Wait to be unparked (may already have happened), a timeout, or interruption.
+ LockSupport.parkNanos(this, busyTimeoutMillis * 1000000L);
+
+ // Clear the interrupted flag, just in case.
+ Thread.interrupted();
+
+ // Check whether we are done waiting yet.
synchronized (mLock) {
- wakeConnectionWaitersLocked();
+ throwIfClosedLocked();
+
+ final SQLiteConnection connection = waiter.mAssignedConnection;
+ final RuntimeException ex = waiter.mException;
+ if (connection != null || ex != null) {
+ recycleConnectionWaiterLocked(waiter);
+ if (connection != null) {
+ return connection;
+ }
+ throw ex; // rethrow!
+ }
+
+ final long now = SystemClock.uptimeMillis();
+ if (now < nextBusyTimeoutTime) {
+ busyTimeoutMillis = now - nextBusyTimeoutTime;
+ } else {
+ logConnectionPoolBusyLocked(now - waiter.mStartTime, connectionFlags);
+ busyTimeoutMillis = CONNECTION_POOL_BUSY_MILLIS;
+ nextBusyTimeoutTime = now + busyTimeoutMillis;
+ }
}
}
-
- // Wait to be unparked (may already have happened), a timeout, or interruption.
- LockSupport.parkNanos(this, busyTimeoutMillis * 1000000L);
-
- // Clear the interrupted flag, just in case.
- Thread.interrupted();
-
- // Check whether we are done waiting yet.
- synchronized (mLock) {
- throwIfClosedLocked();
-
- final SQLiteConnection connection = waiter.mAssignedConnection;
- final RuntimeException ex = waiter.mException;
- if (connection != null || ex != null) {
- if (cancellationSignal != null) {
- cancellationSignal.setOnCancelListener(null);
- }
- recycleConnectionWaiterLocked(waiter);
- if (connection != null) {
- return connection;
- }
- throw ex; // rethrow!
- }
-
- final long now = SystemClock.uptimeMillis();
- if (now < nextBusyTimeoutTime) {
- busyTimeoutMillis = now - nextBusyTimeoutTime;
- } else {
- logConnectionPoolBusyLocked(now - waiter.mStartTime, connectionFlags);
- busyTimeoutMillis = CONNECTION_POOL_BUSY_MILLIS;
- nextBusyTimeoutTime = now + busyTimeoutMillis;
- }
+ } finally {
+ // Remove the cancellation listener.
+ if (cancellationSignal != null) {
+ cancellationSignal.setOnCancelListener(null);
}
}
}
// Can't throw.
- private void cancelConnectionWaiterLocked(ConnectionWaiter waiter, int nonce) {
- if (waiter.mNonce != nonce) {
- // Waiter already removed and recycled.
- return;
- }
-
+ private void cancelConnectionWaiterLocked(ConnectionWaiter waiter) {
if (waiter.mAssignedConnection != null || waiter.mException != null) {
// Waiter is done waiting but has not woken up yet.
return;
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 1cb15a6..b319cd5 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -69,18 +69,15 @@
private static final boolean USE_VSYNC = SystemProperties.getBoolean(
"debug.choreographer.vsync", true);
- // Enable/disable allowing traversals to proceed immediately if no drawing occurred
- // during the previous frame. When true, the Choreographer can degrade more gracefully
- // if drawing takes longer than a frame, but it may potentially block in eglSwapBuffers()
- // if there are two dirty buffers enqueued.
- // When false, we always schedule traversals on strict vsync boundaries.
- private static final boolean USE_PIPELINING = SystemProperties.getBoolean(
- "debug.choreographer.pipeline", false);
+ // Enable/disable using the frame time instead of returning now.
+ private static final boolean USE_FRAME_TIME = SystemProperties.getBoolean(
+ "debug.choreographer.frametime", true);
+
+ private static final long NANOS_PER_MS = 1000000;
private static final int MSG_DO_FRAME = 0;
private static final int MSG_DO_SCHEDULE_VSYNC = 1;
private static final int MSG_DO_SCHEDULE_CALLBACK = 2;
- private static final int MSG_DO_TRAVERSAL = 3;
private final Object mLock = new Object();
@@ -93,9 +90,8 @@
private final CallbackQueue[] mCallbackQueues;
private boolean mFrameScheduled;
- private long mLastFrameTime;
- private boolean mDrewLastFrame;
- private boolean mTraversalScheduled;
+ private boolean mCallbacksRunning;
+ private long mLastFrameTimeNanos;
/**
* Callback type: Input callback. Runs first.
@@ -119,7 +115,7 @@
mLooper = looper;
mHandler = new FrameHandler(looper);
mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null;
- mLastFrameTime = Long.MIN_VALUE;
+ mLastFrameTimeNanos = Long.MIN_VALUE;
mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
for (int i = 0; i <= CALLBACK_LAST; i++) {
@@ -236,35 +232,11 @@
}
synchronized (mLock) {
- if (USE_PIPELINING && callbackType == CALLBACK_INPUT) {
- Message msg = Message.obtain(mHandler, action);
- msg.setAsynchronous(true);
- mHandler.sendMessage(msg);
- return;
- }
-
final long now = SystemClock.uptimeMillis();
final long dueTime = now + delayMillis;
mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
if (dueTime <= now) {
- if (USE_PIPELINING && callbackType == CALLBACK_TRAVERSAL) {
- if (!mDrewLastFrame) {
- if (DEBUG) {
- Log.d(TAG, "Scheduling traversal immediately.");
- }
- if (!mTraversalScheduled) {
- mTraversalScheduled = true;
- Message msg = mHandler.obtainMessage(MSG_DO_TRAVERSAL);
- msg.setAsynchronous(true);
- mHandler.sendMessageAtTime(msg, dueTime);
- }
- return;
- }
- if (DEBUG) {
- Log.d(TAG, "Scheduling traversal on next frame.");
- }
- }
scheduleFrameLocked(now);
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
@@ -306,23 +278,36 @@
}
/**
- * Tells the choreographer that the application has actually drawn to a surface.
+ * Gets the time when the current frame started. The frame time should be used
+ * instead of {@link SystemClock#uptimeMillis()} to synchronize animations.
+ * This helps to reduce inter-frame jitter because the frame time is fixed at the
+ * time the frame was scheduled to start, regardless of when the animations or
+ * drawing code actually ran.
*
- * It uses this information to determine whether to draw immediately or to
- * post a draw to the next vsync because it might otherwise block.
+ * This method should only be called from within a callback.
+ *
+ * @return The frame start time, in the {@link SystemClock#uptimeMillis()} time base.
+ *
+ * @throws IllegalStateException if no frame is in progress.
*/
- public void notifyDrawOccurred() {
- if (DEBUG) {
- Log.d(TAG, "Draw occurred.");
- }
+ public long getFrameTime() {
+ return getFrameTimeNanos() / NANOS_PER_MS;
+ }
- if (USE_PIPELINING) {
- synchronized (mLock) {
- if (!mDrewLastFrame) {
- mDrewLastFrame = true;
- scheduleFrameLocked(SystemClock.uptimeMillis());
- }
+ /**
+ * Same as {@link #getFrameTime()} but with nanosecond precision.
+ *
+ * @return The frame start time, in the {@link System#nanoTime()} time base.
+ *
+ * @throws IllegalStateException if no frame is in progress.
+ */
+ public long getFrameTimeNanos() {
+ synchronized (mLock) {
+ if (!mCallbacksRunning) {
+ throw new IllegalStateException("This method must only be called as "
+ + "part of a callback while a frame is in progress.");
}
+ return USE_FRAME_TIME ? mLastFrameTimeNanos : System.nanoTime();
}
}
@@ -345,7 +330,8 @@
mHandler.sendMessageAtFrontOfQueue(msg);
}
} else {
- final long nextFrameTime = Math.max(mLastFrameTime + sFrameDelay, now);
+ final long nextFrameTime = Math.max(
+ mLastFrameTimeNanos / NANOS_PER_MS + sFrameDelay, now);
if (DEBUG) {
Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms.");
}
@@ -356,14 +342,18 @@
}
}
- void doFrame(int frame) {
+ void doFrame(long timestampNanos, int frame) {
synchronized (mLock) {
if (!mFrameScheduled) {
return; // no work to do
}
mFrameScheduled = false;
- mLastFrameTime = SystemClock.uptimeMillis();
- mDrewLastFrame = false;
+ mLastFrameTimeNanos = timestampNanos;
+ }
+
+ final long startNanos;
+ if (DEBUG) {
+ startNanos = System.nanoTime();
}
doCallbacks(Choreographer.CALLBACK_INPUT);
@@ -371,25 +361,24 @@
doCallbacks(Choreographer.CALLBACK_TRAVERSAL);
if (DEBUG) {
+ final long endNanos = System.nanoTime();
Log.d(TAG, "Frame " + frame + ": Finished, took "
- + (SystemClock.uptimeMillis() - mLastFrameTime) + " ms.");
+ + (endNanos - startNanos) * 0.000001f + " ms, latency "
+ + (startNanos - timestampNanos) * 0.000001f + " ms.");
}
}
void doCallbacks(int callbackType) {
- final long start;
Callback callbacks;
synchronized (mLock) {
- start = SystemClock.uptimeMillis();
- callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(start);
-
- if (USE_PIPELINING && callbackType == CALLBACK_TRAVERSAL && mTraversalScheduled) {
- mTraversalScheduled = false;
- mHandler.removeMessages(MSG_DO_TRAVERSAL);
+ final long now = SystemClock.uptimeMillis();
+ callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(now);
+ if (callbacks == null) {
+ return;
}
+ mCallbacksRunning = true;
}
-
- if (callbacks != null) {
+ try {
for (Callback c = callbacks; c != null; c = c.next) {
if (DEBUG) {
Log.d(TAG, "RunCallback: type=" + callbackType
@@ -398,8 +387,9 @@
}
c.action.run();
}
-
+ } finally {
synchronized (mLock) {
+ mCallbacksRunning = false;
do {
final Callback next = callbacks.next;
recycleCallbackLocked(callbacks);
@@ -428,15 +418,6 @@
}
}
- void doTraversal() {
- synchronized (mLock) {
- if (mTraversalScheduled) {
- mTraversalScheduled = false;
- doCallbacks(CALLBACK_TRAVERSAL);
- }
- }
- }
-
private void scheduleVsyncLocked() {
mDisplayEventReceiver.scheduleVsync();
}
@@ -475,7 +456,7 @@
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_DO_FRAME:
- doFrame(0);
+ doFrame(System.nanoTime(), 0);
break;
case MSG_DO_SCHEDULE_VSYNC:
doScheduleVsync();
@@ -483,9 +464,6 @@
case MSG_DO_SCHEDULE_CALLBACK:
doScheduleCallback(msg.arg1);
break;
- case MSG_DO_TRAVERSAL:
- doTraversal();
- break;
}
}
}
@@ -497,7 +475,7 @@
@Override
public void onVsync(long timestampNanos, int frame) {
- doFrame(frame);
+ doFrame(timestampNanos, frame);
}
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index b9295c3..c0771c5 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -72,7 +72,7 @@
* "true", to enable partial invalidates
* "false", to disable partial invalidates
*/
- static final String RENDER_DIRTY_REGIONS_PROPERTY = "hwui.render_dirty_regions";
+ static final String RENDER_DIRTY_REGIONS_PROPERTY = "debug.hwui.render_dirty_regions";
/**
* System property used to enable or disable vsync.
@@ -82,7 +82,7 @@
* "true", to disable vsync
* "false", to enable vsync
*/
- static final String DISABLE_VSYNC_PROPERTY = "hwui.disable_vsync";
+ static final String DISABLE_VSYNC_PROPERTY = "debug.hwui.disable_vsync";
/**
* System property used to enable or disable hardware rendering profiling.
@@ -95,8 +95,10 @@
* Possible values:
* "true", to enable profiling
* "false", to disable profiling
+ *
+ * @hide
*/
- static final String PROFILE_PROPERTY = "hwui.profile";
+ public static final String PROFILE_PROPERTY = "debug.hwui.profile";
/**
* System property used to specify the number of frames to be used
@@ -110,7 +112,7 @@
* Possible values:
* "60", to set the limit of frames to 60
*/
- static final String PROFILE_MAXFRAMES_PROPERTY = "hwui.profile.maxframes";
+ static final String PROFILE_MAXFRAMES_PROPERTY = "debug.hwui.profile.maxframes";
/**
* System property used to debug EGL configuration choice.
@@ -119,7 +121,7 @@
* "choice", print the chosen configuration only
* "all", print all possible configurations
*/
- static final String PRINT_CONFIG_PROPERTY = "hwui.print_config";
+ static final String PRINT_CONFIG_PROPERTY = "debug.hwui.print_config";
/**
* Turn on to draw dirty regions every other frame.
@@ -127,8 +129,10 @@
* Possible values:
* "true", to enable dirty regions debugging
* "false", to disable dirty regions debugging
+ *
+ * @hide
*/
- static final String DEBUG_DIRTY_REGIONS_PROPERTY = "hwui.debug_dirty_regions";
+ public static final String DEBUG_DIRTY_REGIONS_PROPERTY = "debug.hwui.show_dirty_regions";
/**
* A process can set this flag to false to prevent the use of hardware
diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java
index 6a457ec..9c56782 100644
--- a/core/java/android/view/InputEventReceiver.java
+++ b/core/java/android/view/InputEventReceiver.java
@@ -46,7 +46,8 @@
InputChannel inputChannel, MessageQueue messageQueue);
private static native void nativeDispose(int receiverPtr);
private static native void nativeFinishInputEvent(int receiverPtr, int seq, boolean handled);
- private static native void nativeConsumeBatchedInputEvents(int receiverPtr);
+ private static native void nativeConsumeBatchedInputEvents(int receiverPtr,
+ long frameTimeNanos);
/**
* Creates an input event receiver bound to the specified input channel.
@@ -114,7 +115,7 @@
* immediately (such as a pointer up event).
*/
public void onBatchedInputEventPending() {
- consumeBatchedInputEvents();
+ consumeBatchedInputEvents(-1);
}
/**
@@ -150,13 +151,16 @@
*
* This method forces all batched input events to be delivered immediately.
* Should be called just before animating or drawing a new frame in the UI.
+ *
+ * @param frameTimeNanos The time in the {@link System#nanoTime()} time base
+ * when the current display frame started rendering, or -1 if unknown.
*/
- public final void consumeBatchedInputEvents() {
+ public final void consumeBatchedInputEvents(long frameTimeNanos) {
if (mReceiverPtr == 0) {
Log.w(TAG, "Attempted to consume batched input events but the input event "
+ "receiver has already been disposed.");
} else {
- nativeConsumeBatchedInputEvents(mReceiverPtr);
+ nativeConsumeBatchedInputEvents(mReceiverPtr, frameTimeNanos);
}
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b65bf8f..588bb06 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -648,6 +648,13 @@
protected static final String VIEW_LOG_TAG = "View";
/**
+ * When set to true, apps will draw debugging information about their layouts.
+ *
+ * @hide
+ */
+ public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
+
+ /**
* Used to mark a View that has no ID.
*/
public static final int NO_ID = -1;
@@ -13846,7 +13853,7 @@
/**
* @hide
*/
- public Insets getLayoutInsets() {
+ public Insets getOpticalInsets() {
if (mLayoutInsets == null) {
mLayoutInsets = (mBackground == null) ? Insets.NONE : mBackground.getLayoutInsets();
}
@@ -16903,7 +16910,7 @@
/**
* Show where the margins, bounds and layout bounds are for each view.
*/
- final boolean mDebugLayout = SystemProperties.getBoolean("debug.layout", false);
+ final boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
/**
* Creates a new set of attachment information with the specified
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 9009e9ae..467e285 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -173,10 +173,9 @@
protected int mGroupFlags;
/*
- * THe layout mode: either {@link #UNDEFINED_LAYOUT_MODE}, {@link #COMPONENT_BOUNDS} or
- * {@link #LAYOUT_BOUNDS}
+ * The layout mode: either {@link #CLIP_BOUNDS} or {@link #OPTICAL_BOUNDS}
*/
- private int mLayoutMode = UNDEFINED_LAYOUT_MODE;
+ private int mLayoutMode = CLIP_BOUNDS;
/**
* NOTE: If you change the flags below make sure to reflect the changes
@@ -345,19 +344,20 @@
// Layout Modes
- private static final int UNDEFINED_LAYOUT_MODE = -1;
-
/**
* This constant is a {@link #setLayoutMode(int) layoutMode}.
- * Component bounds are the raw values of {@link #getLeft() left}, {@link #getTop() top},
+ * Clip bounds are the raw values of {@link #getLeft() left}, {@link #getTop() top},
* {@link #getRight() right} and {@link #getBottom() bottom}.
*/
- public static final int COMPONENT_BOUNDS = 0;
+ public static final int CLIP_BOUNDS = 0;
/**
* This constant is a {@link #setLayoutMode(int) layoutMode}.
+ * Optical bounds describe where a widget appears to be. They sit inside the clip
+ * bounds which need to cover a larger area to allow other effects,
+ * such as shadows and glows, to be drawn.
*/
- public static final int LAYOUT_BOUNDS = 1;
+ public static final int OPTICAL_BOUNDS = 1;
/**
* We clip to padding when FLAG_CLIP_TO_PADDING and FLAG_PADDING_NOT_NULL
@@ -382,15 +382,8 @@
private static final int ARRAY_INITIAL_CAPACITY = 12;
private static final int ARRAY_CAPACITY_INCREMENT = 12;
- private static Paint DEBUG_PAINT;
-
- private static Paint getDebugPaint() {
- if (DEBUG_PAINT == null) {
- DEBUG_PAINT = new Paint();
- DEBUG_PAINT.setStyle(Paint.Style.STROKE);
- }
- return DEBUG_PAINT;
- }
+ private static Paint sDebugPaint;
+ private static float[] sDebugLines;
// Used to draw cached views
Paint mCachePaint;
@@ -2678,7 +2671,8 @@
private static void drawRect(Canvas canvas, int x1, int y1, int x2, int y2, int color) {
Paint paint = getDebugPaint();
paint.setColor(color);
- canvas.drawRect(x1, y1, x2 - 1, y2 - 1, paint);
+
+ canvas.drawLines(getDebugLines(x1, y1, x2, y2), paint);
}
/**
@@ -2696,10 +2690,10 @@
*/
protected void onDebugDraw(Canvas canvas) {
// Draw optical bounds
- if (getLayoutMode() == LAYOUT_BOUNDS) {
+ if (getLayoutMode() == OPTICAL_BOUNDS) {
for (int i = 0; i < getChildCount(); i++) {
View c = getChildAt(i);
- Insets insets = c.getLayoutInsets();
+ Insets insets = c.getOpticalInsets();
drawRect(canvas,
c.getLeft() + insets.left,
c.getTop() + insets.top,
@@ -4597,37 +4591,22 @@
}
/**
- * Returns the basis of alignment during the layout of this view group:
- * either {@link #COMPONENT_BOUNDS} or {@link #LAYOUT_BOUNDS}.
+ * Returns the basis of alignment during layout operations on this view group:
+ * either {@link #CLIP_BOUNDS} or {@link #OPTICAL_BOUNDS}.
*
* @return the layout mode to use during layout operations
*
* @see #setLayoutMode(int)
*/
public int getLayoutMode() {
- if (mLayoutMode == UNDEFINED_LAYOUT_MODE) {
- ViewParent parent = getParent();
- if (parent instanceof ViewGroup) {
- ViewGroup viewGroup = (ViewGroup) parent;
- return viewGroup.getLayoutMode();
- } else {
- int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
- boolean preJellyBean = targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN;
- return preJellyBean ? COMPONENT_BOUNDS : LAYOUT_BOUNDS;
- }
-
- }
return mLayoutMode;
}
/**
- * Sets the basis of alignment during alignment of this view group.
- * Valid values are either {@link #COMPONENT_BOUNDS} or {@link #LAYOUT_BOUNDS}.
+ * Sets the basis of alignment during the layout of this view group.
+ * Valid values are either {@link #CLIP_BOUNDS} or {@link #OPTICAL_BOUNDS}.
* <p>
- * The default is to query the property of the parent if this view group has a parent.
- * If this ViewGroup is the root of the view hierarchy the default
- * value is {@link #LAYOUT_BOUNDS} for target SDK's greater than JellyBean,
- * {@link #LAYOUT_BOUNDS} otherwise.
+ * The default is {@link #CLIP_BOUNDS}.
*
* @param layoutMode the layout mode to use during layout operations
*
@@ -6136,4 +6115,43 @@
mLocation.set(0, 0, 0, 0);
}
}
+
+ private static Paint getDebugPaint() {
+ if (sDebugPaint == null) {
+ sDebugPaint = new Paint();
+ sDebugPaint.setAntiAlias(false);
+ }
+ return sDebugPaint;
+ }
+
+ private static float[] getDebugLines(int x1, int y1, int x2, int y2) {
+ if (sDebugLines== null) {
+ sDebugLines = new float[16];
+ }
+
+ x2--;
+ y2--;
+
+ sDebugLines[0] = x1;
+ sDebugLines[1] = y1;
+ sDebugLines[2] = x2;
+ sDebugLines[3] = y1;
+
+ sDebugLines[4] = x2;
+ sDebugLines[5] = y1;
+ sDebugLines[6] = x2;
+ sDebugLines[7] = y2 + 1;
+
+ sDebugLines[8] = x2 + 1;
+ sDebugLines[9] = y2;
+ sDebugLines[10] = x1;
+ sDebugLines[11] = y2;
+
+ sDebugLines[12] = x1;
+ sDebugLines[13] = y2;
+ sDebugLines[14] = x1;
+ sDebugLines[15] = y1;
+
+ return sDebugLines;
+ }
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ef9649a..c5c7746 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -948,6 +948,7 @@
mTraversalBarrier = mHandler.getLooper().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
+ scheduleConsumeBatchedInput();
}
}
@@ -965,9 +966,6 @@
mTraversalScheduled = false;
mHandler.getLooper().removeSyncBarrier(mTraversalBarrier);
- doConsumeBatchedInput(false);
- doProcessInputEvents();
-
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
@@ -2007,7 +2005,6 @@
final boolean fullRedrawNeeded = mFullRedrawNeeded;
mFullRedrawNeeded = false;
- mChoreographer.notifyDrawOccurred();
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
try {
@@ -4235,20 +4232,13 @@
}
}
- void doConsumeBatchedInput(boolean callback) {
+ void doConsumeBatchedInput(long frameTimeNanos) {
if (mConsumeBatchedInputScheduled) {
mConsumeBatchedInputScheduled = false;
- if (!callback) {
- mChoreographer.removeCallbacks(Choreographer.CALLBACK_INPUT,
- mConsumedBatchedInputRunnable, null);
+ if (mInputEventReceiver != null) {
+ mInputEventReceiver.consumeBatchedInputEvents(frameTimeNanos);
}
- }
-
- // Always consume batched input events even if not scheduled, because there
- // might be new input there waiting for us that we have no noticed yet because
- // the Looper has not had a chance to run again.
- if (mInputEventReceiver != null) {
- mInputEventReceiver.consumeBatchedInputEvents();
+ doProcessInputEvents();
}
}
@@ -4286,8 +4276,7 @@
final class ConsumeBatchedInputRunnable implements Runnable {
@Override
public void run() {
- doConsumeBatchedInput(true);
- doProcessInputEvents();
+ doConsumeBatchedInput(mChoreographer.getFrameTimeNanos());
}
}
final ConsumeBatchedInputRunnable mConsumedBatchedInputRunnable =
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 56e8b30..b5690e9 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -345,6 +345,14 @@
View curView = root.getView();
root.mAddNesting = 0;
+
+ if (view != null) {
+ InputMethodManager imm = InputMethodManager.getInstance(view.getContext());
+ if (imm != null) {
+ imm.windowDismissed(mViews[index].getWindowToken());
+ }
+ }
+
root.die(true);
finishRemoveViewLocked(curView, index);
if (curView == view) {
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 067be39..1803352 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -672,6 +672,7 @@
* Disconnect any existing input connection, clearing the served view.
*/
void finishInputLocked() {
+ mCurRootView = null;
mNextServedView = null;
if (mServedView != null) {
if (DEBUG) Log.v(TAG, "FINISH INPUT: " + mServedView);
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index e17e048..cb10d0a 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -581,10 +581,10 @@
}
private int getDefaultMargin(View c, boolean isAtEdge, boolean horizontal, boolean leading) {
- return isAtEdge ? DEFAULT_CONTAINER_MARGIN : getDefaultMargin(c, horizontal, leading);
+ return /*isAtEdge ? DEFAULT_CONTAINER_MARGIN :*/ getDefaultMargin(c, horizontal, leading);
}
- private int getDefaultMarginValue(View c, LayoutParams p, boolean horizontal, boolean leading) {
+ private int getDefaultMargin(View c, LayoutParams p, boolean horizontal, boolean leading) {
if (!useDefaultMargins) {
return 0;
}
@@ -602,7 +602,7 @@
int margin = horizontal ?
(leading ? lp.leftMargin : lp.rightMargin) :
(leading ? lp.topMargin : lp.bottomMargin);
- return margin == UNDEFINED ? getDefaultMarginValue(view, lp, horizontal, leading) : margin;
+ return margin == UNDEFINED ? getDefaultMargin(view, lp, horizontal, leading) : margin;
}
private int getMargin(View view, boolean horizontal, boolean leading) {
@@ -777,11 +777,12 @@
LayoutParams lp = new LayoutParams();
for (int i = 0; i < getChildCount(); i++) {
View c = getChildAt(i);
+ Insets insets = getLayoutMode() == OPTICAL_BOUNDS ? c.getOpticalInsets() : Insets.NONE;
lp.setMargins(
- getMargin1(c, true, true),
- getMargin1(c, false, true),
- getMargin1(c, true, false),
- getMargin1(c, false, false));
+ getMargin1(c, true, true) - insets.left,
+ getMargin1(c, false, true) - insets.top,
+ getMargin1(c, true, false) - insets.right,
+ getMargin1(c, false, false) - insets.bottom);
lp.onDebugDraw(c, canvas);
}
}
@@ -946,7 +947,12 @@
}
private int getMeasurement(View c, boolean horizontal) {
- return horizontal ? c.getMeasuredWidth() : c.getMeasuredHeight();
+ int result = horizontal ? c.getMeasuredWidth() : c.getMeasuredHeight();
+ if (getLayoutMode() == OPTICAL_BOUNDS) {
+ Insets insets = c.getOpticalInsets();
+ return result - (horizontal ? insets.left + insets.right : insets.top + insets.bottom);
+ }
+ return result;
}
final int getMeasurementIncludingMargin(View c, boolean horizontal) {
@@ -1052,6 +1058,14 @@
targetWidth - width - paddingRight - rightMargin - dx;
int cy = paddingTop + y1 + gravityOffsetY + alignmentOffsetY + topMargin;
+ boolean useLayoutBounds = getLayoutMode() == OPTICAL_BOUNDS;
+ if (useLayoutBounds) {
+ Insets insets = c.getOpticalInsets();
+ cx -= insets.left;
+ cy -= insets.top;
+ width += (insets.left + insets.right);
+ height += (insets.top + insets.bottom);
+ }
if (width != c.getMeasuredWidth() || height != c.getMeasuredHeight()) {
c.measure(makeMeasureSpec(width, EXACTLY), makeMeasureSpec(height, EXACTLY));
}
@@ -2135,21 +2149,8 @@
return before + after;
}
- private int getAlignmentValue(GridLayout gl, View c, int size, Alignment a, boolean horiz) {
- boolean useLayoutBounds = gl.getLayoutMode() == LAYOUT_BOUNDS;
- if (!useLayoutBounds) {
- return a.getAlignmentValue(c, size);
- } else {
- Insets insets = c.getLayoutInsets();
- int leadingInset = horiz ? insets.left : insets.top; // RTL?
- int trailingInset = horiz ? insets.right : insets.bottom; // RTL?
- int totalInset = leadingInset + trailingInset;
- return leadingInset + a.getAlignmentValue(c, size - totalInset);
- }
- }
-
protected int getOffset(GridLayout gl, View c, Alignment a, int size, boolean horizontal) {
- return before - getAlignmentValue(gl, c, size, a, horizontal);
+ return before - a.getAlignmentValue(c, size, gl.getLayoutMode());
}
protected final void include(GridLayout gl, View c, Spec spec, Axis axis) {
@@ -2158,7 +2159,7 @@
int size = gl.getMeasurementIncludingMargin(c, horizontal);
Alignment alignment = gl.getAlignment(spec.alignment, horizontal);
// todo test this works correctly when the returned value is UNDEFINED
- int before = getAlignmentValue(gl, c, size, alignment, horizontal);
+ int before = alignment.getAlignmentValue(c, size, gl.getLayoutMode());
include(before, size - before);
}
@@ -2441,9 +2442,10 @@
*
* @param view the view to which this alignment should be applied
* @param viewSize the measured size of the view
+ * @param mode the basis of alignment: CLIP or OPTICAL
* @return the alignment value
*/
- abstract int getAlignmentValue(View view, int viewSize);
+ abstract int getAlignmentValue(View view, int viewSize, int mode);
/**
* Returns the size of the view specified by this alignment.
@@ -2473,7 +2475,7 @@
}
@Override
- public int getAlignmentValue(View view, int viewSize) {
+ public int getAlignmentValue(View view, int viewSize, int mode) {
return UNDEFINED;
}
};
@@ -2489,7 +2491,7 @@
}
@Override
- public int getAlignmentValue(View view, int viewSize) {
+ public int getAlignmentValue(View view, int viewSize, int mode) {
return 0;
}
};
@@ -2505,7 +2507,7 @@
}
@Override
- public int getAlignmentValue(View view, int viewSize) {
+ public int getAlignmentValue(View view, int viewSize, int mode) {
return viewSize;
}
};
@@ -2542,8 +2544,8 @@
}
@Override
- public int getAlignmentValue(View view, int viewSize) {
- return (!view.isLayoutRtl() ? ltr : rtl).getAlignmentValue(view, viewSize);
+ public int getAlignmentValue(View view, int viewSize, int mode) {
+ return (!view.isLayoutRtl() ? ltr : rtl).getAlignmentValue(view, viewSize, mode);
}
};
}
@@ -2572,7 +2574,7 @@
}
@Override
- public int getAlignmentValue(View view, int viewSize) {
+ public int getAlignmentValue(View view, int viewSize, int mode) {
return viewSize >> 1;
}
};
@@ -2591,9 +2593,16 @@
}
@Override
- public int getAlignmentValue(View view, int viewSize) {
+ public int getAlignmentValue(View view, int viewSize, int mode) {
int baseline = view.getBaseline();
- return (baseline == -1) ? UNDEFINED : baseline;
+ if (baseline == -1) {
+ return UNDEFINED;
+ } else {
+ if (mode == OPTICAL_BOUNDS) {
+ return baseline - view.getOpticalInsets().top;
+ }
+ return baseline;
+ }
}
@Override
@@ -2644,7 +2653,7 @@
}
@Override
- public int getAlignmentValue(View view, int viewSize) {
+ public int getAlignmentValue(View view, int viewSize, int mode) {
return UNDEFINED;
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 36b1cd6..b2ad25d 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -2148,6 +2148,7 @@
/**
* @return the size (in pixels) of the default text size in this TextView.
*/
+ @ViewDebug.ExportedProperty(category = "text")
public float getTextSize() {
return mTextPaint.getTextSize();
}
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 19bc154..074afa3 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -207,7 +207,7 @@
uint32_t consumerSeq;
InputEvent* myEvent = NULL;
- status_t res = mConsumer.consume(&mPooledInputEventFactory, true /*consumeBatches*/,
+ status_t res = mConsumer.consume(&mPooledInputEventFactory, true /*consumeBatches*/, -1,
&consumerSeq, &myEvent);
if (res != android::OK) {
if (res != android::WOULD_BLOCK) {
diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp
index 8f6f5f4..08e08b9 100644
--- a/core/jni/android_view_InputEventReceiver.cpp
+++ b/core/jni/android_view_InputEventReceiver.cpp
@@ -52,7 +52,7 @@
status_t initialize();
status_t finishInputEvent(uint32_t seq, bool handled);
- status_t consumeEvents(JNIEnv* env, bool consumeBatches);
+ status_t consumeEvents(JNIEnv* env, bool consumeBatches, nsecs_t frameTime);
protected:
virtual ~NativeInputEventReceiver();
@@ -130,15 +130,16 @@
}
JNIEnv* env = AndroidRuntime::getJNIEnv();
- status_t status = r->consumeEvents(env, false /*consumeBatches*/);
+ status_t status = r->consumeEvents(env, false /*consumeBatches*/, -1);
r->mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
return status == OK || status == NO_MEMORY ? 1 : 0;
}
-status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, bool consumeBatches) {
+status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
+ bool consumeBatches, nsecs_t frameTime) {
#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s.", getInputChannelName(),
- consumeBatches ? "true" : "false");
+ ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s, frameTime=%lld.",
+ getInputChannelName(), consumeBatches ? "true" : "false", frameTime);
#endif
if (consumeBatches) {
@@ -150,7 +151,7 @@
uint32_t seq;
InputEvent* inputEvent;
status_t status = mInputConsumer.consume(&mInputEventFactory,
- consumeBatches, &seq, &inputEvent);
+ consumeBatches, frameTime, &seq, &inputEvent);
if (status) {
if (status == WOULD_BLOCK) {
if (!skipCallbacks && !mBatchedInputEventPending
@@ -270,10 +271,11 @@
}
}
-static void nativeConsumeBatchedInputEvents(JNIEnv* env, jclass clazz, jint receiverPtr) {
+static void nativeConsumeBatchedInputEvents(JNIEnv* env, jclass clazz, jint receiverPtr,
+ jlong frameTimeNanos) {
sp<NativeInputEventReceiver> receiver =
reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
- status_t status = receiver->consumeEvents(env, true /*consumeBatches*/);
+ status_t status = receiver->consumeEvents(env, true /*consumeBatches*/, frameTimeNanos);
if (status && status != DEAD_OBJECT && !env->ExceptionCheck()) {
String8 message;
message.appendFormat("Failed to consume batched input event. status=%d", status);
@@ -291,7 +293,7 @@
(void*)nativeDispose },
{ "nativeFinishInputEvent", "(IIZ)V",
(void*)nativeFinishInputEvent },
- { "nativeConsumeBatchedInputEvents", "(I)V",
+ { "nativeConsumeBatchedInputEvents", "(IJ)V",
(void*)nativeConsumeBatchedInputEvents },
};
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3ae2b4e..471a496 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -628,6 +628,11 @@
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="signature" />
+ <!-- Allows registration for remote audio playback. @hide -->
+ <permission android:name="android.permission.REMOTE_AUDIO_PLAYBACK"
+ android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+ android:protectionLevel="signature" />
+
<!-- =========================================== -->
<!-- Permissions associated with telephony state -->
<!-- =========================================== -->
diff --git a/core/res/res/layout/choose_type_and_account.xml b/core/res/res/layout/choose_type_and_account.xml
index 5a05126..d7068b7bf 100644
--- a/core/res/res/layout/choose_type_and_account.xml
+++ b/core/res/res/layout/choose_type_and_account.xml
@@ -38,7 +38,7 @@
<View android:layout_height="3dip"
android:layout_width="match_parent"
android:background="#323232"/>
-
+
<TextView android:id="@+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -56,7 +56,12 @@
android:layout_weight="1"
android:scrollbarAlwaysDrawVerticalTrack="true" />
+ <View android:layout_height="1dip"
+ android:layout_width="match_parent"
+ android:background="?android:attr/dividerHorizontal" />
+
<Button android:id="@+id/addAccount"
+ style="?android:attr/buttonBarButtonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="2dip"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index e7edaf7..e033d22 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -224,7 +224,7 @@
<string name="permlab_removeTasks" msgid="6821513401870377403">"stop lopende programme"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Laat die program toe om take te verwyder en hul programme te dood. Kwaadwillige programme kan die gedrag van ander programme ontwrig."</string>
<string name="permlab_startAnyActivity" msgid="2918768238045206456">"begin enige aktiwiteit"</string>
- <string name="permdesc_startAnyActivity" msgid="997823695343584001">"Laat die program toe om \'n aktiwiteit te begin, ongeag van toestemming-beskerming of uitgevoerde status."</string>
+ <string name="permdesc_startAnyActivity" msgid="997823695343584001">"Laat die program toe om \'n aktiwiteit te begin, ongeag toestemming-beskerming of uitgevoerde status."</string>
<string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"stel skermversoenbaarheid"</string>
<string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Laat die program toe om om die skermversoenbaarheid-modus van ander programme te beheer. Kwaadwillige programme kan die gedrag van ander programme breek."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"aktiveer programontfouting"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 89b00d0..8f0ad171 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -146,8 +146,8 @@
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"ጡባዊዎ ይዘጋል።"</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"ስልክዎ ይዘጋል።"</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"ዘግተህ መውጣት ትፈልጋለህ?"</string>
- <string name="reboot_safemode_title" msgid="7054509914500140361">"ወደ ጥንቁቅ ሁናቴ ውስጥ ዳግም አስጀምር"</string>
- <string name="reboot_safemode_confirm" msgid="55293944502784668">"ወደ ጥንቁቅ ሁናቴ ውስጥ ዳግም ማስጀመር ትፈልጋለህ? ይሄ ሁሉንም የጫንካቸው የሶስተኛ ወገን መተግበሪያዎችን ያሰናክላል። እንደገና ዳግም ስታስጀምር ይመለስሉሃል።"</string>
+ <string name="reboot_safemode_title" msgid="7054509914500140361">"በአስተማማኝ ኹነታ ውስጥ ዳግም አስጀምር"</string>
+ <string name="reboot_safemode_confirm" msgid="55293944502784668">"በአስተማማኝ ኹነታ ውስጥ ዳግም ማስጀመር ትፈልጋለህ? ይሄ ሁሉንም የጫንካቸው የሶስተኛ ወገን መተግበሪያዎችን ያሰናክላል። እንደገና ዳግም ስታስጀምር ይመለስሉሃል።"</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"የቅርብ ጊዜ"</string>
<string name="no_recent_tasks" msgid="8794906658732193473">"ምንም የቅርብ ጊዜ ትግበራዎች የሉም"</string>
<string name="global_actions" product="tablet" msgid="408477140088053665">"የጡባዊ አማራጮች"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 870ada0..a22a17e 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"للسماح للتطبيق بتلقي رسائل WAP ومعالجتها. قد تراقب بعض التطبيقات الضارة رسائلك أو تحذفها بدون عرضها لك."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"استرداد التطبيقات التي قيد التشغيل"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"للسماح للتطبيق باسترداد معلومات حول المهام المُشغلة الحالية والحديثة. قد تكتشف التطبيقات الضارة معلومات خاصة حول التطبيقات الأخرى."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"استرداد تفاصيل التطبيقات قيد التشغيل"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"للسماح للتطبيق باسترداد معلومات تفصيلية حول المهام قيد التشغيل حاليًا ومؤخرًا. قد تكتشف التطبيقات الضارة معلومات خاصة حول التطبيقات الأخرى."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"إعادة ترتيب التطبيقات قيد التشغيل"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"للسماح لتطبيق ما بنقل المهام إلى المقدمة والخلفية. قد تفرض التطبيقات الضارة نفسها إلى المقدمة بدون تحكم منك."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"إيقاف التطبيقات التي قيد التشغيل"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 8be8ae8..74ee308 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Дазваляе прыкладанням атрымліваць і апрацоўваць WAP-паведамленні. Шкоднасныя прыкладанні могуць адсочваць вашы паведамленні або выдаляць іх, не паказваючы вам."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"атрымаць запушчаныя прыкладанні"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Дазваляе прыкладанням атрымліваць інфармацыю пра бягучыя і нядаўна запушчаныя заданнi. Шкоднасныя прыкладанні могуць атрымліваць асабістую інфармацыю пра іншыя прыкладаннi."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"атрымаць падрабязныя дадзеныя пра запушчаныя прыкладаннi"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Дазваляе прыкладанню атрымліваць падрабязную інфармацыю пра бягучыя і нядаўна запушчаныя задачы. Шкоднасныя прыкладанні могуць атрымліваць асабістую інфармацыю пра іншыя прыкладаннi."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"змяніць парадак запушчаных прыкладанняў"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Дазваляе прыкладанням перамяшчаць заданні на пярэдні план і фон. Шкоднасныя прыкладанні могуць прымусова рабіць сябе асноўнымі без вашага ведама."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"спыніць запушчаныя прыкладанні"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index dda0bee..71c781d 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Разрешава на приложението да получава и обработва WAP съобщения. Злонамерените приложения могат да наблюдават съобщенията ви или да ги изтрият, без да ви ги покажат."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"извличане на изпълняваните приложения"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Разрешава на приложението да извлича информация за задачите, изпълнявани понастоящем и неотдавна. Злонамерените приложения могат да открият поверителна информация за други приложения."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"извличане на подробности за изпълняваните прилож."</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Разрешава на приложението да извлича подробна информация за задачите, изпълнявани понастоящем и неотдавна. Злонамерените приложения могат да открият поверителна информация за други приложения."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"пренареждане на изпълняваните приложения"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Разрешава на приложението да прехвърля задачи на преден и на заден план. Злонамерените приложения могат сами да се изведат на преден план без ваша намеса."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"спиране на изпълняваните приложения"</string>
@@ -344,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"Разрешава на приложението да изпраща оставащи излъчвания, които се запазват след края на излъчването. Злонамерените приложения могат да причинят бавна или нестабилна работа на таблета, като го накарат да използва твърде много памет."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"Разрешава на приложението да изпраща оставащи излъчвания, които се запазват след края на излъчването. Злонамерените приложения могат да причинят бавна или нестабилна работа на телефона, като го накарат да използва твърде много памет."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"четене на данни за контактите"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"Разрешава на приложението да чете всички данни за съхранените на таблета ви контакти, включително честотата на обаждане, изпращане на имейли или общуване по друг начин с конкретни лица. Това помага при автоматичното довършване на имейл адресите и на други удобни функции. Злонамерените приложения могат да използват това разрешение, за да изпращат данните за контактите ви на други хора."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"Разрешава на приложението да чете всички данни за съхранените на телефона ви контакти, включително честотата на обаждане, изпращане на имейли или общуване по друг начин с конкретни лица. Това помага при автоматичното довършване на имейл адресите и на други удобни функции. Злонамерените приложения могат да използват това разрешение, за да изпращат данните за контактите ви на други хора."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"запис на данни за контактите"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"Разрешава на приложението да променя данните за съхранените на таблета ви контакти, включително честотата на обаждане, изпращане на имейли или общуване по друг начин с конкретни лица. Това помага при автоматичното довършване на имейл адресите и на други удобни функции. Злонамерените приложения могат да използват това, за да изтриват или променят данните за контактите ви."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"Разрешава на приложението да променя данните за съхранените на телефона ви контакти, включително честотата на обаждане, изпращане на имейли или общуване по друг начин с конкретни лица. Това помага при автоматичното довършване на имейл адресите и на други удобни функции. Злонамерените приложения могат да използват това, за да изтриват или променят данните за контактите ви."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"четене на списъка с обаждания"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"Разрешава на приложението да чете списъка с обаждания на таблета ви, включително данните за входящите и изходящите обаждания. Злонамерените приложения могат да използват това, за да изпращат информацията ви на други хора."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"Разрешава на приложението да чете списъка с обаждания на телефона ви, включително данните за входящите и изходящите обаждания. Злонамерените приложения могат да използват това, за да изпращат информацията ви на други хора."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 45ed9b4..f7faa3f 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Umožňuje aplikaci přijmout a zpracovat zprávy WAP. Škodlivé aplikace mohou sledovat vaše zprávy nebo je smazat, aniž by vám byly zobrazeny."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"načtení spuštěných aplikací"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Umožňuje aplikaci získat informace o aktuálně a naposledy spuštěných úlohách. Škodlivé aplikace mohou odhalit soukromé informace o ostatních aplikacích."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"získání podrobností o spuštěných aplikacích"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Umožňuje aplikaci získat podrobné informace o aktuálně a naposledy spuštěných úlohách. Škodlivé aplikace mohou odhalit soukromé informace o ostatních aplikacích."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"změna uspořádání spuštěných aplikací"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Umožňuje aplikaci přesunout úlohy na popředí nebo pozadí. Škodlivé aplikace mohou vynutit zobrazení na popředí bez vašeho svolení."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"zastavení činnosti aplikací"</string>
@@ -344,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"Umožňuje aplikaci odeslat trvalá vysílání, která přetrvávají i po skončení vysílání. Škodlivé aplikace mohou tablet zpomalit či způsobit jeho nestabilitu, protože bude používat příliš mnoho paměti."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"Umožňuje aplikaci odeslat trvalá vysílání, která přetrvávají i po skončení vysílání. Škodlivé aplikace mohou telefon zpomalit či způsobit jeho nestabilitu, protože bude používat příliš mnoho paměti."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"číst data kontaktů"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"Umožňuje aplikaci číst všechny údaje o kontaktech uložených v tabletu včetně toho, jak často voláte, posíláte e-maily nebo komunikujete jinými způsoby s konkrétními osobami. Pomáhá to při automatickém doplňování e-mailových adres a dalších užitečných funkcích. Škodlivé aplikace mohou toto povolení zneužít k posílání vašich kontaktních údajů jiným lidem."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"Umožňuje aplikaci číst všechny údaje o kontaktech uložených v telefonu včetně toho, jak často voláte, posíláte e-maily nebo komunikujete jinými způsoby s konkrétními osobami. Pomáhá to při automatickém doplňování e-mailových adres a dalších užitečných funkcích. Škodlivé aplikace mohou toto povolení zneužít k posílání vašich kontaktních údajů jiným lidem."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"zapisovat data kontaktů"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"Umožňuje aplikaci upravovat všechny údaje o kontaktech uložených v tabletu včetně toho, jak často voláte, posíláte e-maily nebo komunikujete jinými způsoby s konkrétními osobami. Pomáhá to při automatickém doplňování e-mailových adres a dalších užitečných funkcích. Škodlivé aplikace mohou toto povolení zneužít k mazání nebo úpravě vašich kontaktních údajů."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"Umožňuje aplikaci upravovat všechny údaje o kontaktech uložených v telefonu včetně toho, jak často voláte, posíláte e-maily nebo komunikujete jinými způsoby s konkrétními osobami. Pomáhá to při automatickém doplňování e-mailových adres a dalších užitečných funkcích. Škodlivé aplikace mohou toto povolení zneužít k mazání nebo úpravě vašich kontaktních údajů."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"číst seznam hovorů"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"Umožňuje aplikaci číst seznam hovorů vašeho tabletu, včetně dat o příchozích a odchozích hovorech. Škodlivé aplikace mohou tato data posílat jiným osobám."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"Umožňuje aplikaci číst seznam hovorů vašeho telefonu, včetně dat o příchozích a odchozích hovorech. Škodlivé aplikace mohou tato data posílat jiným osobám."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index e0a09ef..69c8178 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Ermöglicht der App, WAP-Mitteilungen zu empfangen und zu verarbeiten. Schädliche Apps können so Ihre Nachrichten überwachen oder löschen, bevor sie angezeigt werden."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"aktive Apps abrufen"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Ermöglicht der App, Informationen zu aktuellen und kürzlich ausgeführten Aufgaben abzurufen. Schädliche Apps können so geheime Informationen zu anderen Apps erhalten."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"Details zu ausgeführten Apps abrufen"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Ermöglicht der App, detaillierte Informationen zu aktuellen und kürzlich ausgeführten Aufgaben abzurufen. Schädliche Apps können so geheime Informationen zu anderen Apps erhalten."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"Aktive Apps neu ordnen"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Ermöglicht der App, Aufgaben in den Vorder- und Hintergrund zu verschieben. Schädliche Apps können so ohne Ihr Zutun eine Anzeige im Vordergrund erzwingen."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"Aktive Apps beenden"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 81108c7..1cdce38 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Επιτρέπει στην εφαρμογή τη λήψη και την επεξεργασία μηνυμάτων WAP. Τυχόν κακόβουλες εφαρμογές ενδέχεται να παρακολουθούν τα μηνύματά σας ή να τα διαγράφουν χωρίς να εμφανίζονται πρώτα σε εσάς."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"ανάκτηση εκτελούμενων εφαρμογών"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Επιτρέπει στην εφαρμογή να ανακτήσει πληροφορίες σχετικά με τις τρέχουσες εκτελούμενες εργασίες και στις εργασίες που έχουν πρόσφατα εκτελεστεί. Τυχόν κακόβουλες εφαρμογές ενδέχεται να ανακαλύψουν ιδιωτικές πληροφορίες σχετικά με άλλες εφαρμογές."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"ανάκτηση λεπτομερειών σχετικά με τις εκτελούμενες εφαρμογές"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Επιτρέπει στην εφαρμογή την ανάκτηση λεπτομερών πληροφοριών σχετικά με τις τρέχουσες εκτελούμενες εργασίες και τις εργασίες που έχουν εκτελεστεί πρόσφατα. Τυχόν κακόβουλες εφαρμογές ενδέχεται να ανακαλύψουν ιδιωτικές πληροφορίες σχετικά με άλλες εφαρμογές."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"αναδιάταξη εκτελούμενων εφαρμογών"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Επιτρέπει στην εφαρμογή τη μετακίνηση εργασιών στο προσκήνιο και στο φόντο. Τυχόν κακόβουλες εφαρμογές μπορούν να προωθηθούν στο προσκήνιο χωρίς να μπορείτε να τις ελέγξετε."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"διακοπή εκτέλεσης εφαρμογών"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 7af3213..8da460c 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Permite que la aplicación reciba y procese mensajes WAP. Las aplicaciones maliciosas pueden controlar tus mensajes o eliminarlos sin mostrártelos."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"recuperar aplicaciones en ejecución"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Permite que la aplicación recupere información sobre tareas en ejecución y recientemente ejecutadas. Las aplicaciones maliciosas pueden descubrir información privada sobre otras aplicaciones."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"recuperar información sobre las aplicaciones en ejecución"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permite que la aplicación recupere información detallada sobre tareas en ejecución y recientemente ejecutadas. Las aplicaciones malintencionadas pueden hallar información privada sobre otras aplicaciones."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"reorganizar aplicaciones en ejecución"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Permite que la aplicación mueva tareas al primero o segundo plano. Las aplicaciones maliciosas pueden forzar su paso al primer plano sin que tú las controles."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"detener las aplicaciones en ejecución"</string>
@@ -344,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"Permite que la aplicación envíe transmisiones persistentes que permanecen luego de que finaliza la transmisión. Las aplicaciones maliciosas pueden hacer que la tableta funcione más lentamente o de manera inestable al forzarla a utilizar mucha memoria."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"Permite que la aplicación envíe transmisiones persistentes que permanecen luego de que finaliza la transmisión. Las aplicaciones maliciosas pueden hacer que el dispositivo funcione más lento o de manera inestable al forzarlo a utilizar mucha memoria."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"leer datos de contacto"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"Permite a la aplicación leer todos los datos sobre los contactos almacenados en tu tableta, incluida la frecuencia con la que realizaste llamadas, enviaste correos o te comunicaste de otras maneras con personas específicas. Esto ayuda a la escritura automática de direcciones de correo y a otras funciones convenientes. Las aplicaciones malintencionadas pueden utilizar este permiso para enviar tus datos de contacto a otras personas."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"Permite a la aplicación leer todos los datos sobre los contactos almacenados en tu teléfono, incluida la frecuencia con la que realizaste llamadas, enviaste correos o te comunicaste de otras maneras con personas específicas. Esto ayuda a la escritura automática de direcciones de correo y a otras funciones convenientes. Las aplicaciones malintencionadas pueden utilizar este permiso para enviar tus datos de contacto a otras personas."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"escribir datos de contacto"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"Permite a la aplicación modificar los datos sobre los contactos almacenados en tu tableta, incluida la frecuencia con la que realizaste llamadas, enviaste correos o te comunicaste de otras maneras con personas específicas. Esto ayuda a la escritura automática de direcciones de correo y a otras funciones convenientes. Las aplicaciones malintencionadas pueden utilizarlo para borrar o modificar tus datos de contacto."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"Permite a la aplicación modificar los datos sobre los contactos almacenados en tu teléfono, incluida la frecuencia con la que realizaste llamadas, enviaste correos o te comunicaste de otras maneras con personas específicas. Esto ayuda a la escritura automática de direcciones de correo y a otras funciones convenientes. Las aplicaciones malintencionadas pueden utilizarlo para borrar o modificar tus datos de contacto."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"leer el registro de llamadas"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"Permite que la aplicación lea el registro de llamadas de la tableta, incluidos los datos sobre llamadas entrantes y salientes. Las aplicaciones malintencionadas pueden usar este permiso para enviar tus datos a otros usuarios."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"Permite que la aplicación lea el registro de llamadas del dispositivo, incluidos los datos sobre llamadas entrantes y salientes. Las aplicaciones malintencionadas pueden usar este permiso para enviar tus datos a otros usuarios."</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index edf8c2b..8d39fd0 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Võimaldab rakendusel vastu võtta ja töödelda WAP-sõnumeid. Pahatahtlikud rakendused võivad teie sõnumeid jälgida või neid kustutada teile näitamata."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"Käitatud rakenduste toomine"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Võimaldab rakendusel hankida teavet praegu töötavate ja hiljuti töötanud ülesannete kohta. Pahatahtlikud rakendused võivad avastada privaatset teavet teiste rakenduste kohta."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"töötavate rakenduste üksikasjade toomine"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Võimaldab rakendusel tuua üksikasjalikku teavet praegu töötavate ja hiljuti käitatud ülesannete kohta. Pahatahtlikud rakendused võivad tuvastada privaatset teavet muude rakenduste kohta."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"käitatud rakenduste ümberjärjestamine"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Võimaldab rakendusel teisaldada ülesanded esiplaanile ja taustale. Pahatahtlikud rakendused võivad sundida end esiplaanile tulema teie loata."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"käitatud rakenduste peatamine"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 64549d3..31e2876 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"به برنامه اجازه میدهد تا پیامهای WAP را دریافت و پردازش کند. برنامههای مخرب میتوانند پیامهای شما را کنترل کنند یا آنها را بدون نشان دادن آنها به شما حذف کنند."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"بازیابی برنامههای در حال اجرا"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"به برنامه اجازه میدهد تا اطلاعات مربوط به کارهایی که اخیرا و در حال حاضر اجرا میشوند را بازیابی کند. برنامههای مخرب میتوانند اطلاعات شخصی مربوط به برنامههای دیگر را پیدا کنند."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"بازیابی جزئیات برنامههای در حال اجرا"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"به برنامه اجازه میدهد تا اطلاعات مفصلی مربوط به کارهایی که در حال حاضر و اخیراً اجرا میشوند را بازیابی کند. برنامههای مخرب میتوانند اطلاعات شخصی مربوط به برنامههای دیگر را پیدا کنند."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"تنظیم مجدد ترتیب برنامههای در حال اجرا"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"به برنامه اجازه میدهد تا کارها را به پیش زمینه و پس زمینه منتقل کند. برنامههای مخرب میتوانند بدون کنترل به اجبار خود را به جلو منتقل کنند."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"متوقف کردن برنامههای در حال اجرا"</string>
@@ -344,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"به برنامه اجازه میدهد تا پخشهای ماندگار را که پس از اتمام پخش باقی میمانند ارسال شوند. برنامههای مخرب میتوانند با استفاده بیش از حد از حافظه وضعیت آن را ناپایدار سازند یا باعث کند شدن رایانه لوحی شوند."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"به برنامه اجازه میدهد تا پخشهای ماندگار را که پس از اتمام پخش باقی میمانند ارسال کند. برنامههای مخرب میتوانند با استفاده بیش از حد از حافظه تلفن را کند یا ناپایدار کنند."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"خواندن اطلاعات تماس"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"به برنامه اجازه میدهد دادههای مربوط به مخاطبان را که بر روی گوشی ذخیره شده است بخواند و این دادهها شامل لیست مخاطبانی که با آنها مکرراً تماس میگیرید، ایمیل میزنید یا با راههای دیگر با آنها ارتباط برقرار میکنید میشود. این موارد در تکمیل خودکار آدرسهای ایمیل یا دیگر موارد برای راحتی کار به شما کمک میکنند. برنامههای خرابکار میتوانند از این مجوز برای ارسال دادههای تماس شما به افراد دیگر استفاده کنند."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"به برنامه اجازه میدهد دادههای مربوط به مخاطبان را که بر روی گوشی ذخیره شده است پاک کند و این دادهها شامل لیست مخاطبانی که با آنها مکرراً تماس میگیرید، ایمیل میزنید یا با راههای دیگر با آنها ارتباط برقرار میکنید میشود. این موارد در تکمیل خودکار آدرسهای ایمیل یا دیگر موارد برای راحتی کار به شما کمک میکنند. برنامههای خرابکار میتوانند از این مجوز برای ارسال دادههای تماس شما به افراد دیگر استفاده کنند."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"نوشتن اطلاعات تماس"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"به برنامه اجازه میدهد دادههای مربوط به مخاطبان را که بر روی رایانه لوحی شما ذخیره شده است تغییر دهد و این دادهها شامل لیست مخاطبانی که با آنها مکرراً تماس میگیرید، ایمیل میزنید یا با راههای دیگر با آنها ارتباط برقرار میکنید میشود. این موارد در تکمیل خودکار آدرسهای ایمیل یا دیگر موارد برای راحتی کار به شما کمک میکنند. برنامههای خرابکار میتوانند از این مجوز برای ارسال دادههای تماس شما به افراد دیگر یا حذف آنها استفاده کنند."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"به برنامه اجازه میدهد دادههای مربوط به مخاطبان را که بر روی گوشی ذخیره شده است تغییر دهد و این دادهها شامل لیست مخاطبانی که با آنها مکرراً تماس میگیرید، ایمیل میزنید یا با راههای دیگر با آنها ارتباط برقرار میکنید میشود. این موارد در تکمیل خودکار آدرسهای ایمیل یا دیگر موارد برای راحتی کار به شما کمک میکنند. برنامههای خرابکار میتوانند از این مجوز برای ارسال دادههای تماس شما به افراد دیگر یا حذف آنها استفاده کنند."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"خواندن گزارش تماس"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"به برنامه اجازه میدهد گزارشات تماس رایانه لوحی شما، از جمله دادههایی درمورد تماسهای ورودی و خروجی را بخواند. برنامههای مخرب ممکن است از این ویژگی برای ارسال دادههای شما به دیگران استفاده کنند."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"به برنامه اجازه میدهد گزارشات تماس تلفنی شما، از جمله دادههایی درمورد تماسهای ورودی و خروجی را بخواند. برنامههای مخرب ممکن است از این ویژگی برای ارسال دادههای شما به دیگران استفاده کنند."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index ba818b9..3aa4796 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Antaa sovelluksen vastaanottaa ja käsitellä WAP-viestejä. Haitalliset sovellukset voivat valvoa viestejä tai poistaa niitä näyttämättä niitä sinulle."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"käynnissä olevien sovellusten noutaminen"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Antaa sovelluksen noutaa käynnissä oleviin ja käynnissä olleisiin tehtäviin liittyviä tietoja. Haitalliset sovellukset saattavat saada näin muihin sovelluksiin liittyviä yksityisiä tietoja."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"hae tiedot suoritettavista sovelluksista"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Antaa sovellukselle oikeuden noutaa käynnissä oleviin ja käynnissä olleisiin tehtäviin liittyviä tietoja. Haitalliset sovellukset saattavat saada näin muihin sovelluksiin liittyviä yksityisiä tietoja."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"käynnissä olevien sovellusten järjesteleminen"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Antaa sovelluksen siirtää tehtäviä etualalle ja taustalle. Haitalliset sovellukset voivat pakottaa itsensä etualalle ilman käyttäjän hallintaa."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"käynnissä olevien sovellusten pysäyttäminen"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 72c8778..1027ae7 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"एप्लिकेशन को WAP संदेशों को प्राप्त करने और संसाधित करने देता है. दुर्भावनापूर्ण एप्लिकेशन आपके संदेशों की निगरानी कर सकते हैं या आपको दिखाए बिना उन्हें हटा सकते हैं."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"चल रहे एप्लिकेशन पुनर्प्राप्त करें"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"एप्लिकेशन को वर्तमान में और हाल ही में चल रहे कार्यों की जानकारी पुर्नप्राप्त करने देता है. दुर्भावनापूर्ण एप्लिकेशन अन्य एप्लिकेशन के बारे में निजी जानकारी खोज सकते हैं."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"चल रहे एप्लिकेशन के विवरण प्राप्त करें"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"एप्लिकेशन को वर्तमान में और हाल ही में चल रहे कार्यों की जानकारी प्राप्त करने देता है. दुर्भावनापूर्ण एप्लिकेशन अन्य एप्लिकेशन के बारे में निजी जानकारी खोज सकते हैं."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"चल रहे एप्लिकेशन पुन: क्रमित करें"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"एप्लिकेशन को अग्रभूमि और पृष्ठभूमि में कार्यों को ले जाने देता है. दुर्भावनापूर्ण एप्लिकेशन आपके नियंत्रण के बिना स्वयं को बलपूर्वक आगे कर सकते हैं."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"चलने वाले एप्लिकेशन रोकें"</string>
@@ -344,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"एप्लिकेशन को स्टिकी प्रसारण भेजने देता है, जो प्रसारण समाप्त होने के बाद भी बने रहते हैं. दुर्भावनापूर्ण एप्लिकेशन टेबलेट की बहुत अधिक स्मृति का उपयोग करके उसे धीमा या अस्थिर कर सकते हैं."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"एप्लिकेशन को स्टिकी प्रसारण भेजने देता है, जो प्रसारण समाप्त होने के बाद भी बना रहता है. दुर्भावनापूर्ण एप्लिकेशन फ़ोन की बहुत अधिक स्मृति का उपयोग करके उसे धीमा या अस्थिर कर सकते हैं."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"संपर्क डेटा पढ़ें"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"एप्लिकेशन को आपके द्वारा विशेष व्यक्तियों को अन्य तरीकों से कॉल, ईमेल, या उनसे संचार करने की आवृत्ति सहित, आपके टेबलेट पर संग्रहीत आपके संपर्कों का सभी डेटा पढ़ने देता है. इससे ईमेल पतों के स्वत: पूर्ण होने और अन्य उपयुक्त सुविधाओं के लिए सहायता मिलती है. दुर्भावनापूर्ण एप्लिकेशन इस अनुमति का उपयोग आपका डेटा अन्य लोगों को भेजने के लिए कर सकते हैं."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"एप्लिकेशन को आपके द्वारा विशेष व्यक्तियों को अन्य तरीकों से कॉल करने, ईमेल करने, या उनसे संचार करने की आवृत्ति सहित, आपके फ़ोन पर संग्रहीत आपके संपर्कों का सभी डेटा पढ़ने देता है. इससे ईमेल पतों के स्वत: पूर्ण होने और अन्य उपयुक्त सुविधाओं के लिए सहायता मिलती है. दुर्भावनापूर्ण एप्लिकेशन इस अनुमति का उपयोग आपका डेटा अन्य लोगों को भेजने के लिए कर सकते हैं."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"संपर्क डेटा लिखें"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"एप्लिकेशन को आपके द्वारा विशेष व्यक्तियों को अन्य तरीकों से कॉल, ईमेल, या उनसे संचार करने की आवृत्ति सहित, आपके टेबलेट पर संग्रहीत आपके संपर्कों का डेटा संशोधित करने देता है. इससे ईमेल पतों के स्वत: पूर्ण होने और अन्य उपयुक्त सुविधाओं के लिए सहायता मिलती है. दुर्भावनापूर्ण एप्लिकेशन इस अनुमति का उपयोग आपका डेटा अन्य लोगों को भेजने के लिए कर सकते हैं."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"एप्लिकेशन को आपके द्वारा विशेष व्यक्तियों को अन्य तरीकों से कॉल, ईमेल, या उनसे संचार करने की आवृत्ति सहित, आपके फ़ोन पर संग्रहीत आपके संपर्कों का डेटा संशोधित करने देता है. इससे ईमेल पतों के स्वत: पूर्ण होने और अन्य उपयुक्त सुविधाओं के लिए सहायता मिलती है. दुर्भावनापूर्ण एप्लिकेशन इस अनुमति का उपयोग आपका डेटा अन्य लोगों को भेजने के लिए कर सकते हैं."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"कॉल लॉग पढ़ें"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"एप्लिकेशन को इनकमिंग और आउटगोइंग कॉल के डेटा सहित, आपके टेबलेट का कॉल लॉग पढ़ने देता है. दुर्भावनापूर्ण एप्लिकेशन अन्य लोगों को आपका डेटा भेजने के लिए इसका उपयोग कर सकते हैं."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"एप्लिकेशन को इनकमिंग और आउटगोइंग कॉल के डेटा सहित, आपके फ़ोन का कॉल लॉग पढ़ने देता है. दुर्भावनापूर्ण एप्लिकेशन अन्य लोगों को आपका डेटा भेजने के लिए इसका उपयोग कर सकते हैं."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 1f03c45..4288eaf 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Omogućuje aplikaciji primanje i obradu WAP poruka. Zlonamjerne aplikacije mogu nadzirati vaše poruke ili ih brisati, a da vam ih ne pokažu."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"dohvaćanje pokrenutih aplikacija"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Omogućuje aplikaciji dohvaćanje informacija o trenutačno i nedavno pokrenutim zadacima. Zlonamjerne aplikacije mogu otkriti privatne informacije o drugim aplikacijama."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"dohvaćanje pojedinosti o pokrenutim aplikacijama"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Aplikaciji omogućuje dohvaćanje detaljnih informacija o trenutačno i nedavno pokrenutim zadacima. Zlonamjerne aplikacije mogu otkriti privatne informacije o drugim aplikacijama."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"promjena redoslijeda pokrenutih aplikacija"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Omogućuje aplikaciji da premjesti zadatke u prednji plan ili pozadinu. Zlonamjerne aplikacije mogu na silu doći u prednji plan bez vašeg nadzora."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"zaustavljanje pokrenutih aplikacija"</string>
@@ -344,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"Omogućuje aplikaciji slanje \"ljepljivih\" emitiranja, koja se zadržavaju nakon što emitiranje završi. Zlonamjerne aplikacije mogu usporiti tabletno računalo ili ga učiniti nestabilnim uzrokujući pretjeranu upotrebu memorije."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"Omogućuje aplikaciji slanje \"ljepljivih\" emitiranja, koja se zadržavaju nakon što emitiranje završi. Zlonamjerne aplikacije mogu usporiti telefon ili ga učiniti nestabilnim uzrokujući pretjeranu upotrebu memorije."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"čitanje kontaktnih podataka"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"Omogućuje aplikaciji čitanje svih podataka o vašim kontaktima pohranjenim na vašem tabletnom računalu, uključujući i učestalost kojom određene pojedince nazivate, šaljete im e-poruke ili komunicirate s njima na druge načine. To pomaže pri automatskom dovršavanju e-adresa i s ostalim prigodnim značajkama. Zlonamjerne aplikacije mogu upotrijebiti to dopuštenje kako bi vaše podatke za kontakt slale drugim osobama."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"Omogućuje aplikaciji čitanje svih podataka o vašim kontaktima pohranjenim na vašem telefonu, uključujući i učestalost kojom određene pojedince nazivate, šaljete im e-poruke ili komunicirate s njima na druge načine. To pomaže pri automatskom dovršavanju e-adresa i s ostalim prigodnim značajkama. Zlonamjerne aplikacije mogu upotrijebiti to dopuštenje kako bi vaše podatke za kontakt slale drugim osobama."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"pisanje kontaktnih podataka"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"Omogućuje aplikaciji izmjenu podataka o vašim kontaktima pohranjenim na vašem tabletnom računalu, uključujući i učestalost kojom određene pojedince nazivate, šaljete im e-poruke ili komunicirate s njima na druge načine. To pomaže pri automatskom dovršavanju e-adresa i s ostalim prigodnim značajkama. Zlonamjerne aplikacije mogu upotrijebiti to dopuštenje kako bi vaše podatke za kontakt izbrisale ili izmijenile."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"Omogućuje aplikaciji izmjenu podataka o vašim kontaktima pohranjenim na vašem telefonu, uključujući i učestalost kojom određene pojedince nazivate, šaljete im e-poruke ili komunicirate s njima na druge načine. To pomaže pri automatskom dovršavanju adresa e-pošte i s ostalim prigodnim značajkama. Zlonamjerne aplikacije mogu upotrijebiti to dopuštenje kako bi vaše podatke za kontakt izbrisale ili izmijenile."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"čitanje dnevnika poziva"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"Aplikaciji omogućuje čitanje dnevnika poziva vašeg tabletnog računala zajedno s podacima o dolaznim i odlaznim pozivima. Zlonamjerne aplikacije to mogu upotrebljavati za slanje vaših podataka drugim osobama."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"Aplikaciji omogućuje čitanje dnevnika poziva vašeg telefona zajedno s podacima o dolaznim i odlaznim pozivima. Zlonamjerne aplikacije to mogu upotrebljavati za slanje vaših podataka drugim osobama."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index c0b259b..0190fb2 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Lehetővé teszi az alkalmazás számára, hogy WAP üzeneteket fogadjon és dolgozzon fel. A rosszindulatú alkalmazások megfigyelhetik vagy törölhetik az üzeneteket anélkül, hogy Ön látná azokat."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"futó alkalmazások lekérése"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Lehetővé teszi az alkalmazás számára a jelenleg és a nemrég futó feladatok adatainak lekérését. A rosszindulatú alkalmazások privát adatokhoz juthatnak más alkalmazásokról."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"futó alkalmazások részleteinek lekérése"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Lehetővé teszi az alkalmazás számára a jelenleg és a nemrég futó feladatok részletes adatainak lekérését. A rosszindulatú alkalmazások más alkalmazásokkal kapcsolatos privát adatokhoz férhetnek hozzá."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"futó alkalmazások átrendezése"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Lehetővé teszi az alkalmazás számára, hogy feladatokat helyezzen át az előtérből a háttérbe és fordítva. A rosszindulatú alkalmazások az előtérbe helyezhetik magukat az Ön engedélye nélkül."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"futó alkalmazások leállítása"</string>
@@ -344,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"Lehetővé teszi az alkalmazás számára a ragadós üzenetek küldését, amelyek a sugárzás után is megmaradnak. A rosszindulatú alkalmazások lelassíthatják vagy instabillá tehetik a táblagépet a túlzott memóriahasználattal."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"Lehetővé teszi az alkalmazás számára ragadós üzenetek küldését, amelyek a sugárzás után is megmaradnak. A rosszindulatú alkalmazások lelassíthatják vagy instabillá tehetik a táblagépet a túlzott memóriahasználattal."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"névjegyadatok olvasása"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"Lehetővé teszi az alkalmazás számára a táblagépen tárolt névjegyekre vonatkozó összes adat -- például az egyes személyekkel telefonon, e-mailben vagy más módon folytatott kommunikáció gyakoriságára vonatkozó adatok -- olvasását. Ez segítséget nyújt az e-mail címek automatikus kiegészítéséhez és az egyéb kényelmi funkciók működéséhez. A rosszindulatú alkalmazások ezt az engedélyt arra használhatják, hogy névjegyeit elküldjék más személyeknek."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"Lehetővé teszi az alkalmazás számára a telefonon tárolt névjegyekre vonatkozó összes adat -- például az egyes személyekkel telefonon, e-mailben vagy más módon folytatott kommunikáció gyakoriságára vonatkozó adatok -- olvasását. Ez segítséget nyújt az e-mail címek automatikus kiegészítéséhez és az egyéb kényelmi funkciók működéséhez. A rosszindulatú alkalmazások ezt az engedélyt arra használhatják, hogy névjegyeit elküldjék más személyeknek."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"névjegyadatok írása"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"Lehetővé teszi az alkalmazás számára a táblagépen tárolt névjegyekre vonatkozó adatok -- például az egyes személyekkel telefonon, e-mailben vagy más módon folytatott kommunikáció gyakoriságára vonatkozó adatok -- módosítását. Ez segítséget nyújt az e-mail címek automatikus kiegészítéséhez és az egyéb kényelmi funkciók működéséhez. A rosszindulatú alkalmazások ezt az engedélyt arra használhatják, hogy módosítsák vagy töröljék névjegyeinek adatait."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"Lehetővé teszi az alkalmazás számára a telefonon tárolt névjegyekre vonatkozó adatok -- például az egyes személyekkel telefonon, e-mailben vagy más módon folytatott kommunikáció gyakoriságára vonatkozó adatok -- módosítását. Ez segítséget nyújt az e-mail címek automatikus kiegészítéséhez és az egyéb kényelmi funkciók működéséhez. A rosszindulatú alkalmazások ezt az engedélyt arra használhatják, hogy módosítsák vagy töröljék névjegyeinek adatait."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"Híváslista beolvasása"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"Lehetővé teszi, hogy az alkalmazás hozzáférjen a táblagép híváslistájához, beleértve a bejövő és kimenő hívások adatait. A rosszindulatú alkalmazások ezt arra használhatják, hogy az adatait elküldjék másoknak."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"Lehetővé teszi, hogy az alkalmazás hozzáférjen híváslistájához, beleértve a bejövő és kimenő hívások adatait. A rosszindulatú alkalmazások ezt arra használhatják, hogy az adatait elküldjék másoknak."</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index adc21ba..9bb765d 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Mengizinkan apl menerima dan memproses pesan WAP. Apl berbahaya dapat memantau pesan atau menghapusnya tanpa menunjukkannya kepada Anda."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"mengambil apl yang berjalan"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Mengizinkan apl mengambil informasi tentang tugas yang sedang dijalankan dan yang baru-baru ini dijalankan. Apl berbahaya dapat menemukan informasi pribadi tentang apl lain."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"mengambil detail aplikasi yang sedang berjalan"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Izinkan aplikasi mengambil informasi mendetail tentang tugas yang saat ini dan baru-baru ini dijalankan. Aplikasi berbahaya dapat menemukan informasi pribadi tentang aplikasi lain."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"menyusun ulang apl yang berjalan"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Mengizinkan apl memindah tugas ke latar depan dan latar belakang. Apl berbahaya dapat memaksa berpindah ke depan tanpa kontrol Anda."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"menghentikan apl yang berjalan"</string>
@@ -323,7 +321,7 @@
<string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"menggunakan media pengawasandi apa pun untuk pemutaran"</string>
<string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Mengizinkan apl menggunakan pengawasandi media apa pun yang terpasang guna mengawasandikan media untuk diputar."</string>
<string name="permlab_diagnostic" msgid="8076743953908000342">"baca/tulis ke sumber daya yang dimiliki oleh diag"</string>
- <string name="permdesc_diagnostic" msgid="6608295692002452283">"Mengizinkan apl membaca dan menulis ke sumber daya apa pun yang dimiliki oleh grup diag; misalnya, file dalam /dev. Izin ini berpotensi mempengaruhi kestabilan dan keamanan sistem. Sebaiknya ini HANYA digunakan untuk diagnostik khusus perangkat keras oleh pabrikan atau operator."</string>
+ <string name="permdesc_diagnostic" msgid="6608295692002452283">"Mengizinkan apl membaca dan menulis ke sumber daya apa pun yang dimiliki oleh grup diag; misalnya, file dalam /dev. Izin ini berpotensi memengaruhi kestabilan dan keamanan sistem. Sebaiknya ini HANYA digunakan untuk diagnostik khusus perangkat keras oleh pabrikan atau operator."</string>
<string name="permlab_changeComponentState" msgid="6335576775711095931">"mengaktifkan atau menonaktifkan komponen apl"</string>
<string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"Mengizinkan apl mengubah apakah komponen apl lain diaktifkan atau tidak. Apl berbahaya dapat menggunakan ini untuk menonaktifkan kemampuan tablet yang penting. Izin ini harus digunakan dengan hati-hati karena dapat menjadikan komponen apl tidak dapat digunakan, tidak konsisten, atau tidak stabil."</string>
<string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"Mengizinkan apl mengubah apakah komponen apl lain diaktifkan atau tidak. Apl berbahaya dapat menggunakan izin ini untuk menonaktifkan kemampuan ponsel yang penting. Izin ini harus digunakan dengan hati-hati, karena mungkin saja menjadikan komponen apl tidak dapat digunakan, tidak konsisten, atau tidak stabil."</string>
@@ -344,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"Mengizinkan apl mengirim siaran permanen, yang tetap ada setelah siaran berakhir. Apl berbahaya dapat membuat tablet menjadi lambat atau tidak stabil dengan memicu penggunaan memori yang terlalu banyak."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"Mengizinkan apl mengirim siaran permanen, yang tetap ada setelah siaran berakhir. Apl berbahaya dapat membuat ponsel menjadi lambat atau tidak stabil dengan memicu penggunaan memori yang terlalu banyak."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"baca data kenalan"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"Memungkinkan aplikasi membaca semua data tentang kenalan yang disimpan pada tablet Anda, termasuk frekuensi saat Anda menghubungi, mengirim email, atau berkomunikasi dengan cara lain dengan individu tertentu. Aplikasi ini membantu pelengkapan otomatis alamat email dan fitur nyaman lainnya. Aplikasi berbahaya dapat menggunakan izin ini untuk mengirim data kenalan Anda kepada orang lain."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"Memungkinkan aplikasi membaca semua data tentang kenalan yang disimpan pada ponsel Anda, termasuk frekuensi saat Anda menghubungi, mengirim email, atau berkomunikasi dengan cara lain dengan individu tertentu. Aplikasi ini membantu pelengkapan otomatis alamat email dan fitur nyaman lainnya. Aplikasi berbahaya dapat menggunakan izin ini untuk mengirim data kenalan Anda kepada orang lain."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"tuliskan data kenalan"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"Memungkinkan aplikasi mengubah semua data tentang kenalan yang disimpan pada tablet Anda, termasuk frekuensi saat Anda menghubungi, mengirim email, atau berkomunikasi dengan cara lain dengan individu tertentu. Aplikasi ini membantu pelengkapan otomatis alamat email dan fitur nyaman lainnya. Aplikasi berbahaya dapat menggunakan izin ini untuk mengirim data kenalan Anda kepada orang lain."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"Memungkinkan aplikasi mengubah semua data tentang kenalan yang disimpan pada ponsel Anda, termasuk frekuensi saat Anda menghubungi, mengirim email, atau berkomunikasi dengan cara lain dengan individu tertentu. Aplikasi ini membantu pelengkapan otomatis alamat email dan fitur nyaman lainnya. Aplikasi berbahaya dapat menggunakan izin ini untuk mengirim data kenalan Anda kepada orang lain."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"membaca log panggilan"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"Memungkinkan apl membaca log panggilan tablet Anda, termasuk data tentang panggilan masuk dan keluar. Apl berbahaya dapat menggunakan ini untuk mengirim data ke orang lain."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"Memungkinkan apl membaca log panggilan ponsel Anda, termasuk data tentang panggilan masuk dan keluar. Apl berbahaya dapat menggunakan ini untuk mengirim data ke orang lain."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 027669d..e8bbd56 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"מאפשר ליישום לקבל ולעבד הודעות WAP. יישומים זדוניים עלולים לעקוב אחר ההודעות שלך או למחוק אותן מבלי להציגן בפניך."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"אחזור יישומים פעילים"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"מאפשר ליישום לאחזר מידע על המשימות הנוכחיות שפועלות, ואלו שפעלו לאחרונה. יישומים זדוניים עלולים לגלות מידע אישי על יישומים אחרים."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"אחזור פרטי יישומים פועלים"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"מאפשר ליישום לאחזר מידע מפורט על המשימות הנוכחיות הפועלות ועל משימות שפעלו לאחרונה. יישומים זדוניים עלולים לגלות מידע אישי על יישומים אחרים."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"סידור מחדש של יישומים פעילים"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"מאפשר ליישום להעביר משימות לחזית ולרקע. יישומים זדוניים עלולים לאלץ את עצמם לעבור לחזית ללא שליטה מצדך."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"עצירת יישומים פעילים"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 6fb1c0a..a65e747 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"WAPメッセージの受信と処理をアプリに許可します。この許可を悪意のあるアプリに利用されると、メッセージが監視されたり、表示されずに削除されたりする恐れがあります。"</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"実行中のアプリの取得"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"現在実行中または最近実行したタスクに関する情報の取得をアプリに許可します。この許可を悪意のあるアプリに利用されると、他のアプリに関する非公開情報が発見される恐れがあります。"</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"実行中のアプリの詳細の取得"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"現在実行中のタスクまたは最近実行したタスクに関する情報の取得をアプリに許可します。この許可を悪意のあるアプリに利用されると、他のアプリに関する非公開情報が読み取られる恐れがあります。"</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"実行中のアプリの順序変更"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"タスクをフォアグラウンドやバックグラウンドに移動することをアプリに許可します。この許可を悪意のあるアプリに利用されると、悪意のあるアプリが強制的に優先される恐れがあります。"</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"実行中のアプリの停止"</string>
@@ -344,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"配信が終了してもメモリに残るstickyブロードキャストの配信をアプリに許可します。この許可を悪意のあるアプリに利用されると、メモリの使用量が増えてタブレットの動作が遅くなったり不安定になったりする恐れがあります。"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"配信が終了してもメモリに残るstickyブロードキャストの配信をアプリに許可します。この許可を悪意のあるアプリに利用されると、メモリの使用量が増えて携帯端末の動作が遅くなったり不安定になったりする恐れがあります。"</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"連絡先データの読み取り"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"タブレットに保存されている連絡先についてすべてのデータを読み取ることをアプリに許可します。このデータには、特定の相手と電話、メール、または他の手段でコミュニケーションをとった回数も含まれます。この権限はメールアドレスの自動補完やその他の便利な機能に役立ちますが、悪意のあるアプリがこれを悪用してあなたの連絡先データを第三者に送信する可能性があります。"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"携帯端末に保存されている連絡先についてすべてのデータを読み取ることをアプリに許可します。このデータには、特定の相手と電話、メール、または他の手段でコミュニケーションをとった回数も含まれます。この権限はメールアドレスの自動補完やその他の便利な機能に役立ちますが、悪意のあるアプリがこれを悪用してあなたの連絡先データを第三者に送信する可能性があります。"</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"連絡先データの書き込み"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"タブレットに保存されている連絡先についてデータの変更をアプリに許可します。このデータには、特定の相手と電話、メール、または他の手段でコミュニケーションをとった回数も含まれます。この権限はメールアドレスの自動補完やその他の便利な機能に役立ちますが、悪意のあるアプリがこれを悪用してあなたの連絡先データを消去または改ざんする可能性があります。"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"携帯端末に保存されている連絡先についてデータの変更をアプリに許可します。このデータには、特定の相手と電話、メール、または他の手段でコミュニケーションをとった回数も含まれます。この権限はメールアドレスの自動補完やその他の便利な機能に役立ちますが、悪意のあるアプリがこれを悪用してあなたの連絡先データを消去または改ざんする可能性があります。"</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"通話履歴の読み取り"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"タブレットの通話履歴(着信や発信のデータなど)の読み取りをアプリに許可します。この許可を悪意のあるアプリに利用されると、データが他のユーザーに送信される恐れがあります。"</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"携帯端末の通話履歴(着信や発信のデータなど)の読み取りをアプリに許可します。この許可を悪意のあるアプリに利用されると、データが他のユーザーに送信される恐れがあります。"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 5fd3709..7a4a55b 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"앱이 WAP 메시지를 받고 처리할 수 있도록 허용합니다. 이 경우 악성 앱이 메시지를 모니터링하거나 사용자가 보기 전에 삭제할 수 있습니다."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"실행 중인 앱 검색"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"앱이 현재 실행 중이거나 최근에 실행된 작업에 대한 정보를 검색할 수 있도록 허용합니다. 이 경우 악성 앱이 다른 앱에 대한 개인 정보를 검색할 수 있습니다."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"실행 중인 앱 세부정보 검색"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"앱이 현재 실행 중이거나 최근에 실행된 작업에 대한 상세한 정보를 검색할 수 있도록 허용합니다. 이 경우 악성 앱이 다른 앱에 대한 개인 정보를 검색할 수 있습니다."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"실행 중인 앱 순서 재지정"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"앱이 작업을 포그라운드나 백그라운드로 이동할 수 있도록 허용합니다. 이 경우 악성 앱이 사용자의 조작 없이 앞으로 이동할 수 있습니다."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"실행 중인 앱 중지"</string>
@@ -344,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"앱이 브로드캐스트가 끝난 후에 남은 브로드캐스트를 보낼 수 있도록 허용합니다. 이 경우 악성 앱이 태블릿에서 메모리를 너무 많이 사용하도록 하여 속도를 저하시키거나 불안정하게 만들 수 있습니다."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"앱이 브로드캐스트가 끝난 후에 남은 브로드캐스트를 보낼 수 있도록 허용합니다. 이 경우 악성 앱이 휴대전화에서 메모리를 너무 많이 사용하도록 하여 속도를 저하시키거나 불안정하게 만들 수 있습니다."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"연락처 데이터 읽기"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"특정인과 전화, 이메일 또는 기타 수단으로 연락한 빈도를 포함하여 내 태블릿에 저장된 연락처에 대한 모든 데이터를 앱이 읽도록 허용합니다. 이렇게 하면 이메일 주소 자동완성과 기타 편리한 기능을 사용할 수 있습니다. 한편 악성 앱이 이를 악용하여 내 연락처 데이터를 다른 사람에게 전송할 수 있습니다."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"특정인과 전화, 이메일 또는 기타 수단으로 연락한 빈도를 포함하여 내 휴대전화에 저장된 연락처에 대한 모든 데이터를 앱이 읽도록 허용합니다. 이렇게 하면 이메일 주소 자동완성과 기타 편리한 기능을 사용할 수 있습니다. 한편 악성 앱이 이를 악용하여 내 연락처 데이터를 다른 사람에게 전송할 수 있습니다."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"연락처 데이터 작성"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"특정인과 전화, 이메일 또는 기타 수단으로 연락한 빈도를 포함하여 내 휴대전화에 저장된 연락처에 대한 모든 데이터를 앱이 수정하도록 허용합니다. 이렇게 하면 이메일 주소 자동완성과 기타 편리한 기능을 사용할 수 있습니다. 한편 악성 앱이 이를 악용하여 내 연락처 데이터를 삭제 또는 수정할 수 있습니다."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"특정인과 전화, 이메일 또는 기타 수단으로 연락한 빈도를 포함하여 내 휴대전화에 저장된 연락처에 대한 모든 데이터를 앱이 수정하도록 허용합니다. 이렇게 하면 이메일 주소 자동완성과 기타 편리한 기능을 사용할 수 있습니다. 한편 악성 앱이 이를 악용하여 내 연락처 데이터를 삭제 또는 수정할 수 있습니다."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"통화 기록 읽기"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"앱에서 수신 및 발신 통화 데이터를 포함하여 태블릿의 통화 기록을 읽을 수 있도록 허용합니다. 이 경우 악성 앱이 데이터를 다른 사용자에게 보낼 수 있습니다."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"앱에서 수신 및 발신 통화 데이터를 포함하여 휴대전화의 통화 기록을 읽을 수 있도록 허용합니다. 이 경우 악성 앱이 데이터를 다른 사용자에게 보낼 수 있습니다."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 750047d..fa379fb2 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Leidžiama programai gauti ir apdoroti WAP pranešimus. Kenkėjiškos programos gali stebėti jūsų pranešimus ar ištrinti juos neparodydamos jų jums."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"nuskaityti vykdomas programas"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Leidžiama programai nuskaityti informaciją apie šiuo ir paskutiniu metu vykdomas užduotis. Kenkėjiškos programos gali atrasti privačios informacijos apie kitas programas."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"nuskaityti veikiančių programų išsamią informaciją"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Leidžiama programai nuskaityti išsamią informaciją apie šiuo ir pastaruoju metu vykdomas užduotis. Kenkėjiškos programos gali atrasti privačios informacijos apie kitas programas."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"pertvarkyti vykdomas programas"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Leidžiama programai užduotis perkelti į priekinį planą ir į foną. Kenkėjiškos programos gali priverstinai persikelti į priekį be jūsų įsikišimo."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"sustabdyti vykdomas programas"</string>
@@ -344,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"Leidžiama programai siųsti užsifiksuojančias transliacijas, kurios išlieka pasibaigus transliacijai. Kenkėjiškos programos gali sulėtinti planšetinį kompiuterį ar padaryti jį nestabilų versdamos naudoti per daug atminties."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"Leidžiama programai siųsti užsifiksuojančias transliacijas, kurios išlieka pasibaigus transliacijai. Kenkėjiškos programos gali sulėtinti telefoną ar padaryti jį nestabilų versdamos jį naudoti per daug atminties."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"skaityti adresato duomenis"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"Leidžiama programai perskaityti visus planšetiniame kompiuteryje saugomus duomenis apie kontaktus, įskaitant informaciją apie tai, kaip dažnai skambinote, rašėte el. laiškus ar kitais būdais bendravote su konkrečiais asmenimis. Tai naudinga naudojant automatinio el. pašto adresų užbaigimo ir kitas patogias funkcijas. Kenkėjiškos programos gali panaudoti šį leidimą, kad siųstų jūsų kontaktinius duomenis kitiems asmenims."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"Leidžiama programai perskaityti visus telefone saugomus duomenis apie kontaktus, įskaitant informaciją apie tai, kaip dažnai skambinote, rašėte el. laiškus ar kitais būdais bendravote su konkrečiais asmenimis. Tai naudinga naudojant automatinio el. pašto adresų užbaigimo ir kitas patogias funkcijas. Kenkėjiškos programos gali panaudoti šį leidimą, kad siųstų jūsų kontaktinius duomenis kitiems asmenims."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"rašyti adresatų duomenis"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"Leidžiama programai keisti planšetiniame kompiuteryje saugomus duomenis apie kontaktus, įskaitant informaciją apie tai, kaip dažnai skambinote, rašėte el. laiškus ar kitais būdais bendravote su konkrečiais asmenimis. Tai naudinga naudojant automatinio el. pašto adresų užbaigimo ir kitas patogias funkcijas. Kenkėjiškos programos gali tuo pasinaudoti, kad ištrintų arba pakeistų jūsų kontaktinius duomenis."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"Leidžiama programai keisti telefone saugomus duomenis apie kontaktus, įskaitant informaciją apie tai, kaip dažnai skambinote, rašėte el. laiškus ar kitais būdais bendravote su konkrečiais asmenimis. Tai naudinga naudojant automatinio el. pašto adresų užbaigimo ir kitas patogias funkcijas. Kenkėjiškos programos gali tuo pasinaudoti, kad ištrintų arba pakeistų jūsų kontaktinius duomenis."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"skaityti skambučių žurnalą"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"Programai leidžiama skaityti planšetinio kompiuterio skambučių žurnalą, įskaitant duomenis apie gaunamus ir siunčiamus skambučius. Kenkėjiškos programos tai gali naudoti, kad išsiųstų jūsų duomenis kitiems žmonėms."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"Programai leidžiama skaityti telefono skambučių žurnalą, įskaitant duomenis apie gaunamus ir siunčiamus skambučius. Kenkėjiškos programos tai gali naudoti, kad išsiųstų jūsų duomenis kitiems žmonėms."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index e01ec9b..6d21773 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Ļauj lietotnei saņemt un apstrādāt WAP ziņojumus. Ļaunprātīgas lietotnes var pārraudzīt vai dzēst šos ziņojumus, neparādot tos jums."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"izgūt izmantotās lietotnes"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Ļauj lietotnei izgūt informāciju par šobrīd un nesen veiktajiem uzdevumiem. Ļaunprātīgas lietotnes var atklāt privātu informāciju par citām lietotnēm."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"Informācijas izguve par izmantotajām lietotnēm"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Ļauj lietotnei izgūt informāciju par šobrīd un nesen veiktajiem uzdevumiem. Ļaunprātīgas lietotnes var atklāt privātu informāciju par citām lietotnēm."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"pārkārtot izmantotās lietotnes"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Ļauj lietotnei pārvietot uzdevumus priekšplānā un fonā. Ļaunprātīgas lietotnes var tikt izvirzītas priekšplānā bez jūsu vadības."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"apturēt izmantoto lietotņu darbību"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 20ede1f..40735433 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -344,15 +344,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"Membolehkan apl untuk menghantar siaran melekit, yang kekal selepas siaran berakhir. Apl hasad boleh membuat tablet perlahan atau tidak stabil dengan menyebabkannya menggunakan memori yang terlalu banyak."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"Membolehkan apl untuk menghantar siaran melekit, yang kekal selepas siaran berakhir. Apl hasad boleh membuat telefon perlahan atau tidak stabil dengan menyebabkannya menggunakan memori yang terlalu banyak."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"baca data kenalan"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"Membenarkan apl membaca semua data tentang kenalan anda yang disimpan pada tablet anda, termasuk kekerapan anda memanggil, menghantar e-mel atau berkomunikasi dengan cara yang lain dengan individu tertentu. Ini membantu auto-pelengkapan alamat e-mel dan ciri mudah lain. Apl hasad boleh menggunakan kebenaran ini untuk menghantar data kenalan anda kepada orang lain."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"Membenarkan apl membaca semua data tentang kenalan anda yang disimpan pada telefon anda, termasuk kekerapan anda memanggil, menghantar e-mel atau berkomunikasi dengan cara yang lain dengan individu tertentu. Ini membantu auto-pelengkapan alamat e-mel dan ciri mudah lain. Apl hasad boleh menggunakan kebenaran ini untuk menghantar data kenalan anda kepada orang lain."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"tulis data kenalan"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"Membolehkan aplikasi untuk mengubah suai data mengenai kenalan anda yang disimpan pada tablet anda, termasuk kekerapan yang anda telah dipanggil, mel, atau disampaikan dengan cara yang lain dengan individu-individu tertentu. Ini membantu dengan auto siap-alamat e-mel dan lain-lain ciri-ciri mudah. Aplikasi berniat jahat boleh menggunakan ini untuk memadam atau mengubah suai data kenalan anda."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"Membenarkan apl mengubah suai data tentang kenalan anda yang disimpan pada telefon anda, termasuk kekerapan anda memanggil, menghantar e-mel atau berkomunikasi dengan cara yang lain dengan individu tertentu. Ini membantu auto-pelengkapan alamat e-mel dan ciri mudah lain. Apl hasad boleh menggunakan kebenaran ini untuk memadam atau mengubah suai data kenalan anda."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"baca log panggilan"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"Membenarkan apl membaca log panggilan tablet anda, termasuk data tentang panggilan masuk dan keluar. Apl hasad boleh menggunakannya untuk menghantar data anda kepada orang lain."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"Membenarkan apl membaca log panggilan telefon anda, termasuk data tentang panggilan masuk dan keluar. Apl hasad boleh menggunakannya untuk menghantar data anda kepada orang lain."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 166df42..e517f51 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -344,15 +344,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"Permite que uma aplicação envie difusões fixas, que permanecem após o fim da difusão. As aplicações maliciosas podem tornar o tablet lento ou instável, fazendo com que utilize demasiada memória."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"Permite que a aplicação envie difusões fixas, que permanecem após o fim da difusão. As aplicações maliciosas podem tornar o telemóvel lento ou instável, fazendo com que utilize demasiada memória."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"ler dados de contacto"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"Permite que a aplicação leia todos os dados sobre os seus contactos armazenados no seu tablet, incluindo a frequência com que ligou, enviou emails ou comunicou de outras formas com indivíduos específicos. Isto ajuda a preencher automaticamente os endereços de email e outras funcionalidades convenientes. As aplicações maliciosas podem utilizar esta permissão para enviar os seus dados de contacto a outras pessoas."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"Permite que a aplicação leia todos os dados sobre os seus contactos armazenados no seu telemóvel, incluindo a frequência com que ligou, enviou emails ou comunicou de outras formas com indivíduos específicos. Isto ajuda a preencher automaticamente os endereços de email e outras funcionalidades convenientes. As aplicações maliciosas podem utilizar esta permissão para enviar os seus dados de contacto a outras pessoas."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"escrever dados de contacto"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"Permite que a aplicação modifique os dados sobre os seus contactos armazenados no seu tablet, incluindo a frequência com que ligou, enviou emails ou comunicou de outras formas com indivíduos específicos. Isto ajuda a preencher automaticamente os endereços de email e outras funcionalidades convenientes. As aplicações maliciosas podem utilizar esta situação para apagar ou modificar os seus dados de contacto."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"Permite que a aplicação modifique os dados sobre os seus contactos armazenados no seu telemóvel, incluindo a frequência com que ligou, enviou emails ou comunicou de outras formas com indivíduos específicos. Isto ajuda a preencher automaticamente os endereços de email e outras funcionalidades convenientes. As aplicações maliciosas podem utilizar esta situação para apagar ou modificar os seus dados de contacto."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"ler registo de chamadas"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"Permite à aplicação ler o registo de chamadas do tablet, incluindo os dados sobre as chamadas recebidas e efetuadas. As aplicações maliciosas podem utilizar esta funcionalidade para enviar os seus dados para outras pessoas."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"Permite que a aplicação leia o registo de chamadas do telemóvel, incluindo os dados sobre as chamadas recebidas e efetuadas. As aplicações maliciosas podem utilizar esta funcionalidade para enviar os seus dados para outras pessoas."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 7a7f343..0304408 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Permite que o aplicativo receba e processe mensagens WAP. Aplicativos maliciosos podem monitorar suas mensagens ou excluí-las sem mostrá-las para você."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"recuperar aplicativos em execução"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Permite que o aplicativo recupere informações sobre atualmente tarefas executadas recentemente e tarefas em execução. Aplicativos maliciosos podem descobrir informações particulares de outros aplicativos."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"recuperar detalhes dos aplicativos em execução"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permite que o aplicativo recupere informações detalhadas sobre tarefas executadas atual e recentemente. Aplicativos maliciosos podem descobrir informações privadas sobre outros aplicativos."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"reordenar os aplicativos em execução"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Permite que o aplicativo mova tarefas para o primeiro plano e para o plano de fundo. Aplicativos maliciosos podem forçar-se para a primeiro plano sem que você tenha controle sobre a ação."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"parar os aplicativos em execução"</string>
@@ -344,11 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"Permite que o aplicativo envie transmissões fixas, que permaneçam depois que a transmissão terminar. Aplicativos maliciosos podem desacelerar ou desestabilizar o tablet, fazendo com que ele utilize muita memória."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"Permite que o aplicativo envie transmissões fixas, que permanecem depois que a transmissão termina. Aplicativos maliciosos podem deixar o telefone lento ou instável, fazendo com que ele use muita memória."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"ler dados do contato"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"Permite que o aplicativo leia todos os dados sobre os contatos armazenados em seu tablet, incluindo a frequência com que você liga, envia e-mails ou se comunica de outras maneiras com cada um. Isso ajuda no preenchimento automático dos endereços de e-mail e em outros recursos práticos. Aplicativos maliciosos podem usar esta permissão para enviar seus dados de contato para outras pessoas."</string>
- <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"Permite que o aplicativo leia todos os dados sobre os contatos armazenados em seu telefone, incluindo a frequência com que você liga, envia e-mails ou se comunica de outras maneiras com cada um. Isso ajuda no preenchimento automático dos endereços de e-mail e em outros recursos práticos. Aplicativos maliciosos podem usar esta permissão para enviar seus dados de contato para outras pessoas."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"Permite que o aplicativo leia todos os dados sobre os contatos armazenados em seu tablet, incluindo a frequência com que você ligou, enviou e-mails ou se comunicou de outras maneiras com cada um. Isso ajuda no preenchimento automático dos endereços de e-mail e em outros recursos práticos. Aplicativos maliciosos podem usar esta permissão para enviar seus dados de contato para outras pessoas."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"Permite que o aplicativo leia todos os dados sobre os contatos armazenados em seu telefone, incluindo a frequência com que você ligou, enviou e-mails ou se comunicou de outras maneiras com cada um. Isso ajuda no preenchimento automático dos endereços de e-mail e em outros recursos práticos. Aplicativos maliciosos podem usar esta permissão para enviar seus dados de contato para outras pessoas."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"gravar dados de contato"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"Permite que o aplicativo leia todos os dados sobre os contatos armazenados em seu tablet, incluindo a frequência com que você liga, envia e-mails ou se comunica de outras maneiras com cada um. Isso ajuda no preenchimento automático dos endereços de e-mail e em outros recursos práticos. Aplicativos maliciosos podem usar esta permissão para apagar ou modificar seus dados de contato."</string>
- <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"Permite que o aplicativo modifique todos os dados sobre os contatos armazenados em seu telefone, incluindo a frequência com que você liga, envia e-mails ou se comunica de outras maneiras com cada um. Isso ajuda no preenchimento automático dos endereços de e-mail e em outros recursos práticos. Aplicativos maliciosos podem usar esta permissão para apagar ou modificar seus dados de contato."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"Permite que o aplicativo leia todos os dados sobre os contatos armazenados em seu tablet, incluindo a frequência com que você ligou, enviou e-mails ou se comunicou de outras maneiras com cada um. Isso ajuda no preenchimento automático dos endereços de e-mail e em outros recursos práticos. Aplicativos maliciosos podem usar esta permissão para apagar ou modificar seus dados de contato."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"Permite que o aplicativo modifique todos os dados sobre os contatos armazenados em seu telefone, incluindo a frequência com que você ligou, enviou e-mails ou se comunicou de outras maneiras com cada um. Isso ajuda no preenchimento automático dos endereços de e-mail e em outros recursos práticos. Aplicativos maliciosos podem usar esta permissão para apagar ou modificar seus dados de contato."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"ler registro de chamadas"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"Permite que o aplicativo leia o registro de chamadas de seu tablet, incluindo dados sobre chamadas recebidas e efetuadas. Aplicativos maliciosos podem usar esta permissão para enviar seus dados para outras pessoas."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"Permite que o aplicativo leia o registro de chamadas de seu telefone, incluindo dados sobre chamadas recebidas e efetuadas. Aplicativos maliciosos podem usar esta permissão para enviar seus dados para outras pessoas."</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 2d7e0147..1633437 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Permite aplicaţiei să primească şi să proceseze mesaje WAP. Aplicaţiile rău intenţionate pot să monitorizeze mesajele sau să le şteargă fără să vi le arate."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"preluare aplicaţii care rulează"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Permite aplicaţiei să preia informaţii despre activităţile rulate curent şi recent. Aplicaţiile rău intenţionate pot să descopere informaţii private despre alte aplicaţii."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"preia detalii despre aplicaţiile care rulează"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permite aplicaţiei să preia informaţii detaliate despre activităţile rulate curent şi recent. Aplicaţiile rău intenţionate pot să descopere informaţii private despre alte aplicaţii."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"reordonare aplicaţii care rulează"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Permite aplicaţiei să mute activităţile în prim-plan şi în fundal. Aplicaţiile rău intenţionate pot să apară forţat în prim-plan, fără ca dvs. să puteţi controla acest lucru."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"oprire aplicaţii care rulează"</string>
@@ -344,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"Permite aplicaţiei să trimită mesaje difuzate persistente, care rămân după terminarea mesajului difuzat. Aplicaţiile rău intenţionate pot să încetinească sau să destabilizeze tableta, determinând-o să utilizeze prea multă memorie."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"Permite aplicaţiei să trimită mesaje difuzate persistente, care rămân după terminarea mesajului difuzat. Aplicaţiile rău intenţionate pot să încetinească sau să destabilizeze telefonul, determinându-l să utilizeze prea multă memorie."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"citire date de contact"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"Permite aplicaţiei să citească toate datele despre persoanele de contact stocate pe tabletă, inclusiv frecvenţa cu care aţi apelat, aţi trimis mesaje de e-mail către sau aţi comunicat în alte moduri cu anumite persoane. Acest lucru permite completarea automată a adreselor de e-mail, precum şi alte funcţii care vă uşurează utilizarea. Aplicaţiile rău intenţionate pot folosi această permisiune pentru a trimite datele dvs. de contact altor persoane."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"Permite aplicaţiei să citească toate datele despre persoanele de contact stocate pe telefon, inclusiv frecvenţa cu care aţi apelat, aţi trimis mesaje de e-mail către sau aţi comunicat în alte moduri cu anumite persoane. Acest lucru permite completarea automată a adreselor de e-mail, precum şi alte funcţii care vă uşurează utilizarea. Aplicaţiile rău intenţionate pot folosi această permisiune pentru a trimite datele dvs. de contact altor persoane."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"scriere date de contact"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"Permite aplicaţiei să modifice datele despre persoanele de contact stocate pe tabletă, inclusiv frecvenţa cu care aţi apelat, aţi trimis mesaje de e-mail către sau aţi comunicat în alte moduri cu anumite persoane. Acest lucru permite completarea automată a adreselor de e-mail, precum şi alte funcţii care vă uşurează utilizarea. Aplicaţiile rău intenţionate pot folosi această permisiune pentru a şterge sau pentru a modifica datele dvs. de contact."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"Permite aplicaţiei să modifice datele despre persoanele de contact stocate pe telefon, inclusiv frecvenţa cu care aţi apelat, aţi trimis mesaje de e-mail către sau aţi comunicat în alte moduri cu anumite persoane. Acest lucru permite completarea automată a adreselor de e-mail, precum şi alte funcţii care vă uşurează utilizarea. Aplicaţiile rău intenţionate pot folosi această permisiune pentru a şterge sau pentru a modifica datele dvs. de contact."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"citeşte jurnalul de apeluri"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"Permite aplicaţiei să citească jurnalul de apeluri al tabletei dvs., inclusiv datele despre apelurile primite sau efectuate. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a trimite datele dvs. altor persoane."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"Permite aplicaţiei să citească jurnalul de apeluri al telefonului dvs., inclusiv datele despre apelurile primite sau efectuate. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a trimite datele dvs. altor persoane."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 3b3bf4c..057e9fc 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -201,8 +201,8 @@
<string name="permdesc_receiveMms" msgid="1424805308566612086">"Приложение сможет получать и обрабатывать MMS. Вредоносные программы смогут отслеживать и удалять сообщения, не показывая их."</string>
<string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"принимать экстренные вызовы"</string>
<string name="permdesc_receiveEmergencyBroadcast" msgid="848524070262431974">"Приложение сможет получать и обрабатывать экстренные сообщения рассылок. Это разрешение доступно только для системных приложений."</string>
- <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"Читать сообщения рассылки"</string>
- <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Приложение сможет считывать сообщения рассылки, полученные вашим устройством. В ряде стран вам будут приходить уведомления об экстренных ситуациях. В этом случае вредоносные программы могут помешать работе вашего устройства."</string>
+ <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"Читать сообщения массовой рассылки"</string>
+ <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Приложение получит доступ к сообщениям широковещательных SMS-служб, которые в некоторых странах используются для информирования населения об экстренных ситуациях. Вредоносные программы могут помешать работе устройства, на которое поступают такие сообщения."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"отправлять SMS-сообщения"</string>
<string name="permdesc_sendSms" msgid="906546667507626156">"Приложение сможет отправлять SMS. Вредоносные программы смогут отправлять SMS без вашего подтверждения, что приведет к непредвиденным расходам."</string>
<string name="permlab_sendSmsNoConfirmation" msgid="4781483105951730228">"отправка SMS без подтверждения"</string>
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Приложение сможет получать и обрабатывать WAP-сообщения. Вредоносные программы смогут отслеживать и удалять сообщения, не показывая их."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"получение запущенных приложений"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Приложение сможет получать информацию о недавно запущенных и выполняемых задачах. Вредоносные программы смогут получить личную информацию из других приложений."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"получение сведений о работающих приложениях"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Приложение сможет получать подробные сведения о недавно запущенных и выполняемых задачах. При этом конфиденциальная информация о других приложениях не будет защищена от вредоносных программ."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"изменение порядка запущенных приложений"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Приложение сможет перемещать задачи в режим активного или фонового выполнения. Вредоносные программы смогут переводить себя в активный режим без вашего ведома."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"остановка запущенных приложений"</string>
@@ -344,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"Приложение сможет отправлять несрочные рассылки, которые не удаляются после их завершения. Вредоносные программы смогут замедлить работу планшетного ПК или сделать ее нестабильной из-за чрезмерного использования памяти."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"Приложение сможет делать рассылки типа sticky broadcast. Вредоносные программы смогут замедлить работу телефона или сделать ее нестабильной из-за чрезмерного использования памяти."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"считывать данные контакта"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"Приложение сможет читать все данные о контактах на вашем устройстве, включая то, как часто вы звоните, отправляете письма и другими способами связываетесь с определенными людьми. Это поможет автоматически вводить адреса эл. почты и использовать другие удобные функции. Вредоносные приложения могут использовать это разрешение для отправки ваших сведений о контактах другим людям."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"Приложение сможет читать все данные о контактах на вашем устройстве, включая то, как часто вы звоните, отправляете письма и другими способами связываетесь с определенными людьми. Это поможет автоматически вводить адреса эл. почты и использовать другие удобные функции. Вредоносные приложения могут использовать это разрешение для отправки ваших сведений о контактах другим людям."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"перезаписывать данные контакта"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"Приложение сможет изменять сведения о контактах на вашем устройстве, включая то, как часто вы звоните, отправляете письма и другими способами связываетесь с определенными людьми. Это помогает автоматически вводить адреса эл. почты и использовать другие удобные функции. Вредоносные приложения могут использовать это для удаления или изменения ваших сведений о контактах."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"Приложение сможет изменять сведения о контактах на вашем устройстве, включая то, как часто вы звоните, отправляете письма и другими способами связываетесь с определенными людьми. Это помогает автоматически вводить адреса эл. почты и использовать другие удобные функции. Вредоносные приложения могут использовать это для удаления или изменения ваших сведений о контактах."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"чтение журнала вызовов"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"Приложение получит доступ к списку вызовов планшетного ПК, включая данные о входящих и исходящих звонках. Вредоносные приложения могут использовать доступ для передачи ваших данных третьим лицам."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"Приложение получит доступ к списку вызовов телефона, включая данные о входящих и исходящих звонках. Вредоносные приложения смогут воспользоваться этим, чтобы отправить ваши данные третьим лицам."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 7c6773d..b52a8a7 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Umožňuje aplikácii prijímať a spracovávať správy WAP. Škodlivé aplikácie môžu sledovať vaše správy alebo ich odstrániť bez toho, aby ich zobrazili."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"načítať spustené aplikácie"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Umožňuje aplikácii načítať informácie o aktuálnych a nedávno spustených úlohách. Škodlivé aplikácie môžu odhaliť súkromné informácie o iných aplikáciách."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"načítať podrobnosti o spustených aplikáciách"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Umožňuje aplikácii načítať podrobné informácie o aktuálnych a nedávno spustených úlohách. Škodlivé aplikácie môžu odhaliť súkromné informácie o iných aplikáciách."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"zmeniť poradie spustených aplikácií"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Umožňuje aplikácii presúvať úlohy do popredia a pozadia. Škodlivé aplikácie sa môžu pretlačiť do popredia bez vášho vedomia."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"zastaviť spustené aplikácie"</string>
@@ -344,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"Umožňuje aplikácii odosielať trvalé vysielania, ktoré pretrvávajú aj po skončení vysielania. Škodlivé aplikácie môžu tablet spomaliť alebo spôsobiť jeho nestabilitu, pretože bude používať príliš veľa pamäte."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"Umožňuje aplikácii odosielať trvalé vysielania, ktoré pretrvávajú aj po skončení vysielania. Škodlivé aplikácie môžu telefón spomaliť alebo spôsobiť jeho nestabilitu spotrebou príliš veľkého množstva pamäte."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"čítanie údajov kontaktov"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"Umožňuje aplikácii čítať všetky údaje o kontaktoch uložených v tablete vrátane toho, ako často voláte, posielate e-maily alebo komunikujete inými spôsobmi s konkrétnymi osobami. Pomáha to pri automatickom dopĺňaní e-mailových adries a ďalších nápomocných funkciách. Škodlivé aplikácie môžu toto povolenie zneužiť na posielanie vašich kontaktných údajov iným ľuďom."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"Umožňuje aplikácii čítať všetky údaje o kontaktoch uložených v telefóne vrátane toho, ako často voláte, posielate e-maily alebo komunikujete inými spôsobmi s konkrétnymi osobami. Pomáha to pri automatickom dopĺňaní e-mailových adries a ďalších nápomocných funkciách. Škodlivé aplikácie môžu toto povolenie zneužiť na posielanie vašich kontaktných údajov iným ľuďom."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"zápis údajov kontaktov"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"Umožňuje aplikácii upravovať všetky údaje o kontaktoch uložených v tablete vrátane toho, ako často voláte, posielate e-maily alebo komunikujete inými spôsobmi s konkrétnymi osobami. Pomáha to pri automatickom dopĺňaní e-mailových adries a ďalších nápomocných funkciách. Škodlivé aplikácie môžu toto povolenie zneužiť na posielanie vašich kontaktných údajov iným ľuďom."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"Umožňuje aplikácii upravovať všetky údaje o kontaktoch uložených v telefóne vrátane toho, ako často voláte, posielate e-maily alebo komunikujete inými spôsobmi s konkrétnymi osobami. Pomáha to pri automatickom dopĺňaní e-mailových adries a ďalších nápomocných funkciách. Škodlivé aplikácie môžu toto povolenie zneužiť na posielanie vašich kontaktných údajov iným ľuďom."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"čítať denník hovorov"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"Umožňuje aplikácii čítať denník hovorov vo vašom tablete vrátane údajov o prichádzajúcich a odchádzajúcich hovoroch. Škodlivé aplikácie to môžu zneužiť na odosielanie vašich údajov iným osobám."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"Umožňuje aplikácii čítať denník hovorov vo vašom telefóne vrátane údajov o prichádzajúcich a odchádzajúcich hovoroch. Škodlivé aplikácie to môžu zneužiť na odosielanie vašich údajov iným osobám."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 5134845..5e38ce7 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Programu omogoča prejemanje in obdelavo sporočil WAP. Zlonamerni programi lahko nadzirajo sporočila ali jih brišejo, ne da bi vam jih pokazali."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"dobivanje programov, ki se izvajajo"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Programu omogoča dobivanje informacij o trenutnih in nedavno izvajajočih se opravilih. Zlonamerni programi lahko odkrijejo zasebne podatke o drugih programih."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"prejemanje podrobnosti o aplikacijah, ki se izvajajo"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Aplikaciji omogoča, da dobi podatke o trenutnih in nedavno izvajajočih se opravilih. Zlonamerne aplikacije lahko odkrijejo zasebne podatke o drugih aplikacijah."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"preurejanje programov, ki se izvajajo"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Programu omogoča premikanje opravil v ospredje in ozadje. Zlonamerni programi se lahko brez vašega nadzora vsilijo v ospredje."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"ustavitev programov, ki se izvajajo"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 1bd98de..f124e60 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Дозвољава апликацији да прима и обрађује WAP поруке. Злонамерне апликације могу да надгледају поруке или да их бришу, а да вам их не прикажу."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"преузимање покренутих апликација"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Дозвољава апликацији да преузима информације о актуелним и недавно покренутим задацима. Злонамерне апликације могу да открију приватне информације о другим апликацијама."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"преузимање детаља о покренутим апликацијама"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Дозвољава апликацији да преузима детаљне информације о актуелним и недавно покренутим задацима. Злонамерне апликације могу да открију приватне информације о другим апликацијама."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"промена редоследа покренутих апликација"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Дозвољава апликацији да премешта задатке у први план и у позадину. Злонамерне апликације могу на тај начин да принудно пређу у први план без ваше контроле."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"заустављање покренутих апликација"</string>
@@ -344,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"Дозвољава апликацији да шаље пријемчива емитовања, која остају по завршетку емитовања. Злонамерне апликације могу да успоре или дестабилизују таблет тиме што ће га приморати да троши превише меморије."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"Дозвољава апликацији да шаље пријемчива емитовања, која остају по завршетку емитовања. Злонамерне апликације могу да успоре или дестабилизују телефон тиме што ће га приморати да троши превише меморије."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"читање података о контактима"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"Дозвољава апликацији да чита све податке о контактима ускладиштене на таблету, укључујући податке о томе колико често зовете одређене особе, шаљете им поруке е-поште или на други начин комуницирате са њима. Ово помаже функцији аутоматског довршавања адреса е-поште и другим корисним функцијама. Злонамерне апликације могу да искористе ову дозволу за слање ваших података о контакту другим људима."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"Дозвољава апликацији да чита све податке о контактима ускладиштене на телефону, укључујући податке о томе колико често зовете одређене особе, шаљете им поруке е-поште или на други начин комуницирате са њима. Ово помаже функцији аутоматског довршавања адреса е-поште и другим корисним функцијама. Злонамерне апликације могу да искористе ову дозволу за слање ваших података о контакту другим људима."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"уписивање података о контактима"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"Дозвољава апликацији да мења податке о контактима ускладиштене на таблету, укључујући податке о томе колико често зовете одређене особе, шаљете им поруке е-поште или на други начин комуницирате са њима. Ово помаже функцији аутоматског довршавања адреса е-поште и другим корисним функцијама. Злонамерне апликације могу то да искористе да би избрисале или измениле ваше податке о контакту."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"Дозвољава апликацији да мења податке о контактима ускладиштене на телефону, укључујући податке о томе колико често зовете одређене особе, шаљете им поруке е-поште или на други начин комуницирате са њима. Ово помаже функцији аутоматског довршавања адреса е-поште и другим корисним функцијама. Злонамерне апликације могу то да искористе да би избрисале или измениле ваше податке о контакту."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"читање евиденције позива"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"Дозвољава апликацији да чита евиденцију позива на таблету, укључујући податке о долазним и одлазним позивима. Злонамерне апликације могу ово да користе да би слале податке другим људима."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"Дозвољава апликацији да чита евиденцију позива на телефону, укључујући податке о долазним и одлазним позивима. Злонамерне апликације могу ово да користе да би слале податке другим људима."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 236f554..cef001f 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Inaruhusu programu kupokea na kuchakata jumbe za WAP. Programu hasidi zinaweza kufuatilia jumbe zako au kuzifuta bila kukuonyesha."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"rudisha programu zinazoendeshwa"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Inaruhusu programu kupata taarifa kuhusu kazi zinazoendelea sasa na hivi karibuni. Programu hasidi zinaweza kugundua taarifa ya kibinafsi kuhusu programu zingine."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"epua maelezo ya programu zinazoendeshwa."</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Huruhusu programu kuepua maelezo tondoti kuhusu kazi za sasa na zinazoendelea hivi karibuni. Programu hasidi huenda zikagundua maelezo ya kibinafsi kuhusu programu zingine."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"Agiza tena programu za kuendeshwa"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Inaruhusu programu kusongesha kazi kwenye mandhari-mbele na mandhari-nyuma. Programu hasidi zinaweza kujilazimisha mbele bila udhibiti wako."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"Komesha programu zinazoendeshwa"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index fec8bf2..89627b1 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -201,8 +201,8 @@
<string name="permdesc_receiveMms" msgid="1424805308566612086">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ MMS แอปพลิเคชันที่เป็นอันตรายอาจตรวจสอบข้อความของคุณหรือลบออกโดยไม่แสดงให้คุณเห็น"</string>
<string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"ได้รับการกระจายข้อความฉุกเฉิน"</string>
<string name="permdesc_receiveEmergencyBroadcast" msgid="848524070262431974">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความที่เผยแพร่กรณีฉุกเฉิน การอนุญาตนี้ใช้ได้เฉพาะกับแอปพลิเคชันระบบเท่านั้น"</string>
- <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"อ่านข้อความกระจายข้อมูลทางมือถือ"</string>
- <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"อนุญาตให้แอปพลิเคชันอ่านข้อความกระจายข้อมูลทางมือถือที่อุปกรณ์ได้รับ การแจ้งเตือนทางมือถือมีให้บริการในบางตำแหน่งโดยจะแจ้งเตือนคุณเกี่ยวกับสถานการณ์ฉุกเฉิน แอปพลิเคชันที่เป็นอันตรายอาจเข้าแทรกแซงการทำงานของอุปกรณ์เมื่อได้รับข้อความแจ้งเตือน"</string>
+ <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"อ่านข้อความที่ได้รับจากสถานีมือถือ"</string>
+ <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"อนุญาตให้แอปอ่านข้อความจากสถานีมือถือที่อุปกรณ์ได้รับ การแจ้งเตือนทางมือถือมีให้บริการในบางพื้นที่ โดยจะแจ้งเตือนคุณเกี่ยวกับสถานการณ์ฉุกเฉิน แอปที่เป็นอันตรายอาจเข้าแทรกแซงการทำงานของอุปกรณ์เมื่อได้รับข้อความแจ้งเตือนฉุกเฉิน"</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"ส่งข้อความ SMS"</string>
<string name="permdesc_sendSms" msgid="906546667507626156">"อนุญาตให้แอปพลิเคชันส่งข้อความ SMS แอปพลิเคชันที่เป็นอันตรายอาจทำให้คุณต้องเสียค่าใช้จ่ายด้วยการส่งข้อความโดยไม่มีการยืนยันจากคุณ"</string>
<string name="permlab_sendSmsNoConfirmation" msgid="4781483105951730228">"ส่งข้อความ SMS โดยไม่มีการยืนยัน"</string>
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ WAP แอปพลิเคชันที่เป็นอันตรายอาจตรวจสอบข้อความของคุณหรือลบออกโดยไม่แสดงให้คุณเห็น"</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"เรียกแอปพลิเคชันที่ทำงานอยู่"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"อนุญาตให้แอปพลิเคชันดึงข้อมูลเกี่ยวกับงานที่กำลังเรียกใช้อยู่ในปัจจุบันและงานล่าสุด แอปพลิเคชันที่เป็นอันตรายอาจค้นพบข้อมูลเฉพาะตัวเกี่ยวกับแอปพลิเคชันอื่นๆ"</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"ดึงรายละเอียดของแอปพลิเคชันที่ทำงานอยู่"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"อนุญาตให้แอปพลิเคชันดึงข้อมูลเกี่ยวกับงานที่กำลังเรียกใช้อยู่ในปัจจุบันและงานล่าสุด แอปพลิเคชันที่เป็นอันตรายอาจค้นพบข้อมูลเฉพาะตัวเกี่ยวกับแอปพลิเคชันอื่นๆ"</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"จัดลำดับแอปพลิเคชันที่ทำงานอยู่ใหม่"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"อนุญาตให้แอปพลิเคชันย้ายงานไปยังส่วนหน้าและพื้นหลัง แอปพลิเคชันที่เป็นอันตรายอาจบังคับตัวเองให้ไปที่ส่วนหน้าโดยไม่มีการควบคุมจากคุณ"</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"หยุดแอปพลิเคชันที่ทำงานอยู่"</string>
@@ -344,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"อนุญาตให้แอปพลิเคชันส่งการกระจายข้อมูลที่ติดหนึบ ซึ่งจะยังคงอยู่หลังจากการกระจายข้อมูลจบไปแล้ว แอปพลิเคชันที่เป็นอันตรายอาจทำให้แท็บเล็ตทำงานช้าลงหรือไม่เสถียรโดยการใช้หน่วยความจำมากเกินไป"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"อนุญาตให้แอปพลิเคชันส่งการกระจายข้อมูลที่ติดหนึบ ซึ่งจะยังคงอยู่หลังจากการกระจายข้อมูลจบไปแล้ว แอปพลิเคชันที่เป็นอันตรายอาจทำให้โทรศัพท์ทำงานช้าลงหรือไม่เสถียรโดยการใช้หน่วยความจำมากเกินไป"</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"อ่านข้อมูลที่อยู่ติดต่อแล้ว"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"อนุญาตให้แอปพลิเคชันอ่านข้อมูลทั้งหมดเกี่ยวกับผู้ติดต่อที่จัดเก็บไว้ในแท็บเล็ตของคุณ รวมถึงความถี่ที่คุณโทรหา ส่งอีเมล หรือสื่อสารในรูปแบบอื่นกับคนบางคน ซึ่งจะช่วยให้ระบบสามารถเติมที่อยู่อีเมลและให้คุณลักษณะเพื่ออำนวยความสะดวกสบายอื่นๆ โดยอัตโนมัติ แอปพลิเคชันที่เป็นอันตรายสามารถใช้การอนุญาตนี้ในการส่งข้อมูลผู้ติดต่อของคุณไปยังบุคคลอื่น"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"อนุญาตให้แอปพลิเคชันอ่านข้อมูลทั้งหมดเกี่ยวกับผู้ติดต่อที่จัดเก็บไว้ในโทรศัพท์ของคุณ รวมถึงความถี่ที่คุณโทรหา ส่งอีเมล หรือสื่อสารในรูปแบบอื่นกับคนบางคน ซึ่งจะช่วยให้ระบบสามารถเติมที่อยู่อีเมลและให้คุณลักษณะเพื่ออำนวยความสะดวกสบายอื่นๆ โดยอัตโนมัติ แอปพลิเคชันที่เป็นอันตรายสามารถใช้การอนุญาตนี้ในการส่งข้อมูลผู้ติดต่อของคุณไปยังบุคคลอื่น"</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"เขียนข้อมูลที่อยู่ติดต่อ"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"อนุญาตให้แอปพลิเคชันแก้ไขข้อมูลเกี่ยวกับผู้ติดต่อที่จัดเก็บไว้ในแท็บเล็ตของคุณ รวมถึงความถี่ที่คุณโทรหา ส่งอีเมล หรือสื่อสารในรูปแบบอื่นกับคนบางคน ซึ่งจะช่วยให้ระบบสามารถเติมที่อยู่อีเมลและให้คุณลักษณะเพื่ออำนวยความสะดวกสบายอื่นๆ โดยอัตโนมัติ แอปพลิเคชันที่เป็นอันตรายสามารถใช้คุณลักษณะนี้ในการลบหรือแก้ไขข้อมูลผู้ติดต่อของคุณ"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"อนุญาตให้แอปพลิเคชันแก้ไขข้อมูลเกี่ยวกับผู้ติดต่อที่จัดเก็บไว้ในโทรศัพท์ของคุณ รวมถึงความถี่ที่คุณโทรหา ส่งอีเมล หรือสื่อสารในรูปแบบอื่นกับคนบางคน ซึ่งจะช่วยให้ระบบสามารถเติมที่อยู่อีเมลและให้คุณลักษณะเพื่ออำนวยความสะดวกสบายอื่นๆ โดยอัตโนมัติ แอปพลิเคชันที่เป็นอันตรายสามารถใช้คุณลักษณะนี้ในการลบหรือแก้ไขข้อมูลผู้ติดต่อของคุณ"</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"อ่านประวัติการโทร"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"อนุญาตให้แอปอ่านประวัติการโทรจากแท็บเล็ตของคุณ รวมถึงข้อมูลเกี่ยวกับสายเรียกเข้าและการโทรออก แอปที่เป็นอันตรายอาจใช้สิ่งนี้เพื่อส่งข้อมูลของคุณให้กับบุคคลอื่น"</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"อนุญาตให้แอปอ่านประวัติการโทรจากโทรศัพท์ของคุณ รวมถึงข้อมูลเกี่ยวกับสายเรียกเข้าและการโทรออก แอปที่เป็นอันตรายอาจใช้สิ่งนี้เพื่อส่งข้อมูลของคุณให้กับบุคคลอื่น"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 95359af..f59b276 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Pinapayagan ang app na tumanggap at magproseso ng mga mensaheng WAP. Maaaring subaybayan ng nakakahamak na apps ang iyong mga mensahe o tanggalin ang mga ito nang hindi ipinapakita ang mga ito sa iyo."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"bawiin ang tumatakbong apps"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Pinapayagan ang app na bawiin ang impormasyon tungkol sa kasalukuyan at kamakailang tumatakbong mga gawain. Maaaring makatuklas ang nakakahamak na apps ng pribadong impormasyon tungkol sa iba pang apps."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"bawiin ang mga detalye ng gumaganang apps"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Binibigyang-daan ang app na bawiin ang detalyadong impormasyon tungkol sa mga kasalukuyan at kamakailang gumaganang gawain. Maaaring makatuklas ang nakakahamak na apps ng pribadong impormasyon tungkol sa iba pang apps."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"muling isaayos ang tumatakbong apps"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Pinapayagan ang app na ilipat ang mga gawain sa foreground at background. Maaaring puwersahin ng nakakahamak na apps ang mga sarili nito sa harapan nang wala ang iyong pagkontrol."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"ihinto ang pagpapatakbo ng apps"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 8427aea..975c3d9 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Uygulamaya, WAP mesajlarını alma ve işleme izni verir. Kötü amaçlı uygulamalar mesajlarınızı izleyebilir veya onları size göstermeden silebilir."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"çalışan uygulamaları al"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Uygulamaya, şu anda çalışmakta olan ve son çalışan işlemler hakkında bilgi alma izni verir. Kötü amaçlı uygulamalar diğer uygulamalar hakkında özel bilgileri ele geçirebilir."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"çalışan uygulamaların ayrıntılarını al"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Uygulamaya, şu anda çalışmakta olan ve son çalışan işlemler hakkında ayrıntılı bilgi alma izni verir. Kötü amaçlı uygulamalar diğer uygulamalar hakkında özel bilgileri ele geçirebilir."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"çalışan uygulamaları yeniden sırala"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Uygulamaya, görevleri ön plana ve arka plana taşıma izni verir. Kötü amaçlı uygulamalar kendilerini sizin denetiminiz dışında ön plana taşıyabilir."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"çalışan uygulamaları durdur"</string>
@@ -344,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"Uygulamaya, yayın bittikten sonra da kalan sabit yayınlar gönderme izni verir. Kötü amaçlı uygulamalar tabletin çok fazla bellek kullanmasına neden olarak onu yavaşlatabilir veya kararsız hale getirebilirler."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"Uygulamaya, yayın bittikten sonra da kalan sabit yayınlar gönderme izni verir. Kötü amaçlı uygulamalar telefonun çok fazla bellek kullanmasına neden olarak onu yavaşlatabilir veya dengesiz hale getirebilir."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"kişi verilerini oku"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"Uygulamaya, belirli kişilerle ne sıklıkta sesli çağrı, e-posta ve diğer şekillerde iletişim kurduğunuz da dahil olmak üzere tabletinizde kayıtlı kişilerle ilgili tüm verileri okuma izni verir. Bu seçenek, e-posta adreslerinin otomatik tamamlanmasına ve diğer kullanışlı özelliklerin sağlanmasına yardımcı olur. Kötü amaçlı uygulamalar bu izni kullanarak kişi bilgilerinizi başkalarına gönderebilir."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"Uygulamaya, belirli kişilerle ne sıklıkta sesli çağrı, e-posta ve diğer şekillerde iletişim kurduğunuz da dahil olmak üzere telefonunuzda kayıtlı kişilerle ilgili tüm verileri okuma izni verir. Bu seçenek, e-posta adreslerinin otomatik tamamlanmasına ve diğer kullanışlı özelliklerin sağlanmasına yardımcı olur. Kötü amaçlı uygulamalar bu izni kullanarak kişi bilgilerinizi başkalarına gönderebilir."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"kişi verileri yaz"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"Uygulamaya, belirli kişilerle ne sıklıkta sesli çağrı, e-posta ve diğer şekillerde iletişim kurduğunuz da dahil olmak üzere tabletinizde kayıtlı kişilerle ilgili tüm verileri değiştirme izni verir. Bu seçenek, e-posta adreslerinin otomatik tamamlanmasına ve diğer kullanışlı özelliklerin sağlanmasına yardımcı olur. Kötü amaçlı uygulamalar bu izni kullanarak kişi bilgilerinizi silebilir veya değiştirebilir."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"Uygulamaya, belirli kişilerle ne sıklıkta sesli çağrı, e-posta ve diğer şekillerde iletişim kurduğunuz da dahil olmak üzere telefonunuzda kayıtlı kişilerle ilgili tüm verileri değiştirme izni verir. Bu seçenek, e-posta adreslerinin otomatik tamamlanmasına ve diğer kullanışlı özelliklerin sağlanmasına yardımcı olur. Kötü amaçlı uygulamalar bu izni kullanarak kişi bilgilerinizi silebilir veya değiştirebilir."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"çağrı günlüğünü oku"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"Uygulamaya tabletinizin çağrı günlüğünü (gelen ve giden çağrılarla ilgili veriler dahil olmak üzere) okuma izni verir. Kötü amaçlı uygulamalar bu izni kullanarak verilerinizi başka kişilere gönderebilir."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"Uygulamaya telefonunuzun çağrı günlüğünü (gelen ve giden çağrılarla ilgili veriler dahil olmak üzere) okuma izni verir. Kötü amaçlı uygulamalar bu izni kullanarak verilerinizi başka kişilere gönderebilir."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 92b29db..3b3f3a7 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -342,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"Дозволяє програмі надсилати закріплені широкомовні повідомлення, які залишаються після відтворення широкомовного повідомлення. Шкідливі програми можуть сповільнювати роботу планшетного ПК або порушувати її стабільність, спричиняючи завелике використання пам’яті."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"Дозволяє програмі надсилати закріплені широкомовні повідомлення, які залишаються після відтворення широкомовного повідомлення. Шкідливі програми можуть сповільнювати роботу телефону або порушувати її стабільність, спричиняючи завелике використання пам’яті."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"читати контакт. дані"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"Дозволяє програмі читати всі дані про контакти, які зберігаються на вашому планшетному ПК, зокрема частоту здійснення дзвінків, надсилання електронних листів або інших способів спілкування з окремими особами. Це допомагає автоматично завершувати написання електронних адрес і користуватися іншими зручними функціями. Шкідливі програми можуть використовувати цей дозвіл для надсилання ваших контактних даних іншим людям."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"Дозволяє програмі читати всі дані про контакти, які зберігаються на вашому телефоні, зокрема частоту здійснення дзвінків, надсилання електронних листів або інших способів спілкування з окремими особами. Це допомагає автоматично завершувати написання електронних адрес і користуватися іншими зручними функціями. Шкідливі програми можуть використовувати цей дозвіл для надсилання ваших контактних даних іншим людям."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"запис. контактні дані"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"Дозволяє програмі змінювати всі дані про контакти, які зберігаються на вашому планшетному ПК, зокрема частоту здійснення дзвінків, надсилання електронних листів або інших способів спілкування з окремими особами. Це допомагає автоматично завершувати написання електронних адрес і користуватися іншими зручними функціями. Шкідливі програми можуть використовувати це для стирання чи зміни ваших контактних даних."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"Дозволяє програмі змінювати всі дані про контакти, які зберігаються на вашому телефоні, зокрема частоту здійснення дзвінків, надсилання електронних листів або інших способів спілкування з окремими особами. Це допомагає автоматично завершувати написання електронних адрес і користуватися іншими зручними функціями. Шкідливі програми можуть використовувати це для стирання чи зміни ваших контактних даних."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"читати журнал викликів"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"Дозволяє програмі читати журнал викликів вашого планшетного ПК, включно з даними про вхідні та вихідні дзвінки. Шкідливі програми можуть використовувати це для надсилання ваших даних іншим людям."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"Дозволяє програмі читати журнал викликів вашого телефону, включно з даними про вхідні та вихідні дзвінки. Шкідливі програми можуть використовувати це для надсилання ваших даних іншим людям."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index d527e16..660be8c 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Cho phép ứng dụng nhận và xử lý tin nhắn WAP. Ứng dụng độc hại có thể giám sát tin nhắn của bạn hoặc xóa tin nhắn mà không hiển thị chúng cho bạn."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"truy xuất các ứng dụng đang chạy"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Cho phép ứng dụng truy xuất thông tin về các công việc đã và đang chạy gần đây. Ứng dụng độc hại có thể phát hiện thông tin riêng tư về các ứng dụng khác."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"truy xuất chi tiết về các ứng dụng đang chạy"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Cho phép ứng dụng truy xuất thông tin chi tiết về các tác vụ đã và đang chạy gần đây. Ứng dụng độc hại có thể phát hiện thông tin riêng tư về các ứng dụng khác."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"sắp xếp lại những ứng dụng đang chạy"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Cho phép ứng dụng di chuyển công việc sang nền trước và nền sau. Ứng dụng độc hại có thể tự hiển thị ở nền trước mà không chịu sự kiểm soát của bạn."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"dừng các ứng dụng đang chạy"</string>
@@ -344,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"Cho phép ứng dụng gửi nội dung truyền phát hấp dẫn người xem. Nội dung này sẽ vẫn còn sau khi quá trình truyền phát kết thúc. Ứng dụng độc hại có thể làm cho máy tính bảng bị chậm hoặc không ổn định bằng cách khiến máy tính bảng sử dụng quá nhiều bộ nhớ."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"Cho phép ứng dụng gửi nội dung truyền phát hấp dẫn người xem. Nội dung này sẽ vẫn còn sau khi quá trình truyền phát kết thúc. Ứng dụng độc hại có thể làm cho điện thoại bị chậm hoặc không ổn định bằng cách khiến điện thoại sử dụng quá nhiều bộ nhớ."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"đọc dữ liệu liên hệ"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"Cho phép ứng dụng đọc tất cả dữ liệu về các liên hệ được lưu trữ trên máy tính bảng của bạn, bao gồm cả các liên hệ mà bạn thường xuyên gọi, gửi email hoặc liên lạc theo các cách khác với các cá nhân cụ thể. Việc này giúp ích cho tính năng tự động hoàn tất địa chỉ email và các tính năng tiện lợi khác. Các ứng dụng độc hại có thể sử dụng quyền này để gửi dữ liệu liên hệ của bạn cho những người khác."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"Cho phép ứng dụng đọc tất cả dữ liệu về các liên hệ được lưu trữ trên điện thoại của bạn, bao gồm cả các liên hệ mà bạn thường xuyên gọi, gửi email hoặc liên lạc theo các cách khác với các cá nhân cụ thể. Việc này giúp ích cho tính năng tự động hoàn tất địa chỉ email và các tính năng tiện lợi khác. Các ứng dụng độc hại có thể sử dụng quyền này để gửi dữ liệu liên hệ của bạn cho những người khác."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"ghi dữ liệu liên hệ"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"Cho phép ứng dụng sửa đổi dữ liệu về các liên hệ được lưu trữ trên máy tính bảng của bạn, bao gồm cả các liên hệ mà bạn thường xuyên gọi, gửi email hoặc liên lạc theo các cách khác với các cá nhân cụ thể. Việc này giúp ích cho tính năng tự động hoàn tất địa chỉ email và các tính năng tiện lợi khác. Các ứng dụng độc hại có thể sử dụng quyền này để xóa hoặc sửa đổi dữ liệu liên hệ của bạn."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"Cho phép ứng dụng sửa đổi dữ liệu về các liên hệ được lưu trữ trên điện thoại của bạn, bao gồm cả các liên hệ mà bạn thường xuyên gọi, gửi email hoặc liên lạc theo các cách khác với các cá nhân cụ thể. Việc này giúp ích cho tính năng tự động hoàn tất địa chỉ email và các tính năng tiện lợi khác. Các ứng dụng độc hại có thể sử dụng quyền này để xóa hoặc sửa đổi dữ liệu liên hệ của bạn."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"đọc nhật ký cuộc gọi"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"Cho phép ứng dụng đọc nhật ký cuộc gọi trên máy tính bảng của bạn, bao gồm dữ liệu về các cuộc gọi đến và gọi đi. Các ứng dụng độc hại có thể sử dụng quyền này để gửi dữ liệu của bạn cho những người khác."</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"Cho phép ứng dụng đọc nhật ký cuộc gọi trên điện thoại của bạn, bao gồm dữ liệu về các cuộc gọi đến và gọi đi. Các ứng dụng độc hại có thể sử dụng quyền này để gửi dữ liệu của bạn cho những người khác."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 115bc82..0d0835c 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -344,15 +344,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"允许应用发送持久广播,此类广播在结束后仍会保留。恶意应用可能会导致平板电脑使用过多内存,从而使速度变慢或变得不稳定。"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"允许应用发送持久广播,此类广播在结束后仍会保留。恶意应用可能会导致手机使用过多内存,从而使速度变慢或变得不稳定。"</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"读取联系人数据"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"允许该应用读取与您平板电脑上存储的联系人相关的所有数据,包括您呼叫特定联系人、向其发送电子邮件或以其他方式通信的频率。这有助于自动填充电子邮件地址,以及实现其他某些便利功能。恶意应用可能会借此将您的联系人数据发送给他人。"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"允许该应用读取与您手机上存储的联系人相关的所有数据,包括您呼叫特定联系人、向其发送电子邮件或以其他方式通信的频率。这有助于自动填充电子邮件地址,以及实现其他某些便利功能。恶意应用可能会借此将您的联系人数据发送给他人。"</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"写入联系数据"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"允许该应用修改与您平板电脑上存储的联系人相关的数据,包括您呼叫特定联系人、向其发送电子邮件或以其他方式通信的频率。这有助于自动填充电子邮件地址,以及实现其他某些便利功能。恶意应用可能会借此删除或修改您的联系人数据。"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"允许该应用修改与您手机上存储的联系人相关的数据,包括您呼叫特定联系人、向其发送电子邮件或以其他方式通信的频率。这有助于自动填充电子邮件地址,以及实现其他某些便利功能。恶意应用可能会借此删除或修改您的联系人数据。"</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"读取通话记录"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"允许该应用读取平板电脑的通话记录,包括有关来电和外拨电话的数据。恶意应用可能会借此将您的数据发送给他人。"</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"允许该应用读取手机的通话记录,包括有关来电和外拨电话的数据。恶意应用可能会借此将您的数据发送给他人。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 78ce6a1..637d319 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"允許應用程式接收及處理 WAP 訊息。請注意,惡意應用程式可能利用此功能監視訊息,或在您讀取訊息前擅自將其刪除。"</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"擷取執行中的應用程式"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"允許應用程式取得最近執行任務的資訊。請注意,惡意應用程式可能利用此功能找出其他應用程式的隱私資訊。"</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"擷取執行中應用程式的詳細資料"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"允許應用程式擷取目前及最近執行任務的詳細資訊。惡意應用程式可能會找出其他應用程式的私人資訊。"</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"重新排序正在執行的應用程式"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"允許應用程式將工作移至前景或背景。請注意,惡意應用程式可能利用此功能自行移動至前景。"</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"停止執行中的應用程式"</string>
@@ -344,15 +342,11 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"允許應用程式傳送記憶廣播,這類廣播在廣播動作結束後仍繼續存在。請注意,惡意應用程式可能利用此功能讓平板電腦使用過多的記憶體,導致平板電腦的執行速度變慢或不穩定。"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"允許應用程式傳送記憶廣播,這類廣播在廣播動作結束後仍繼續存在。請注意,惡意應用程式可能利用此功能讓手機使用過多的記憶體,導致手機的執行速度變慢或不穩定。"</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"讀取聯絡人資料"</string>
- <!-- no translation found for permdesc_readContacts (6370069055638209432) -->
- <skip />
- <!-- no translation found for permdesc_readContacts (4093353182535351501) -->
- <skip />
+ <string name="permdesc_readContacts" product="tablet" msgid="6370069055638209432">"允許應用程式讀取儲存在平板電腦中的所有聯絡人資料,包括您與特定聯絡人通話、傳送電子郵件或使用其他通訊方式的互動頻率,這樣您就可以在輸入電子郵件地址時使用自動完成功能和其他便利功能。不過,惡意應用程式也可藉此將您的聯絡人資料傳送給其他人。"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4093353182535351501">"允許應用程式讀取儲存在手機中的所有聯絡人資料,包括您與特定聯絡人通話、傳送電子郵件或使用其他通訊方式的互動頻率,這樣您就可以在輸入電子郵件地址時使用自動完成功能和其他便利功能。不過,惡意應用程式也可藉此將您的聯絡人資料傳送給其他人。"</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"輸入聯絡人資料"</string>
- <!-- no translation found for permdesc_writeContacts (5495863352173533286) -->
- <skip />
- <!-- no translation found for permdesc_writeContacts (6108469962248865715) -->
- <skip />
+ <string name="permdesc_writeContacts" product="tablet" msgid="5495863352173533286">"允許應用程式修改儲存在平板電腦中的資料,包括您與特定聯絡人通話、傳送電子郵件或使用其他通訊方式的互動頻率,這樣您就可以在輸入電子郵件地址時使用自動完成功能和其他便利功能。不過,惡意應用程式也可藉此清除或修改您的聯絡人資料。"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="6108469962248865715">"允許應用程式修改儲存在手機中的資料,包括您與特定聯絡人通話、傳送電子郵件或使用其他通訊方式的互動頻率,這樣您就可以在輸入電子郵件地址時使用自動完成功能和其他便利功能。不過,惡意應用程式也可藉此清除或修改您的聯絡人資料。"</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"讀取通話紀錄"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"允許應用程式讀取平板電腦的通話紀錄,包括來電和已撥電話相關資料。請注意,惡意應用程式可能濫用此功能將您的資料傳送給他人。"</string>
<string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"允許應用程式讀取手機的通話紀錄,包括來電和已撥電話相關資料。請注意,惡意應用程式可能濫用此功能將您的資料傳送給他人。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 91aa9fd..05981cd 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -217,10 +217,8 @@
<string name="permdesc_receiveWapPush" msgid="7983455145335316872">"Ivumela ukuthi insiza yamukele iphinde isebenze imiyalezo ye-WAP. Izinsiza ezinobungozi zingabheka imiyalezo yakho noma ziyisuse ngaphandle kokuthi zikukhombise."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"thola izinsiza ezisebenzayo"</string>
<string name="permdesc_getTasks" msgid="6608159250520381359">"Ivumela insiza uuthi ithole kabusha ulwazi mayelana nezinto ezenzeka manje nezisanda kwenzeka. Izinsiza ezinobungozi zingathola imininingwane eyimfihlo mayelana nezinye izinsiza."</string>
- <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
- <skip />
- <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
- <skip />
+ <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"thola kabusha imininingwane yezinhlelo zokusebenza ezisebenzayo"</string>
+ <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Ivumela uhlelo lokusebenza ukuthola kabusha ulwazi mayelana nezinto ezenzeka manje nezisanda kwenzeka. Izinhlelo zokusebenza ezingalungile zingathola imininingwane eyimfihlo mayelana nezinye izinhlelo zokusebenza."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"misa kabusha izinsiza ezisebenzayo"</string>
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Ivumela insiza ukuthi ihambise izenzo ziye ngaphambili kanye nasemumva. Izinsiza ezinobungozi zingaziphoqelela ukuth iziye phambili ngaphandle kokulawula kwakho."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"misa izinsiza ezisebenzayo"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index acf63a1..472b19c 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -271,8 +271,7 @@
<!-- Boolean indicating whether the wifi chipset supports background scanning mechanism.
This mechanism allows the host to remain in suspend state and the dongle to actively
scan and wake the host when a configured SSID is detected by the dongle. This chipset
- capability can provide power savings when wifi needs to be always kept on.
- The driver commands needed to support the feature are BGSCAN-START and BGSCAN-STOP -->
+ capability can provide power savings when wifi needs to be always kept on. -->
<bool translatable="false" name="config_wifi_background_scan_support">false</bool>
<!-- Integer indicating wpa_supplicant scan interval in milliseconds -->
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index bda6266..f812822 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -194,7 +194,7 @@
<dimen name="activity_chooser_popup_min_width">200dip</dimen>
<!-- The default gap between components in a layout. -->
- <dimen name="default_gap">16dip</dimen>
+ <dimen name="default_gap">8dip</dimen>
<!-- Text padding for dropdown items -->
<dimen name="dropdownitem_text_padding_left">8dip</dimen>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 213f692..bc1e79c 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -456,21 +456,21 @@
<string name="permdesc_expandStatusBar">Allows the app to expand or collapse the status bar.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_processOutgoingCalls">intercept outgoing calls</string>
+ <string name="permlab_processOutgoingCalls">reroute outgoing calls</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_processOutgoingCalls">Allows the app to
process outgoing calls and change the number to be dialed. Malicious
apps may monitor, redirect, or prevent outgoing calls.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_receiveSms">receive SMS</string>
+ <string name="permlab_receiveSms">receive text messages (SMS)</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_receiveSms">Allows the app to receive
and process SMS messages. Malicious apps may monitor
your messages or delete them without showing them to you.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_receiveMms">receive MMS</string>
+ <string name="permlab_receiveMms">receive text messages (MMS)</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_receiveMms">Allows the app to receive
and process MMS messages. Malicious apps may monitor
@@ -507,7 +507,7 @@
messages without your confirmation.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_readSms">read SMS or MMS</string>
+ <string name="permlab_readSms">read your text messages (SMS or MMS)</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_readSms" product="tablet">Allows the app to read
SMS messages stored on your tablet or SIM card. Malicious apps
@@ -518,7 +518,7 @@
may read your confidential messages.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_writeSms">edit SMS or MMS</string>
+ <string name="permlab_writeSms">edit your text messages (SMS or MMS)</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_writeSms" product="tablet">Allows the app to write
to SMS messages stored on your tablet or SIM card. Malicious apps
@@ -529,7 +529,7 @@
may delete your messages.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_receiveWapPush">receive WAP</string>
+ <string name="permlab_receiveWapPush">receive text messages (WAP)</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_receiveWapPush">Allows the app to receive
and process WAP messages. Malicious apps may monitor
@@ -539,7 +539,7 @@
<string name="permlab_getTasks">retrieve running apps</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_getTasks">Allows the app to retrieve
- information about currently and recently running tasks. Malicious apps may
+ information about currently and recently running tasks. Malicious apps may
discover private information about other apps.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=50] -->
@@ -583,7 +583,7 @@
to kill other apps.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_changeConfiguration">change your UI settings</string>
+ <string name="permlab_changeConfiguration">change system display settings</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_changeConfiguration">Allows the app to
change the current configuration, such as the locale or overall font
@@ -596,7 +596,7 @@
enable the car mode.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_killBackgroundProcesses">kill background processes</string>
+ <string name="permlab_killBackgroundProcesses">close other apps</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_killBackgroundProcesses">Allows the app to
kill background processes of other apps, even if memory
@@ -681,7 +681,7 @@
needed for normal apps.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_setAlwaysFinish">make all background apps close</string>
+ <string name="permlab_setAlwaysFinish">force background apps to close</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_setAlwaysFinish">Allows the app
to control whether activities are always finished as soon as they
@@ -690,7 +690,7 @@
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_batteryStats">modify battery statistics</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_batteryStats">Allows the app to modify
+ <string name="permdesc_batteryStats">Allows the app to modify
collected battery statistics. Not for use by normal apps.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -711,7 +711,7 @@
user interface. Not for use by normal apps.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_systemAlertWindow">display system-level alerts</string>
+ <string name="permlab_systemAlertWindow">draw over other apps</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_systemAlertWindow">Allows the app to
show system alert windows. Malicious apps may take over the
@@ -920,7 +920,7 @@
existing apps to collect private data from you.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_writeSettings">modify global system settings</string>
+ <string name="permlab_writeSettings">modify system settings</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_writeSettings">Allows the app to modify the
system\'s settings data. Malicious apps may corrupt your system\'s
@@ -937,7 +937,7 @@
Google services map. Not for use by normal apps.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_receiveBootCompleted">automatically start at boot</string>
+ <string name="permlab_receiveBootCompleted">run at startup</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_receiveBootCompleted" product="tablet">Allows the app to
have itself started as soon as the system has finished booting.
@@ -963,7 +963,7 @@
to use too much memory.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_readContacts">read contact data</string>
+ <string name="permlab_readContacts">read your contacts</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_readContacts" product="tablet">Allows the app to read all
the data about your contacts stored on your tablet, including the frequency
@@ -980,7 +980,7 @@
other people.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_writeContacts">write contact data</string>
+ <string name="permlab_writeContacts">modify your contacts</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_writeContacts" product="tablet">Allows the app to modify
the data about your contacts stored on your tablet, including the frequency
@@ -1014,14 +1014,14 @@
<!-- Title of the read profile permission, listed so the user can decide whether to allow the application to read the user's personal profile data. [CHAR LIMIT=30] -->
- <string name="permlab_readProfile">read your profile data</string>
+ <string name="permlab_readProfile">read your own contact card</string>
<!-- Description of the read profile permission, listed so the user can decide whether to allow the application to read the user's personal profile data. [CHAR LIMIT=NONE] -->
<string name="permdesc_readProfile" product="default">Allows the app to read personal
profile information stored on your device, such as your name and contact information. This
means the app can identify you and send your profile information to others.</string>
<!-- Title of the write profile permission, listed so the user can decide whether to allow the application to write to the user's personal profile data. [CHAR LIMIT=30] -->
- <string name="permlab_writeProfile">write to your profile data</string>
+ <string name="permlab_writeProfile">modify your own contact card</string>
<!-- Description of the write profile permission, listed so the user can decide whether to allow the application to write to the user's personal profile data. [CHAR LIMIT=NONE] -->
<string name="permdesc_writeProfile" product="default">Allows the app to change or add
to personal profile information stored on your device, such as your name and contact
@@ -1045,18 +1045,18 @@
<string name="permlab_readCalendar">read calendar events plus confidential information</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_readCalendar" product="tablet">Allows the app to read all calendar
- events stored on your tablet, including those of friends or coworkers. Malicious apps
+ events stored on your tablet, including those of friends or coworkers. Malicious apps
may extract personal information from these calendars without the owners\' knowledge.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_readCalendar" product="default">Allows the app to read all calendar
- events stored on your phone, including those of friends or coworkers. Malicious apps
+ events stored on your phone, including those of friends or coworkers. Malicious apps
may extract personal information from these calendars without the owners\' knowledge.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_writeCalendar">add or modify calendar events and send email to guests without owners\' knowledge</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_writeCalendar">Allows the app to send event invitations as the calendar owner and add, remove,
- change events that you can modify on your device, including those of friends or co-workers. Malicious apps
+ change events that you can modify on your device, including those of friends or co-workers. Malicious apps
may send spam emails that appear to come from calendar owners, modify events without the owners\' knowledge, or add fake events.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -1151,14 +1151,19 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_reboot" product="default">Allows the app to force the phone to reboot.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
+ <string name="permlab_mount_unmount_filesystems" product="nosdcard">access USB storage filesystem</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_mount_unmount_filesystems">mount and unmount filesystems</string>
+ <string name="permlab_mount_unmount_filesystems" product="default">access SD Card filesystem</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_mount_unmount_filesystems">Allows the app to mount and
unmount filesystems for removable storage.</string>
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
+ <string name="permlab_mount_format_filesystems" product="nosdcard">erase USB storage</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_mount_format_filesystems">format external storage</string>
+ <string name="permlab_mount_format_filesystems" product="default">erase SD Card</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_mount_format_filesystems">Allows the app to format removable storage.</string>
@@ -1188,7 +1193,7 @@
<string name="permdesc_asec_rename">Allows the app to rename internal storage.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_vibrate">control vibrator</string>
+ <string name="permlab_vibrate">control vibration</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_vibrate">Allows the app to control the vibrator.</string>
@@ -1267,7 +1272,7 @@
you.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_readPhoneState">read phone state and identity</string>
+ <string name="permlab_readPhoneState">read phone status and identity</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_readPhoneState">Allows the app to access the phone
features of the device. An app with this permission can determine the phone
@@ -1310,7 +1315,7 @@
<string name="permdesc_setWallpaper">Allows the app to set the system wallpaper.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_setWallpaperHints">set wallpaper size hints</string>
+ <string name="permlab_setWallpaperHints">adjust your wallpaper size</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_setWallpaperHints">Allows the app to set the system wallpaper size hints.</string>
@@ -1341,14 +1346,14 @@
<string name="permdesc_accountManagerService">Allows the app to make calls to AccountAuthenticators.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_getAccounts">discover known accounts</string>
+ <string name="permlab_getAccounts">find accounts on the device</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_getAccounts" product="tablet">Allows the app to get the list of accounts known by the tablet.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_getAccounts" product="default">Allows the app to get the list of accounts known by the phone.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_authenticateAccounts">act as an account authenticator</string>
+ <string name="permlab_authenticateAccounts">create accounts and set passwords</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_authenticateAccounts">Allows the app
to use the account authenticator capabilities of the
@@ -1356,19 +1361,19 @@
setting their passwords.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_manageAccounts">manage the accounts list</string>
+ <string name="permlab_manageAccounts">add or remove accounts</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_manageAccounts">Allows the app to
perform operations like adding and removing accounts, and deleting
their password.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_useCredentials">use the authentication credentials of an account</string>
+ <string name="permlab_useCredentials">use accounts on the device</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_useCredentials">Allows the app to request authentication tokens.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_accessNetworkState">view network state</string>
+ <string name="permlab_accessNetworkState">view network connections</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_accessNetworkState">Allows the app to view the state of all networks.</string>
@@ -1400,12 +1405,12 @@
<string name="permdesc_changeBackgroundDataSetting">Allows the app to change the background data usage setting.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_accessWifiState">view Wi-Fi state</string>
+ <string name="permlab_accessWifiState">view Wi-Fi connections</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_accessWifiState">Allows the app to view the information about the state of Wi-Fi.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_changeWifiState">change Wi-Fi state</string>
+ <string name="permlab_changeWifiState">connect and disconnect from Wi-Fi</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_changeWifiState">Allows the app to connect to and disconnect from Wi-Fi access points, and to make changes to
configured Wi-Fi networks.</string>
@@ -1419,7 +1424,7 @@
than the non-multicast mode.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_bluetoothAdmin">Bluetooth administration</string>
+ <string name="permlab_bluetoothAdmin">access Bluetooth settings</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_bluetoothAdmin" product="tablet">Allows the app to
configure the local Bluetooth tablet, and to discover and pair with remote
@@ -1428,13 +1433,13 @@
<string name="permdesc_bluetoothAdmin" product="default">Allows the app to configure
the local Bluetooth phone, and to discover and pair with remote devices.</string>
- <string name="permlab_accessWimaxState">View WiMAX state</string>
+ <string name="permlab_accessWimaxState">View WiMAX connections</string>
<string name="permdesc_accessWimaxState">Allows the app to view the information about the state of WiMAX.</string>
<string name="permlab_changeWimaxState">Change WiMAX state</string>
<string name="permdesc_changeWimaxState">Allows the app to connect to and disconnect from WiMAX network.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_bluetooth">create Bluetooth connections</string>
+ <string name="permlab_bluetooth">pair with Bluetooth devices</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_bluetooth" product="tablet">Allows the app to view the
configuration of the local Bluetooth tablet, and to make and accept
@@ -1451,7 +1456,7 @@
with Near Field Communication (NFC) tags, cards, and readers.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_disableKeyguard">disable keylock</string>
+ <string name="permlab_disableKeyguard">disable your screen lock</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_disableKeyguard">Allows the app to disable
the keylock and any associated password security. A legitimate example of
@@ -1465,7 +1470,7 @@
such as whether sync is enabled for the People app.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_writeSyncSettings">write sync settings</string>
+ <string name="permlab_writeSyncSettings">toggle sync on and off</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_writeSyncSettings">Allows the app to modify the sync
settings, such as whether sync is enabled for the People app.</string>
@@ -1488,7 +1493,7 @@
your currently synced feeds. Malicious apps may change your synced feeds.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_readDictionary">read user-defined dictionary</string>
+ <string name="permlab_readDictionary">read terms you added to the dictionary</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_readDictionary">Allows the app to read any private
words, names and phrases that the user may have stored in the user dictionary.</string>
@@ -1500,18 +1505,18 @@
user dictionary.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
- <string name="permlab_sdcardRead" product="nosdcard">read USB storage contents</string>
+ <string name="permlab_sdcardRead" product="nosdcard">read the contents of your USB storage</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_sdcardRead" product="default">read SD card contents</string>
+ <string name="permlab_sdcardRead" product="default">read the contents of your SD card</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
- <string name="permdesc_sdcardRead" product="nosdcard">Allows the app to read contents of USB storage.</string>
+ <string name="permdesc_sdcardRead" product="nosdcard">Allows the app to read contents of USB storage, which may include photos and media.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_sdcardRead" product="default">Allows the app to read contents of SD card.</string>
+ <string name="permdesc_sdcardRead" product="default">Allows the app to read contents of SD card, which may include photos and media.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
- <string name="permlab_sdcardWrite" product="nosdcard">modify/delete USB storage contents</string>
+ <string name="permlab_sdcardWrite" product="nosdcard">modify or delete the contents of your USB storage</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_sdcardWrite" product="default">modify/delete SD card contents</string>
+ <string name="permlab_sdcardWrite" product="default">modify or delete the contens of your SD card</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
<string name="permdesc_sdcardWrite" product="nosdcard">Allows the app to write to the USB storage.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -2279,14 +2284,14 @@
<!-- Title of an application permission, listed so the user can choose whether
they want to allow the application to do this. -->
- <string name="permlab_readHistoryBookmarks">read Browser\'s history and bookmarks</string>
+ <string name="permlab_readHistoryBookmarks">read your Web bookmarks and history</string>
<!-- Description of an application permission, listed so the user can choose whether
they want to allow the application to do this. -->
<string name="permdesc_readHistoryBookmarks">Allows the app to read all
the URLs that the Browser has visited, and all of the Browser\'s bookmarks.</string>
<!-- Title of an application permission, listed so the user can choose whether
they want to allow the application to do this. -->
- <string name="permlab_writeHistoryBookmarks">write Browser\'s history and bookmarks</string>
+ <string name="permlab_writeHistoryBookmarks">write web bookmarks and history</string>
<!-- Description of an application permission, listed so the user can choose whether
they want to allow the application to do this. -->
<string name="permdesc_writeHistoryBookmarks" product="tablet">Allows the app to modify the
@@ -2300,7 +2305,7 @@
<!-- Title of an application permission, listed so the user can choose whether
they want to allow the application to do this. -->
- <string name="permlab_setAlarm">set alarm in alarm clock</string>
+ <string name="permlab_setAlarm">set an alarm</string>
<!-- Description of an application permission, listed so the user can choose whether
they want to allow the application to do this. -->
<string name="permdesc_setAlarm">Allows the app to set an alarm in
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 006baa7..b68b267 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -56,6 +56,7 @@
private NinePatchState mNinePatchState;
private NinePatch mNinePatch;
private Rect mPadding;
+ private Insets mLayoutInsets = Insets.NONE;
private Paint mPaint;
private boolean mMutated;
@@ -180,12 +181,21 @@
}
}
+ private Insets scaleFromDensity(Insets insets, int sdensity, int tdensity) {
+ int left = Bitmap.scaleFromDensity(insets.left, sdensity, tdensity);
+ int top = Bitmap.scaleFromDensity(insets.top, sdensity, tdensity);
+ int right = Bitmap.scaleFromDensity(insets.right, sdensity, tdensity);
+ int bottom = Bitmap.scaleFromDensity(insets.bottom, sdensity, tdensity);
+ return Insets.of(left, top, right, bottom);
+ }
+
private void computeBitmapSize() {
final int sdensity = mNinePatch.getDensity();
final int tdensity = mTargetDensity;
if (sdensity == tdensity) {
mBitmapWidth = mNinePatch.getWidth();
mBitmapHeight = mNinePatch.getHeight();
+ mLayoutInsets = mNinePatchState.mLayoutInsets;
} else {
mBitmapWidth = Bitmap.scaleFromDensity(mNinePatch.getWidth(),
sdensity, tdensity);
@@ -202,6 +212,7 @@
dest.right = Bitmap.scaleFromDensity(src.right, sdensity, tdensity);
dest.bottom = Bitmap.scaleFromDensity(src.bottom, sdensity, tdensity);
}
+ mLayoutInsets = scaleFromDensity(mNinePatchState.mLayoutInsets, sdensity, tdensity);
}
}
@@ -226,7 +237,7 @@
*/
@Override
public Insets getLayoutInsets() {
- return mNinePatchState.mLayoutInsets;
+ return mLayoutInsets;
}
@Override
diff --git a/include/androidfw/Input.h b/include/androidfw/Input.h
index a98e1a2..044f2bf 100644
--- a/include/androidfw/Input.h
+++ b/include/androidfw/Input.h
@@ -208,6 +208,7 @@
status_t setAxisValue(int32_t axis, float value);
void scale(float scale);
+ void lerp(const PointerCoords& a, const PointerCoords& b, float alpha);
inline float getX() const {
return getAxisValue(AMOTION_EVENT_AXIS_X);
diff --git a/include/androidfw/InputTransport.h b/include/androidfw/InputTransport.h
index 29c296e..2924505 100644
--- a/include/androidfw/InputTransport.h
+++ b/include/androidfw/InputTransport.h
@@ -33,6 +33,7 @@
#include <utils/RefBase.h>
#include <utils/String8.h>
#include <utils/Vector.h>
+#include <utils/BitSet.h>
namespace android {
@@ -271,6 +272,9 @@
* If consumeBatches is true, then events are still batched but they are consumed
* immediately as soon as the input channel is exhausted.
*
+ * The frameTime parameter specifies the time when the current display frame started
+ * rendering in the CLOCK_MONOTONIC time base, or -1 if unknown.
+ *
* The returned sequence number is never 0 unless the operation failed.
*
* Returns OK on success.
@@ -280,7 +284,7 @@
* Other errors probably indicate that the channel is broken.
*/
status_t consume(InputEventFactoryInterface* factory, bool consumeBatches,
- uint32_t* outSeq, InputEvent** outEvent);
+ nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent);
/* Sends a finished signal to the publisher to inform it that the message
* with the specified sequence number has finished being process and whether
@@ -298,7 +302,7 @@
* has a deferred event to be processed. Deferred events are somewhat special in
* that they have already been removed from the input channel. If the input channel
* becomes empty, the client may need to do extra work to ensure that it processes
- * the deferred event despite the fact that the inptu channel's file descriptor
+ * the deferred event despite the fact that the input channel's file descriptor
* is not readable.
*
* One option is simply to call consume() in a loop until it returns WOULD_BLOCK.
@@ -329,11 +333,55 @@
// Batched motion events per device and source.
struct Batch {
- uint32_t seq; // sequence number of last input message batched in the event
- MotionEvent event;
+ Vector<InputMessage> samples;
};
Vector<Batch> mBatches;
+ // Touch state per device and source, only for sources of class pointer.
+ struct History {
+ nsecs_t eventTime;
+ BitSet32 idBits;
+ PointerCoords pointers[MAX_POINTERS];
+
+ void initializeFrom(const InputMessage* msg) {
+ eventTime = msg->body.motion.eventTime;
+ idBits.clear();
+ for (size_t i = 0; i < msg->body.motion.pointerCount; i++) {
+ uint32_t id = msg->body.motion.pointers[i].properties.id;
+ idBits.markBit(id);
+ size_t index = idBits.getIndexOfBit(id);
+ pointers[index].copyFrom(msg->body.motion.pointers[i].coords);
+ }
+ }
+ };
+ struct TouchState {
+ int32_t deviceId;
+ int32_t source;
+ size_t historyCurrent;
+ size_t historySize;
+ History history[2];
+
+ void initialize(int32_t deviceId, int32_t source) {
+ this->deviceId = deviceId;
+ this->source = source;
+ historyCurrent = 0;
+ historySize = 0;
+ }
+
+ void addHistory(const InputMessage* msg) {
+ historyCurrent ^= 1;
+ if (historySize < 2) {
+ historySize += 1;
+ }
+ history[historyCurrent].initializeFrom(msg);
+ }
+
+ const History* getHistory(size_t index) const {
+ return &history[(historyCurrent + index) & 1];
+ }
+ };
+ Vector<TouchState> mTouchStates;
+
// Chain of batched sequence numbers. When multiple input messages are combined into
// a batch, we append a record here that associates the last sequence number in the
// batch with the previous one. When the finished signal is sent, we traverse the
@@ -344,13 +392,26 @@
};
Vector<SeqChain> mSeqChains;
+ status_t consumeBatch(InputEventFactoryInterface* factory,
+ nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent);
+ status_t consumeSamples(InputEventFactoryInterface* factory,
+ Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent);
+
+ void updateTouchState(InputMessage* msg);
+ void resampleTouchState(nsecs_t frameTime, MotionEvent* event,
+ const InputMessage *next);
+
ssize_t findBatch(int32_t deviceId, int32_t source) const;
+ ssize_t findTouchState(int32_t deviceId, int32_t source) const;
+
status_t sendUnchainedFinishedSignal(uint32_t seq, bool handled);
static void initializeKeyEvent(KeyEvent* event, const InputMessage* msg);
static void initializeMotionEvent(MotionEvent* event, const InputMessage* msg);
- static bool canAppendSamples(const MotionEvent* event, const InputMessage* msg);
- static void appendSamples(MotionEvent* event, const InputMessage* msg);
+ static void addSample(MotionEvent* event, const InputMessage* msg);
+ static bool canAddSample(const Batch& batch, const InputMessage* msg);
+ static ssize_t findSampleNoLaterThan(const Batch& batch, nsecs_t time);
+ static bool shouldResampleTool(int32_t toolType);
};
} // namespace android
diff --git a/libs/androidfw/Input.cpp b/libs/androidfw/Input.cpp
index 1617a3f..fbe1926 100644
--- a/libs/androidfw/Input.cpp
+++ b/libs/androidfw/Input.cpp
@@ -229,6 +229,26 @@
scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MINOR, scaleFactor);
}
+void PointerCoords::lerp(const PointerCoords& a, const PointerCoords& b, float alpha) {
+ bits = 0;
+ for (uint64_t bitsRemaining = a.bits | b.bits; bitsRemaining; ) {
+ int32_t axis = __builtin_ctz(bitsRemaining);
+ uint64_t axisBit = 1LL << axis;
+ bitsRemaining &= ~axisBit;
+ if (a.bits & axisBit) {
+ if (b.bits & axisBit) {
+ float aval = a.getAxisValue(axis);
+ float bval = b.getAxisValue(axis);
+ setAxisValue(axis, aval + alpha * (bval - aval));
+ } else {
+ setAxisValue(axis, a.getAxisValue(axis));
+ }
+ } else {
+ setAxisValue(axis, b.getAxisValue(axis));
+ }
+ }
+}
+
#ifdef HAVE_ANDROID_OS
status_t PointerCoords::readFromParcel(Parcel* parcel) {
bits = parcel->readInt64();
diff --git a/libs/androidfw/InputTransport.cpp b/libs/androidfw/InputTransport.cpp
index 294236f..9a4182c 100644
--- a/libs/androidfw/InputTransport.cpp
+++ b/libs/androidfw/InputTransport.cpp
@@ -16,6 +16,9 @@
// Log debug messages about transport actions
#define DEBUG_TRANSPORT_ACTIONS 0
+// Log debug messages about touch event resampling
+#define DEBUG_RESAMPLING 0
+
#include <cutils/log.h>
#include <errno.h>
@@ -24,6 +27,7 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <math.h>
namespace android {
@@ -34,6 +38,20 @@
// behind processing touches.
static const size_t SOCKET_BUFFER_SIZE = 32 * 1024;
+// Nanoseconds per milliseconds.
+static const nsecs_t NANOS_PER_MS = 1000000;
+
+// Latency added during resampling. A few milliseconds doesn't hurt much but
+// reduces the impact of mispredicted touch positions.
+static const nsecs_t RESAMPLE_LATENCY = 4 * NANOS_PER_MS;
+
+// Minimum time difference between consecutive samples before attempting to resample.
+static const nsecs_t RESAMPLE_MIN_DELTA = 1 * NANOS_PER_MS;
+
+// Maximum linear interpolation scale value. The larger this is, the more error may
+// potentially be introduced.
+static const float RESAMPLE_MAX_ALPHA = 2.0f;
+
// --- InputMessage ---
@@ -341,10 +359,10 @@
}
status_t InputConsumer::consume(InputEventFactoryInterface* factory,
- bool consumeBatches, uint32_t* outSeq, InputEvent** outEvent) {
+ bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
#if DEBUG_TRANSPORT_ACTIONS
- ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s",
- mChannel->getName().string(), consumeBatches ? "true" : "false");
+ ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%lld",
+ mChannel->getName().string(), consumeBatches ? "true" : "false", frameTime);
#endif
*outSeq = 0;
@@ -362,20 +380,15 @@
status_t result = mChannel->receiveMessage(&mMsg);
if (result) {
// Consume the next batched event unless batches are being held for later.
- if (!mBatches.isEmpty() && (consumeBatches || result != WOULD_BLOCK)) {
- MotionEvent* motionEvent = factory->createMotionEvent();
- if (! motionEvent) return NO_MEMORY;
-
- const Batch& batch = mBatches.top();
- motionEvent->copyFrom(&batch.event, true /*keepHistory*/);
- *outSeq = batch.seq;
- *outEvent = motionEvent;
- mBatches.pop();
+ if (consumeBatches || result != WOULD_BLOCK) {
+ result = consumeBatch(factory, frameTime, outSeq, outEvent);
+ if (*outEvent) {
#if DEBUG_TRANSPORT_ACTIONS
- ALOGD("channel '%s' consumer ~ consumed batch event, seq=%u",
- mChannel->getName().string(), *outSeq);
+ ALOGD("channel '%s' consumer ~ consumed batch event, seq=%u",
+ mChannel->getName().string(), *outSeq);
#endif
- break;
+ break;
+ }
}
return result;
}
@@ -400,35 +413,23 @@
ssize_t batchIndex = findBatch(mMsg.body.motion.deviceId, mMsg.body.motion.source);
if (batchIndex >= 0) {
Batch& batch = mBatches.editItemAt(batchIndex);
- if (canAppendSamples(&batch.event, &mMsg)) {
- // Append to the batch and save the new sequence number for the tail end.
- uint32_t chain = batch.seq;
- appendSamples(&batch.event, &mMsg);
- batch.seq = mMsg.body.motion.seq;
-
- // Update the sequence number chain.
- SeqChain seqChain;
- seqChain.seq = batch.seq;
- seqChain.chain = chain;
- mSeqChains.push(seqChain);
+ if (canAddSample(batch, &mMsg)) {
+ batch.samples.push(mMsg);
#if DEBUG_TRANSPORT_ACTIONS
ALOGD("channel '%s' consumer ~ appended to batch event",
mChannel->getName().string());
#endif
break;
} else {
- MotionEvent* motionEvent = factory->createMotionEvent();
- if (! motionEvent) return NO_MEMORY;
-
// We cannot append to the batch in progress, so we need to consume
// the previous batch right now and defer the new message until later.
mMsgDeferred = true;
-
- // Return the end of the previous batch.
- motionEvent->copyFrom(&batch.event, true /*keepHistory*/);
- *outSeq = batch.seq;
- *outEvent = motionEvent;
+ status_t result = consumeSamples(factory,
+ batch, batch.samples.size(), outSeq, outEvent);
mBatches.removeAt(batchIndex);
+ if (result) {
+ return result;
+ }
#if DEBUG_TRANSPORT_ACTIONS
ALOGD("channel '%s' consumer ~ consumed batch event and "
"deferred current event, seq=%u",
@@ -443,8 +444,7 @@
|| mMsg.body.motion.action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
mBatches.push();
Batch& batch = mBatches.editTop();
- batch.seq = mMsg.body.motion.seq;
- initializeMotionEvent(&batch.event, &mMsg);
+ batch.samples.push(mMsg);
#if DEBUG_TRANSPORT_ACTIONS
ALOGD("channel '%s' consumer ~ started batch event",
mChannel->getName().string());
@@ -455,6 +455,7 @@
MotionEvent* motionEvent = factory->createMotionEvent();
if (! motionEvent) return NO_MEMORY;
+ updateTouchState(&mMsg);
initializeMotionEvent(motionEvent, &mMsg);
*outSeq = mMsg.body.motion.seq;
*outEvent = motionEvent;
@@ -474,6 +475,213 @@
return OK;
}
+status_t InputConsumer::consumeBatch(InputEventFactoryInterface* factory,
+ nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
+ status_t result;
+ for (size_t i = mBatches.size(); i-- > 0; ) {
+ Batch& batch = mBatches.editItemAt(i);
+ if (frameTime < 0) {
+ result = consumeSamples(factory, batch, batch.samples.size(),
+ outSeq, outEvent);
+ mBatches.removeAt(i);
+ return result;
+ }
+
+ nsecs_t sampleTime = frameTime - RESAMPLE_LATENCY;
+ ssize_t split = findSampleNoLaterThan(batch, sampleTime);
+ if (split < 0) {
+ continue;
+ }
+
+ result = consumeSamples(factory, batch, split + 1, outSeq, outEvent);
+ const InputMessage* next;
+ if (batch.samples.isEmpty()) {
+ mBatches.removeAt(i);
+ next = NULL;
+ } else {
+ next = &batch.samples.itemAt(0);
+ }
+ if (!result) {
+ resampleTouchState(sampleTime, static_cast<MotionEvent*>(*outEvent), next);
+ }
+ return result;
+ }
+
+ return WOULD_BLOCK;
+}
+
+status_t InputConsumer::consumeSamples(InputEventFactoryInterface* factory,
+ Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent) {
+ MotionEvent* motionEvent = factory->createMotionEvent();
+ if (! motionEvent) return NO_MEMORY;
+
+ uint32_t chain = 0;
+ for (size_t i = 0; i < count; i++) {
+ InputMessage& msg = batch.samples.editItemAt(i);
+ updateTouchState(&msg);
+ if (i) {
+ SeqChain seqChain;
+ seqChain.seq = msg.body.motion.seq;
+ seqChain.chain = chain;
+ mSeqChains.push(seqChain);
+ addSample(motionEvent, &msg);
+ } else {
+ initializeMotionEvent(motionEvent, &msg);
+ }
+ chain = msg.body.motion.seq;
+ }
+ batch.samples.removeItemsAt(0, count);
+
+ *outSeq = chain;
+ *outEvent = motionEvent;
+ return OK;
+}
+
+void InputConsumer::updateTouchState(InputMessage* msg) {
+ if (!(msg->body.motion.source & AINPUT_SOURCE_CLASS_POINTER)) {
+ return;
+ }
+
+ int32_t deviceId = msg->body.motion.deviceId;
+ int32_t source = msg->body.motion.source;
+
+ // TODO: Filter the incoming touch event so that it aligns better
+ // with prior predictions. Turning RESAMPLE_LATENCY offsets the need
+ // for filtering but it would be nice to reduce the latency further.
+
+ switch (msg->body.motion.action) {
+ case AMOTION_EVENT_ACTION_DOWN: {
+ ssize_t index = findTouchState(deviceId, source);
+ if (index < 0) {
+ mTouchStates.push();
+ index = mTouchStates.size() - 1;
+ }
+ TouchState& touchState = mTouchStates.editItemAt(index);
+ touchState.initialize(deviceId, source);
+ touchState.addHistory(msg);
+ break;
+ }
+
+ case AMOTION_EVENT_ACTION_MOVE: {
+ ssize_t index = findTouchState(deviceId, source);
+ if (index >= 0) {
+ TouchState& touchState = mTouchStates.editItemAt(index);
+ touchState.addHistory(msg);
+ }
+ break;
+ }
+
+ case AMOTION_EVENT_ACTION_UP:
+ case AMOTION_EVENT_ACTION_CANCEL: {
+ ssize_t index = findTouchState(deviceId, source);
+ if (index >= 0) {
+ mTouchStates.removeAt(index);
+ }
+ break;
+ }
+ }
+}
+
+void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
+ const InputMessage* next) {
+ if (event->getAction() != AMOTION_EVENT_ACTION_MOVE
+ || !(event->getSource() & AINPUT_SOURCE_CLASS_POINTER)) {
+#if DEBUG_RESAMPLING
+ ALOGD("Not resampled, not a move.");
+#endif
+ return;
+ }
+
+ ssize_t index = findTouchState(event->getDeviceId(), event->getSource());
+ if (index < 0) {
+#if DEBUG_RESAMPLING
+ ALOGD("Not resampled, no touch state for device.");
+#endif
+ return;
+ }
+
+ TouchState& touchState = mTouchStates.editItemAt(index);
+ if (touchState.historySize < 1) {
+#if DEBUG_RESAMPLING
+ ALOGD("Not resampled, no history for device.");
+#endif
+ return;
+ }
+
+ const History* current = touchState.getHistory(0);
+ const History* other;
+ History future;
+ if (next) {
+ future.initializeFrom(next);
+ other = &future;
+ } else if (touchState.historySize >= 2) {
+ other = touchState.getHistory(1);
+ } else {
+#if DEBUG_RESAMPLING
+ ALOGD("Not resampled, insufficient data.");
+#endif
+ return;
+ }
+
+ nsecs_t delta = current->eventTime - other->eventTime;
+ if (delta > -RESAMPLE_MIN_DELTA && delta < RESAMPLE_MIN_DELTA) {
+#if DEBUG_RESAMPLING
+ ALOGD("Not resampled, delta time is %lld", delta);
+#endif
+ return;
+ }
+
+ float alpha = float(current->eventTime - sampleTime) / delta;
+ if (fabs(alpha) > RESAMPLE_MAX_ALPHA) {
+#if DEBUG_RESAMPLING
+ ALOGD("Not resampled, alpha is %f", alpha);
+#endif
+ return;
+ }
+
+ size_t pointerCount = event->getPointerCount();
+ PointerCoords resampledCoords[MAX_POINTERS];
+ for (size_t i = 0; i < pointerCount; i++) {
+ uint32_t id = event->getPointerId(i);
+ if (!current->idBits.hasBit(id)) {
+#if DEBUG_RESAMPLING
+ ALOGD("Not resampled, missing id %d", id);
+#endif
+ return;
+ }
+ const PointerCoords& currentCoords =
+ current->pointers[current->idBits.getIndexOfBit(id)];
+ if (other->idBits.hasBit(id)
+ && shouldResampleTool(event->getToolType(i))) {
+ const PointerCoords& otherCoords =
+ other->pointers[other->idBits.getIndexOfBit(id)];
+ resampledCoords[i].lerp(currentCoords, otherCoords, alpha);
+#if DEBUG_RESAMPLING
+ ALOGD("[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f), "
+ "other (%0.3f, %0.3f), alpha %0.3f",
+ i, resampledCoords[i].getX(), resampledCoords[i].getY(),
+ currentCoords.getX(), currentCoords.getY(),
+ otherCoords.getX(), otherCoords.getY(),
+ alpha);
+#endif
+ } else {
+ resampledCoords[i].copyFrom(currentCoords);
+#if DEBUG_RESAMPLING
+ ALOGD("[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f)",
+ i, resampledCoords[i].getX(), resampledCoords[i].getY(),
+ currentCoords.getX(), currentCoords.getY());
+#endif
+ }
+ }
+
+ event->addSample(sampleTime, resampledCoords);
+}
+
+bool InputConsumer::shouldResampleTool(int32_t toolType) {
+ return toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
+ || toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
+}
+
status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {
#if DEBUG_TRANSPORT_ACTIONS
ALOGD("channel '%s' consumer ~ sendFinishedSignal: seq=%u, handled=%s",
@@ -538,7 +746,18 @@
ssize_t InputConsumer::findBatch(int32_t deviceId, int32_t source) const {
for (size_t i = 0; i < mBatches.size(); i++) {
const Batch& batch = mBatches.itemAt(i);
- if (batch.event.getDeviceId() == deviceId && batch.event.getSource() == source) {
+ const InputMessage& head = batch.samples.itemAt(0);
+ if (head.body.motion.deviceId == deviceId && head.body.motion.source == source) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+ssize_t InputConsumer::findTouchState(int32_t deviceId, int32_t source) const {
+ for (size_t i = 0; i < mTouchStates.size(); i++) {
+ const TouchState& touchState = mTouchStates.itemAt(i);
+ if (touchState.deviceId == deviceId && touchState.source == source) {
return i;
}
}
@@ -587,21 +806,7 @@
pointerCoords);
}
-bool InputConsumer::canAppendSamples(const MotionEvent* event, const InputMessage *msg) {
- size_t pointerCount = msg->body.motion.pointerCount;
- if (event->getPointerCount() != pointerCount
- || event->getAction() != msg->body.motion.action) {
- return false;
- }
- for (size_t i = 0; i < pointerCount; i++) {
- if (*event->getPointerProperties(i) != msg->body.motion.pointers[i].properties) {
- return false;
- }
- }
- return true;
-}
-
-void InputConsumer::appendSamples(MotionEvent* event, const InputMessage* msg) {
+void InputConsumer::addSample(MotionEvent* event, const InputMessage* msg) {
size_t pointerCount = msg->body.motion.pointerCount;
PointerCoords pointerCoords[pointerCount];
for (size_t i = 0; i < pointerCount; i++) {
@@ -612,4 +817,30 @@
event->addSample(msg->body.motion.eventTime, pointerCoords);
}
+bool InputConsumer::canAddSample(const Batch& batch, const InputMessage *msg) {
+ const InputMessage& head = batch.samples.itemAt(0);
+ size_t pointerCount = msg->body.motion.pointerCount;
+ if (head.body.motion.pointerCount != pointerCount
+ || head.body.motion.action != msg->body.motion.action) {
+ return false;
+ }
+ for (size_t i = 0; i < pointerCount; i++) {
+ if (head.body.motion.pointers[i].properties
+ != msg->body.motion.pointers[i].properties) {
+ return false;
+ }
+ }
+ return true;
+}
+
+ssize_t InputConsumer::findSampleNoLaterThan(const Batch& batch, nsecs_t time) {
+ size_t numSamples = batch.samples.size();
+ size_t index = 0;
+ while (index < numSamples
+ && batch.samples.itemAt(index).body.motion.eventTime <= time) {
+ index += 1;
+ }
+ return ssize_t(index) - 1;
+}
+
} // namespace android
diff --git a/libs/androidfw/tests/InputPublisherAndConsumer_test.cpp b/libs/androidfw/tests/InputPublisherAndConsumer_test.cpp
index 442b62f..f45774b 100644
--- a/libs/androidfw/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/androidfw/tests/InputPublisherAndConsumer_test.cpp
@@ -88,7 +88,7 @@
uint32_t consumeSeq;
InputEvent* event;
- status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, &consumeSeq, &event);
+ status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event);
ASSERT_EQ(OK, status)
<< "consumer consume should return OK";
@@ -171,7 +171,7 @@
uint32_t consumeSeq;
InputEvent* event;
- status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, &consumeSeq, &event);
+ status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event);
ASSERT_EQ(OK, status)
<< "consumer consume should return OK";
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index e363b73..71a4ed7 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -25,10 +25,15 @@
namespace uirenderer {
// Defined in ShapeCache.h
-void computePathBounds(const SkPath *path, const SkPaint* paint,
+
+void computePathBounds(const SkPath* path, const SkPaint* paint,
float& left, float& top, float& offset, uint32_t& width, uint32_t& height) {
const SkRect& bounds = path->getBounds();
+ computeBounds(bounds, paint, left, top, offset, width, height);
+}
+void computeBounds(const SkRect& bounds, const SkPaint* paint,
+ float& left, float& top, float& offset, uint32_t& width, uint32_t& height) {
const float pathWidth = fmax(bounds.width(), 1.0f);
const float pathHeight = fmax(bounds.height(), 1.0f);
diff --git a/libs/hwui/ShapeCache.cpp b/libs/hwui/ShapeCache.cpp
index 0d7cd9c..5a23235 100644
--- a/libs/hwui/ShapeCache.cpp
+++ b/libs/hwui/ShapeCache.cpp
@@ -105,10 +105,29 @@
PathTexture* texture = get(entry);
if (!texture) {
- SkPath path;
- path.addRect(0.0f, 0.0f, width, height, SkPath::kCW_Direction);
+ SkRect bounds;
+ bounds.set(0.0f, 0.0f, width, height);
- texture = addTexture(entry, &path, paint);
+ float left, top, offset;
+ uint32_t rectWidth, rectHeight;
+ computeBounds(bounds, paint, left, top, offset, rectWidth, rectHeight);
+
+ if (!checkTextureSize(rectWidth, rectHeight)) return NULL;
+
+ purgeCache(rectWidth, rectHeight);
+
+ SkBitmap bitmap;
+ initBitmap(bitmap, rectWidth, rectHeight);
+
+ SkPaint pathPaint(*paint);
+ initPaint(pathPaint);
+
+ SkCanvas canvas(bitmap);
+ canvas.translate(-left + offset, -top + offset);
+ canvas.drawRect(bounds, pathPaint);
+
+ texture = createTexture(0, 0, offset, rectWidth, rectHeight, 0);
+ addTexture(entry, &bitmap, texture);
}
return texture;
diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h
index f180e94..3a95b99 100644
--- a/libs/hwui/ShapeCache.h
+++ b/libs/hwui/ShapeCache.h
@@ -336,6 +336,19 @@
protected:
PathTexture* addTexture(const Entry& entry, const SkPath *path, const SkPaint* paint);
+ PathTexture* addTexture(const Entry& entry, SkBitmap* bitmap);
+ void addTexture(const Entry& entry, SkBitmap* bitmap, PathTexture* texture);
+
+ /**
+ * Ensures there is enough space in the cache for a texture of the specified
+ * dimensions.
+ */
+ void purgeCache(uint32_t width, uint32_t height);
+
+ void initBitmap(SkBitmap& bitmap, uint32_t width, uint32_t height);
+ void initPaint(SkPaint& paint);
+
+ bool checkTextureSize(uint32_t width, uint32_t height);
PathTexture* get(Entry entry) {
return mCache.get(entry);
@@ -489,8 +502,63 @@
}
}
-void computePathBounds(const SkPath *path, const SkPaint* paint,
+void computePathBounds(const SkPath* path, const SkPaint* paint,
float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
+void computeBounds(const SkRect& bounds, const SkPaint* paint,
+ float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
+
+static PathTexture* createTexture(float left, float top, float offset,
+ uint32_t width, uint32_t height, uint32_t id) {
+ PathTexture* texture = new PathTexture;
+ texture->left = left;
+ texture->top = top;
+ texture->offset = offset;
+ texture->width = width;
+ texture->height = height;
+ texture->generation = id;
+ return texture;
+}
+
+template<class Entry>
+void ShapeCache<Entry>::purgeCache(uint32_t width, uint32_t height) {
+ const uint32_t size = width * height;
+ // Don't even try to cache a bitmap that's bigger than the cache
+ if (size < mMaxSize) {
+ while (mSize + size > mMaxSize) {
+ mCache.removeOldest();
+ }
+ }
+}
+
+template<class Entry>
+void ShapeCache<Entry>::initBitmap(SkBitmap& bitmap, uint32_t width, uint32_t height) {
+ bitmap.setConfig(SkBitmap::kA8_Config, width, height);
+ bitmap.allocPixels();
+ bitmap.eraseColor(0);
+}
+
+template<class Entry>
+void ShapeCache<Entry>::initPaint(SkPaint& paint) {
+ // Make sure the paint is opaque, color, alpha, filter, etc.
+ // will be applied later when compositing the alpha8 texture
+ paint.setColor(0xff000000);
+ paint.setAlpha(255);
+ paint.setColorFilter(NULL);
+ paint.setMaskFilter(NULL);
+ paint.setShader(NULL);
+ SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrc_Mode);
+ SkSafeUnref(paint.setXfermode(mode));
+}
+
+template<class Entry>
+bool ShapeCache<Entry>::checkTextureSize(uint32_t width, uint32_t height) {
+ if (width > mMaxTextureSize || height > mMaxTextureSize) {
+ ALOGW("Shape %s too large to be rendered into a texture (%dx%d, max=%dx%d)",
+ mName, width, height, mMaxTextureSize, mMaxTextureSize);
+ return false;
+ }
+ return true;
+}
template<class Entry>
PathTexture* ShapeCache<Entry>::addTexture(const Entry& entry, const SkPath *path,
@@ -500,51 +568,31 @@
uint32_t width, height;
computePathBounds(path, paint, left, top, offset, width, height);
- if (width > mMaxTextureSize || height > mMaxTextureSize) {
- ALOGW("Shape %s too large to be rendered into a texture (%dx%d, max=%dx%d)",
- mName, width, height, mMaxTextureSize, mMaxTextureSize);
- return NULL;
- }
+ if (!checkTextureSize(width, height)) return NULL;
- const uint32_t size = width * height;
- // Don't even try to cache a bitmap that's bigger than the cache
- if (size < mMaxSize) {
- while (mSize + size > mMaxSize) {
- mCache.removeOldest();
- }
- }
-
- PathTexture* texture = new PathTexture;
- texture->left = left;
- texture->top = top;
- texture->offset = offset;
- texture->width = width;
- texture->height = height;
- texture->generation = path->getGenerationID();
+ purgeCache(width, height);
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kA8_Config, width, height);
- bitmap.allocPixels();
- bitmap.eraseColor(0);
+ initBitmap(bitmap, width, height);
SkPaint pathPaint(*paint);
-
- // Make sure the paint is opaque, color, alpha, filter, etc.
- // will be applied later when compositing the alpha8 texture
- pathPaint.setColor(0xff000000);
- pathPaint.setAlpha(255);
- pathPaint.setColorFilter(NULL);
- pathPaint.setMaskFilter(NULL);
- pathPaint.setShader(NULL);
- SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrc_Mode);
- SkSafeUnref(pathPaint.setXfermode(mode));
+ initPaint(pathPaint);
SkCanvas canvas(bitmap);
canvas.translate(-left + offset, -top + offset);
canvas.drawPath(*path, pathPaint);
- generateTexture(bitmap, texture);
+ PathTexture* texture = createTexture(left, top, offset, width, height, path->getGenerationID());
+ addTexture(entry, &bitmap, texture);
+ return texture;
+}
+
+template<class Entry>
+void ShapeCache<Entry>::addTexture(const Entry& entry, SkBitmap* bitmap, PathTexture* texture) {
+ generateTexture(*bitmap, texture);
+
+ uint32_t size = texture->width * texture->height;
if (size < mMaxSize) {
mSize += size;
SHAPE_LOGD("ShapeCache::get: create %s: name, size, mSize = %d, %d, %d",
@@ -556,8 +604,6 @@
} else {
texture->cleanup = true;
}
-
- return texture;
}
template<class Entry>
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 2a006c6..f603525 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2306,4 +2306,12 @@
}
}
+ /** {@hide} */
+ public IRingtonePlayer getRingtonePlayer() {
+ try {
+ return getService().getRingtonePlayer();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
}
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 3e958dc..dc9496f 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -16,6 +16,7 @@
package android.media;
+import static android.Manifest.permission.REMOTE_AUDIO_PLAYBACK;
import static android.media.AudioManager.RINGER_MODE_NORMAL;
import static android.media.AudioManager.RINGER_MODE_SILENT;
import static android.media.AudioManager.RINGER_MODE_VIBRATE;
@@ -360,7 +361,6 @@
private int mPrevVolDirection = AudioManager.ADJUST_SAME;
// Keyguard manager proxy
private KeyguardManager mKeyguardManager;
-
// mVolumeControlStream is set by VolumePanel to temporarily force the stream type which volume
// is controlled by Vol keys.
private int mVolumeControlStream = -1;
@@ -369,6 +369,8 @@
// server process so in theory it is not necessary to monitor the client death.
// However it is good to be ready for future evolutions.
private ForceControlStreamClient mForceControlStreamClient = null;
+ // Used to play ringtones outside system_server
+ private volatile IRingtonePlayer mRingtonePlayer;
///////////////////////////////////////////////////////////////////////////
// Construction
@@ -4231,6 +4233,17 @@
}
@Override
+ public void setRingtonePlayer(IRingtonePlayer player) {
+ mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null);
+ mRingtonePlayer = player;
+ }
+
+ @Override
+ public IRingtonePlayer getRingtonePlayer() {
+ return mRingtonePlayer;
+ }
+
+ @Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
@@ -4238,6 +4251,4 @@
dumpFocusStack(pw);
dumpRCStack(pw);
}
-
-
}
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index df210406..1a2714e 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -21,6 +21,8 @@
import android.media.IAudioFocusDispatcher;
import android.media.IRemoteControlClient;
import android.media.IRemoteControlDisplay;
+import android.media.IRingtonePlayer;
+import android.net.Uri;
/**
* {@hide}
@@ -113,10 +115,11 @@
oneway void remoteControlDisplayUsesBitmapSize(in IRemoteControlDisplay rcd, int w, int h);
void startBluetoothSco(IBinder cb);
-
void stopBluetoothSco(IBinder cb);
void forceVolumeControlStream(int streamType, IBinder cb);
+ void setRingtonePlayer(IRingtonePlayer player);
+ IRingtonePlayer getRingtonePlayer();
int getMasterStreamType();
}
diff --git a/media/java/android/media/IRingtonePlayer.aidl b/media/java/android/media/IRingtonePlayer.aidl
new file mode 100644
index 0000000..44a0333
--- /dev/null
+++ b/media/java/android/media/IRingtonePlayer.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.net.Uri;
+
+/**
+ * @hide
+ */
+interface IRingtonePlayer {
+ /** Used for Ringtone.java playback */
+ void play(IBinder token, in Uri uri, int streamType);
+ void stop(IBinder token);
+ boolean isPlaying(IBinder token);
+
+ /** Used for Notification sound playback. */
+ void playAsync(in Uri uri, boolean looping, int streamType);
+ void stopAsync();
+}
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index f16ba36..57139d2 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -18,17 +18,15 @@
import android.content.ContentResolver;
import android.content.Context;
-import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
-import android.media.AudioManager;
-import android.media.MediaPlayer;
import android.net.Uri;
+import android.os.Binder;
+import android.os.RemoteException;
import android.provider.DrmStore;
import android.provider.MediaStore;
import android.provider.Settings;
import android.util.Log;
-import java.io.FileDescriptor;
import java.io.IOException;
/**
@@ -41,7 +39,8 @@
* @see RingtoneManager
*/
public class Ringtone {
- private static String TAG = "Ringtone";
+ private static final String TAG = "Ringtone";
+ private static final boolean LOGD = true;
private static final String[] MEDIA_COLUMNS = new String[] {
MediaStore.Audio.Media._ID,
@@ -55,21 +54,26 @@
DrmStore.Audio.TITLE
};
- private MediaPlayer mAudio;
+ private final Context mContext;
+ private final AudioManager mAudioManager;
+ private final boolean mAllowRemote;
+ private final IRingtonePlayer mRemotePlayer;
+ private final Binder mRemoteToken;
+
+ private MediaPlayer mLocalPlayer;
private Uri mUri;
private String mTitle;
- private FileDescriptor mFileDescriptor;
- private AssetFileDescriptor mAssetFileDescriptor;
private int mStreamType = AudioManager.STREAM_RING;
- private AudioManager mAudioManager;
- private Context mContext;
-
- Ringtone(Context context) {
+ /** {@hide} */
+ public Ringtone(Context context, boolean allowRemote) {
mContext = context;
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ mAllowRemote = allowRemote;
+ mRemotePlayer = allowRemote ? mAudioManager.getRingtonePlayer() : null;
+ mRemoteToken = allowRemote ? new Binder() : null;
}
/**
@@ -79,18 +83,10 @@
*/
public void setStreamType(int streamType) {
mStreamType = streamType;
-
- if (mAudio != null) {
- /*
- * The stream type has to be set before the media player is
- * prepared. Re-initialize it.
- */
- try {
- openMediaPlayer();
- } catch (IOException e) {
- Log.w(TAG, "Couldn't set the stream type", e);
- }
- }
+
+ // The stream type has to be set before the media player is prepared.
+ // Re-initialize it.
+ setUri(mUri);
}
/**
@@ -164,67 +160,75 @@
return title;
}
-
- private void openMediaPlayer() throws IOException {
- if (mAudio != null) {
- mAudio.release();
- }
- mAudio = new MediaPlayer();
- if (mUri != null) {
- mAudio.setDataSource(mContext, mUri);
- } else if (mFileDescriptor != null) {
- mAudio.setDataSource(mFileDescriptor);
- } else if (mAssetFileDescriptor != null) {
- // Note: using getDeclaredLength so that our behavior is the same
- // as previous versions when the content provider is returning
- // a full file.
- if (mAssetFileDescriptor.getDeclaredLength() < 0) {
- mAudio.setDataSource(mAssetFileDescriptor.getFileDescriptor());
- } else {
- mAudio.setDataSource(mAssetFileDescriptor.getFileDescriptor(),
- mAssetFileDescriptor.getStartOffset(),
- mAssetFileDescriptor.getDeclaredLength());
- }
- } else {
- throw new IOException("No data source set.");
- }
- mAudio.setAudioStreamType(mStreamType);
- mAudio.prepare();
- }
- void open(FileDescriptor fd) throws IOException {
- mFileDescriptor = fd;
- openMediaPlayer();
- }
+ /**
+ * Set {@link Uri} to be used for ringtone playback. Attempts to open
+ * locally, otherwise will delegate playback to remote
+ * {@link IRingtonePlayer}.
+ *
+ * @hide
+ */
+ public void setUri(Uri uri) {
+ destroyLocalPlayer();
- void open(AssetFileDescriptor fd) throws IOException {
- mAssetFileDescriptor = fd;
- openMediaPlayer();
- }
-
- void open(Uri uri) throws IOException {
mUri = uri;
- openMediaPlayer();
+ if (mUri == null) {
+ return;
+ }
+
+ // TODO: detect READ_EXTERNAL and specific content provider case, instead of relying on throwing
+
+ // try opening uri locally before delegating to remote player
+ mLocalPlayer = new MediaPlayer();
+ try {
+ mLocalPlayer.setDataSource(mContext, mUri);
+ mLocalPlayer.setAudioStreamType(mStreamType);
+ mLocalPlayer.prepare();
+
+ } catch (SecurityException e) {
+ destroyLocalPlayer();
+ if (!mAllowRemote) {
+ throw new IllegalStateException("Remote playback not allowed", e);
+ }
+ } catch (IOException e) {
+ destroyLocalPlayer();
+ if (!mAllowRemote) {
+ throw new IllegalStateException("Remote playback not allowed", e);
+ }
+ }
+
+ if (LOGD) {
+ if (mLocalPlayer != null) {
+ Log.d(TAG, "Successfully created local player");
+ } else {
+ Log.d(TAG, "Problem opening; delegating to remote player");
+ }
+ }
+ }
+
+ /** {@hide} */
+ public Uri getUri() {
+ return mUri;
}
/**
* Plays the ringtone.
*/
public void play() {
- if (mAudio == null) {
- try {
- openMediaPlayer();
- } catch (Exception ex) {
- Log.e(TAG, "play() caught ", ex);
- mAudio = null;
- }
- }
- if (mAudio != null) {
- // do not ringtones if stream volume is 0
+ if (mLocalPlayer != null) {
+ // do not play ringtones if stream volume is 0
// (typically because ringer mode is silent).
if (mAudioManager.getStreamVolume(mStreamType) != 0) {
- mAudio.start();
+ mLocalPlayer.start();
}
+ } else if (mAllowRemote) {
+ try {
+ mRemotePlayer.play(mRemoteToken, mUri, mStreamType);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Problem playing ringtone: " + e);
+ }
+ } else {
+ throw new IllegalStateException("Neither local nor remote playback available");
}
}
@@ -232,10 +236,22 @@
* Stops a playing ringtone.
*/
public void stop() {
- if (mAudio != null) {
- mAudio.reset();
- mAudio.release();
- mAudio = null;
+ if (mLocalPlayer != null) {
+ destroyLocalPlayer();
+ } else if (mAllowRemote) {
+ try {
+ mRemotePlayer.stop(mRemoteToken);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Problem stopping ringtone: " + e);
+ }
+ }
+ }
+
+ private void destroyLocalPlayer() {
+ if (mLocalPlayer != null) {
+ mLocalPlayer.reset();
+ mLocalPlayer.release();
+ mLocalPlayer = null;
}
}
@@ -245,7 +261,18 @@
* @return True if playing, false otherwise.
*/
public boolean isPlaying() {
- return mAudio != null && mAudio.isPlaying();
+ if (mLocalPlayer != null) {
+ return mLocalPlayer.isPlaying();
+ } else if (mAllowRemote) {
+ try {
+ return mRemotePlayer.isPlaying(mRemoteToken);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Problem checking ringtone: " + e);
+ return false;
+ }
+ } else {
+ throw new IllegalStateException("Neither local nor remote playback available");
+ }
}
void setTitle(String title) {
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index a5b1f45..5e18bfa 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -606,16 +606,15 @@
* @see #getRingtone(Context, Uri)
*/
private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType) {
-
try {
- Ringtone r = new Ringtone(context);
+ final Ringtone r = new Ringtone(context, true);
if (streamType >= 0) {
r.setStreamType(streamType);
}
- r.open(ringtoneUri);
+ r.setUri(ringtoneUri);
return r;
} catch (Exception ex) {
- Log.e(TAG, "Failed to open ringtone " + ringtoneUri);
+ Log.e(TAG, "Failed to open ringtone " + ringtoneUri + ": " + ex);
}
return null;
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 2444829..50aaa9a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -681,10 +681,15 @@
}
private int enableWifi(boolean enable) {
+ if (mWfm == null) {
+ mWfm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+ }
if (mWfm != null) {
int state = mWfm.getWifiState();
mWfm.setWifiEnabled(enable);
return state;
+ } else {
+ Log.e(TAG, "Failed to fetch WifiManager instance");
}
return WifiManager.WIFI_STATE_UNKNOWN;
}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index a31c264..cef21b0 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INJECT_EVENTS" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
@@ -12,6 +13,7 @@
<uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
<uses-permission android:name="android.permission.STATUS_BAR" />
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
+ <uses-permission android:name="android.permission.REMOTE_AUDIO_PLAYBACK" />
<!-- Networking and telephony -->
<uses-permission android:name="android.permission.BLUETOOTH" />
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index f5ac4d4..6ad380a 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -139,5 +139,5 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"ตำแหน่งที่กำหนดโดย GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"ล้างการแจ้งเตือนทั้งหมด"</string>
<string name="dreams_dock_launcher" msgid="3541196417659166245">"เปิดโปรแกรมรักษาหน้าจอ"</string>
- <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"ข้อมูลแอปพลิเคชัน"</string>
+ <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"ข้อมูลแอป"</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index ae568f8..0a57499 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -41,6 +41,7 @@
final Object[] SERVICES = new Object[] {
0, // system bar or status bar, filled in below.
com.android.systemui.power.PowerUI.class,
+ com.android.systemui.media.RingtonePlayer.class,
};
/**
diff --git a/services/java/com/android/server/NotificationPlayer.java b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
similarity index 98%
rename from services/java/com/android/server/NotificationPlayer.java
rename to packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
index 52d2381..6a12eb1 100644
--- a/services/java/com/android/server/NotificationPlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.systemui.media;
import android.content.Context;
import android.media.AudioManager;
@@ -36,7 +36,7 @@
/**
* @hide
* This class is provides the same interface and functionality as android.media.AsyncPlayer
- * with the following differences:
+ * with the following differences:
* - whenever audio is played, audio focus is requested,
* - whenever audio playback is stopped or the playback completed, audio focus is abandoned.
*/
@@ -338,4 +338,3 @@
}
}
}
-
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
new file mode 100644
index 0000000..9e273d4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media;
+
+import android.content.Context;
+import android.media.IAudioService;
+import android.media.IRingtonePlayer;
+import android.media.Ringtone;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Slog;
+
+import com.android.systemui.SystemUI;
+import com.google.android.collect.Maps;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.HashMap;
+
+/**
+ * Service that offers to play ringtones by {@link Uri}, since our process has
+ * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}.
+ */
+public class RingtonePlayer extends SystemUI {
+ private static final String TAG = "RingtonePlayer";
+ private static final boolean LOGD = true;
+
+ // TODO: support Uri switching under same IBinder
+
+ private IAudioService mAudioService;
+
+ private final NotificationPlayer mAsyncPlayer = new NotificationPlayer(TAG);
+ private final HashMap<IBinder, Client> mClients = Maps.newHashMap();
+
+ @Override
+ public void start() {
+ mAsyncPlayer.setUsesWakeLock(mContext);
+
+ mAudioService = IAudioService.Stub.asInterface(
+ ServiceManager.getService(Context.AUDIO_SERVICE));
+ try {
+ mAudioService.setRingtonePlayer(mCallback);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Problem registering RingtonePlayer: " + e);
+ }
+ }
+
+ /**
+ * Represents an active remote {@link Ringtone} client.
+ */
+ private class Client implements IBinder.DeathRecipient {
+ private final IBinder mToken;
+ private final Ringtone mRingtone;
+
+ public Client(IBinder token, Uri uri, int streamType) {
+ mToken = token;
+ mRingtone = new Ringtone(mContext, false);
+ mRingtone.setStreamType(streamType);
+ mRingtone.setUri(uri);
+ }
+
+ @Override
+ public void binderDied() {
+ if (LOGD) Slog.d(TAG, "binderDied() token=" + mToken);
+ synchronized (mClients) {
+ mClients.remove(mToken);
+ }
+ mRingtone.stop();
+ }
+ }
+
+ private IRingtonePlayer mCallback = new IRingtonePlayer.Stub() {
+ @Override
+ public void play(IBinder token, Uri uri, int streamType) throws RemoteException {
+ if (LOGD) Slog.d(TAG, "play(token=" + token + ", uri=" + uri + ")");
+ Client client;
+ synchronized (mClients) {
+ client = mClients.get(token);
+ if (client == null) {
+ client = new Client(token, uri, streamType);
+ token.linkToDeath(client, 0);
+ mClients.put(token, client);
+ }
+ }
+ client.mRingtone.play();
+ }
+
+ @Override
+ public void stop(IBinder token) {
+ if (LOGD) Slog.d(TAG, "stop(token=" + token + ")");
+ Client client;
+ synchronized (mClients) {
+ client = mClients.remove(token);
+ }
+ if (client != null) {
+ client.mToken.unlinkToDeath(client, 0);
+ client.mRingtone.stop();
+ }
+ }
+
+ @Override
+ public boolean isPlaying(IBinder token) {
+ if (LOGD) Slog.d(TAG, "isPlaying(token=" + token + ")");
+ Client client;
+ synchronized (mClients) {
+ client = mClients.get(token);
+ }
+ if (client != null) {
+ return client.mRingtone.isPlaying();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void playAsync(Uri uri, boolean looping, int streamType) {
+ if (LOGD) Slog.d(TAG, "playAsync(uri=" + uri + ")");
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ throw new SecurityException("Async playback only available from system UID.");
+ }
+ mAsyncPlayer.play(mContext, uri, looping, streamType);
+ }
+
+ @Override
+ public void stopAsync() {
+ if (LOGD) Slog.d(TAG, "stopAsync()");
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ throw new SecurityException("Async playback only available from system UID.");
+ }
+ mAsyncPlayer.stop();
+ }
+ };
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("Clients:");
+ synchronized (mClients) {
+ for (Client client : mClients.values()) {
+ pw.print(" mToken=");
+ pw.print(client.mToken);
+ pw.print(" mUri=");
+ pw.println(client.mRingtone.getUri());
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 424317a..4bb2d1d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -36,6 +36,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.Surface;
+import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManagerImpl;
import android.widget.ImageView;
@@ -73,7 +74,7 @@
int mNavigationIconHints = 0;
private Drawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon;
-
+
private DelegateViewHelper mDelegateHelper;
// workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288)
@@ -311,7 +312,6 @@
}
mCurrentView = mRotatedViews[rot];
mCurrentView.setVisibility(View.VISIBLE);
- mVertical = (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270);
// force the low profile & disabled states into compliance
setLowProfile(mLowProfile, false, true /* force */);
@@ -333,6 +333,14 @@
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (DEBUG) Slog.d(TAG, String.format(
"onSizeChanged: (%dx%d) old: (%dx%d)", w, h, oldw, oldh));
+
+ final boolean newVertical = w > 0 && h > w;
+ if (newVertical != mVertical) {
+ mVertical = newVertical;
+ //Slog.v(TAG, String.format("onSizeChanged: h=%d, w=%d, vert=%s", h, w, mVertical?"y":"n"));
+ reorient();
+ }
+
postCheckForInvalidLayout("sizeChanged");
super.onSizeChanged(w, h, oldw, oldh);
}
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 1ba7e79..663a031 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -16,16 +16,15 @@
package com.android.server;
-import com.android.internal.os.AtomicFile;
-import com.android.internal.statusbar.StatusBarNotification;
-import com.android.internal.util.FastXmlSerializer;
+import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
+import static org.xmlpull.v1.XmlPullParser.END_TAG;
+import static org.xmlpull.v1.XmlPullParser.START_TAG;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.app.INotificationManager;
import android.app.ITransientNotification;
import android.app.Notification;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
@@ -39,8 +38,8 @@
import android.content.res.Resources;
import android.database.ContentObserver;
import android.media.AudioManager;
-import android.net.NetworkPolicy;
-import android.net.NetworkTemplate;
+import android.media.IAudioService;
+import android.media.IRingtonePlayer;
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
@@ -48,6 +47,7 @@
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.UserId;
import android.os.Vibrator;
import android.provider.Settings;
@@ -61,6 +61,14 @@
import android.view.accessibility.AccessibilityManager;
import android.widget.Toast;
+import com.android.internal.os.AtomicFile;
+import com.android.internal.statusbar.StatusBarNotification;
+import com.android.internal.util.FastXmlSerializer;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -74,18 +82,6 @@
import libcore.io.IoUtils;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-import static android.net.NetworkPolicyManager.POLICY_NONE;
-import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeBooleanAttribute;
-import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeIntAttribute;
-import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeLongAttribute;
-import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
-import static org.xmlpull.v1.XmlPullParser.END_TAG;
-import static org.xmlpull.v1.XmlPullParser.START_TAG;
-
/** {@hide} */
public class NotificationManagerService extends INotificationManager.Stub
@@ -126,12 +122,13 @@
private int mDefaultNotificationLedOn;
private int mDefaultNotificationLedOff;
- private NotificationRecord mSoundNotification;
- private NotificationPlayer mSound;
private boolean mSystemReady;
private int mDisabledNotifications;
+ private NotificationRecord mSoundNotification;
private NotificationRecord mVibrateNotification;
+
+ private IAudioService mAudioService;
private Vibrator mVibrator;
// for enabling and disabling notification pulse behavior
@@ -409,17 +406,19 @@
// cancel whatever's going on
long identity = Binder.clearCallingIdentity();
try {
- mSound.stop();
- }
- finally {
+ final IRingtonePlayer player = mAudioService.getRingtonePlayer();
+ if (player != null) {
+ player.stopAsync();
+ }
+ } catch (RemoteException e) {
+ } finally {
Binder.restoreCallingIdentity(identity);
}
identity = Binder.clearCallingIdentity();
try {
mVibrator.cancel();
- }
- finally {
+ } finally {
Binder.restoreCallingIdentity(identity);
}
}
@@ -445,11 +444,15 @@
synchronized (mNotificationList) {
// sound
mSoundNotification = null;
+
long identity = Binder.clearCallingIdentity();
try {
- mSound.stop();
- }
- finally {
+ final IRingtonePlayer player = mAudioService.getRingtonePlayer();
+ if (player != null) {
+ player.stopAsync();
+ }
+ } catch (RemoteException e) {
+ } finally {
Binder.restoreCallingIdentity(identity);
}
@@ -458,8 +461,7 @@
identity = Binder.clearCallingIdentity();
try {
mVibrator.cancel();
- }
- finally {
+ } finally {
Binder.restoreCallingIdentity(identity);
}
@@ -570,8 +572,6 @@
mContext = context;
mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
mAm = ActivityManagerNative.getDefault();
- mSound = new NotificationPlayer(TAG);
- mSound.setUsesWakeLock(context);
mToastQueue = new ArrayList<ToastRecord>();
mHandler = new WorkerHandler();
@@ -622,6 +622,9 @@
}
void systemReady() {
+ mAudioService = IAudioService.Stub.asInterface(
+ ServiceManager.getService(Context.AUDIO_SERVICE));
+
// no beeping until we're basically done booting
mSystemReady = true;
}
@@ -1026,11 +1029,14 @@
// do not play notifications if stream volume is 0
// (typically because ringer mode is silent).
if (audioManager.getStreamVolume(audioStreamType) != 0) {
- long identity = Binder.clearCallingIdentity();
+ final long identity = Binder.clearCallingIdentity();
try {
- mSound.play(mContext, uri, looping, audioStreamType);
- }
- finally {
+ final IRingtonePlayer player = mAudioService.getRingtonePlayer();
+ if (player != null) {
+ player.playAsync(uri, looping, audioStreamType);
+ }
+ } catch (RemoteException e) {
+ } finally {
Binder.restoreCallingIdentity(identity);
}
}
@@ -1121,11 +1127,14 @@
// sound
if (mSoundNotification == r) {
mSoundNotification = null;
- long identity = Binder.clearCallingIdentity();
+ final long identity = Binder.clearCallingIdentity();
try {
- mSound.stop();
- }
- finally {
+ final IRingtonePlayer player = mAudioService.getRingtonePlayer();
+ if (player != null) {
+ player.stopAsync();
+ }
+ } catch (RemoteException e) {
+ } finally {
Binder.restoreCallingIdentity(identity);
}
}
@@ -1386,7 +1395,6 @@
}
pw.println(" mSoundNotification=" + mSoundNotification);
- pw.println(" mSound=" + mSound);
pw.println(" mVibrateNotification=" + mVibrateNotification);
pw.println(" mDisabledNotifications=0x" + Integer.toHexString(mDisabledNotifications));
pw.println(" mSystemReady=" + mSystemReady);
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 276bc5b..1dce5dd 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -8091,7 +8091,7 @@
private void updateResizingWindows(final WindowState w) {
final WindowStateAnimator winAnimator = w.mWinAnimator;
- if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) {
+ if (w.mHasSurface && !w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) {
w.mContentInsetsChanged |=
!w.mLastContentInsets.equals(w.mContentInsets);
w.mVisibleInsetsChanged |=
@@ -8336,10 +8336,6 @@
for (i=N-1; i>=0; i--) {
WindowState w = mWindows.get(i);
- if (someoneLosingFocus && w == mCurrentFocus && w.isDisplayedLw()) {
- focusDisplayed = true;
- }
-
final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
// Update effect.
@@ -8397,6 +8393,10 @@
winAnimator.setSurfaceBoundaries(recoveringMemory);
}
+ if (someoneLosingFocus && w == mCurrentFocus && w.isDisplayedLw()) {
+ focusDisplayed = true;
+ }
+
updateResizingWindows(w);
}
diff --git a/tests/GridLayoutTest/res/drawable/btn_default.xml b/tests/GridLayoutTest/res/drawable/btn_default.xml
deleted file mode 100644
index c6cfda0..0000000
--- a/tests/GridLayoutTest/res/drawable/btn_default.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_window_focused="false" android:state_enabled="true"
- android:drawable="@drawable/my_btn_default_normal" />
- <item android:state_window_focused="false" android:state_enabled="false"
- android:drawable="@drawable/my_btn_default_normal" />
- <item android:state_pressed="true"
- android:drawable="@drawable/my_btn_default_pressed" />
- <item android:state_focused="true" android:state_enabled="true"
- android:drawable="@drawable/my_btn_default_selected" />
- <item android:state_enabled="true"
- android:drawable="@drawable/my_btn_default_normal" />
- <item android:state_focused="true"
- android:drawable="@drawable/my_btn_default_normal_disable_focused" />
- <item
- android:drawable="@drawable/my_btn_default_normal_disable" />
-</selector>
diff --git a/tests/GridLayoutTest/res/drawable/my_btn_default_normal.9.png b/tests/GridLayoutTest/res/drawable/btn_default_normal.9.png
similarity index 100%
rename from tests/GridLayoutTest/res/drawable/my_btn_default_normal.9.png
rename to tests/GridLayoutTest/res/drawable/btn_default_normal.9.png
Binary files differ
diff --git a/tests/GridLayoutTest/res/drawable/my_btn_default_normal_disable.9.png b/tests/GridLayoutTest/res/drawable/my_btn_default_normal_disable.9.png
deleted file mode 100755
index f4f01c7..0000000
--- a/tests/GridLayoutTest/res/drawable/my_btn_default_normal_disable.9.png
+++ /dev/null
Binary files differ
diff --git a/tests/GridLayoutTest/res/drawable/my_btn_default_normal_disable_focused.9.png b/tests/GridLayoutTest/res/drawable/my_btn_default_normal_disable_focused.9.png
deleted file mode 100755
index 5376db2..0000000
--- a/tests/GridLayoutTest/res/drawable/my_btn_default_normal_disable_focused.9.png
+++ /dev/null
Binary files differ
diff --git a/tests/GridLayoutTest/res/drawable/my_btn_default_pressed.9.png b/tests/GridLayoutTest/res/drawable/my_btn_default_pressed.9.png
deleted file mode 100755
index 4312c27..0000000
--- a/tests/GridLayoutTest/res/drawable/my_btn_default_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/tests/GridLayoutTest/res/drawable/my_btn_default_selected.9.png b/tests/GridLayoutTest/res/drawable/my_btn_default_selected.9.png
deleted file mode 100755
index 06b7790..0000000
--- a/tests/GridLayoutTest/res/drawable/my_btn_default_selected.9.png
+++ /dev/null
Binary files differ
diff --git a/tests/GridLayoutTest/src/com/android/test/layout/LayoutInsetsTest.java b/tests/GridLayoutTest/src/com/android/test/layout/LayoutInsetsTest.java
index e9e1ae7..103de2f 100644
--- a/tests/GridLayoutTest/src/com/android/test/layout/LayoutInsetsTest.java
+++ b/tests/GridLayoutTest/src/com/android/test/layout/LayoutInsetsTest.java
@@ -4,46 +4,49 @@
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
+import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.GridLayout;
import android.widget.TextView;
-import static android.widget.GridLayout.*;
+import static android.widget.GridLayout.ALIGN_BOUNDS;
+import static android.widget.GridLayout.LayoutParams;
+import static android.widget.GridLayout.OPTICAL_BOUNDS;
public class LayoutInsetsTest extends Activity {
+ static int[] GRAVITIES = {Gravity.LEFT, Gravity.LEFT, Gravity.CENTER_HORIZONTAL, Gravity.RIGHT, Gravity.RIGHT};
+
public static View create(Context context) {
+ final int N = GRAVITIES.length;
+
GridLayout p = new GridLayout(context);
p.setUseDefaultMargins(true);
- p.setAlignmentMode(ALIGN_BOUNDS);
- p.setOrientation(VERTICAL);
+ //p.setAlignmentMode(ALIGN_BOUNDS);
+ p.setLayoutMode(OPTICAL_BOUNDS);
- {
- TextView c = new TextView(context);
- c.setTextSize(32);
- c.setText("Email setup");
- p.addView(c);
- }
- {
- Button c = new Button(context);
- c.setBackgroundResource(R.drawable.btn_default);
- c.setText("Test");
- p.addView(c);
+ p.setColumnCount(N);
+
+ for (int i = 0; i < 2*N; i++) {
+ View c;
+ if (i % 2 == 0) {
+ TextView tv = new TextView(context);
+ tv.setTextSize(32);
+ tv.setText("A");
+ c = tv;
+ } else {
+ Button b = new Button(context);
+ b.setBackgroundResource(R.drawable.btn_default_normal);
+ b.setText("B");
+ c = b;
+ }
+
+ LayoutParams lp = new LayoutParams();
+ lp.setGravity(GRAVITIES[(i % N)]);
+ p.addView(c, lp);
+
}
- {
- Button c = new Button(context);
- c.setBackgroundResource(R.drawable.btn_default);
- c.setText("Manual setup");
- p.addView(c);
- c.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Button b = (Button) v;
- b.setEnabled(false);
- }
- });
- }
return p;
}
diff --git a/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java b/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java
index b3a2600..03c2923 100644
--- a/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java
+++ b/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java
@@ -28,17 +28,18 @@
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashSet;
+import java.util.Collections;
import java.util.Iterator;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
- * This smoke test is designed to quickly sniff for any error conditions
- * encountered after initial startup.
+ * This smoke test is designed to check for crashes and ANRs in an attempt to quickly determine if
+ * all minimal functionality in the build is working properly.
*/
public class ProcessErrorsTest extends AndroidTestCase {
-
+
private static final String TAG = "ProcessErrorsTest";
private final Intent mHomeIntent;
@@ -46,15 +47,28 @@
protected ActivityManager mActivityManager;
protected PackageManager mPackageManager;
+ /**
+ * Used to buffer asynchronously-caused crashes and ANRs so that we can have a big fail-party
+ * in the catch-all testCase.
+ */
+ private static final Collection<ProcessError> mAsyncErrors =
+ Collections.synchronizedSet(new LinkedHashSet<ProcessError>());
+
public ProcessErrorsTest() {
mHomeIntent = new Intent(Intent.ACTION_MAIN);
mHomeIntent.addCategory(Intent.CATEGORY_HOME);
mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
+ /**
+ * {@inheritDoc}
+ */
@Override
public void setUp() throws Exception {
super.setUp();
+ // First, make sure we have a Context
+ assertNotNull("getContext() returned null!", getContext());
+
mActivityManager = (ActivityManager)
getContext().getSystemService(Context.ACTIVITY_SERVICE);
mPackageManager = getContext().getPackageManager();
@@ -75,43 +89,48 @@
assertNull(reportMsg, reportMsg);
}
- private String checkForProcessErrors() throws Exception {
- List<ProcessErrorStateInfo> errList;
- errList = mActivityManager.getProcessesInErrorState();
+ /**
+ * A test that runs all Launcher-launchable activities and verifies that no ANRs or crashes
+ * happened while doing so.
+ */
+ public void testRunAllActivities() throws Exception {
+ final Set<ProcessError> errSet = new LinkedHashSet<ProcessError>();
- // note: this contains information about each process that is currently in an error
- // condition. if the list is empty (null) then "we're good".
+ for (ResolveInfo app : getLauncherActivities(mPackageManager)) {
+ final Collection<ProcessError> errProcs = runOneActivity(app);
+ if (errProcs != null) {
+ errSet.addAll(errProcs);
+ }
+ }
- // if the list is non-empty, then it's useful to report the contents of the list
- final String reportMsg = reportListContents(errList);
- return reportMsg;
+ if (!errSet.isEmpty()) {
+ fail(String.format("Got %d errors:\n%s", errSet.size(),
+ reportWrappedListContents(errSet)));
+ }
}
/**
- * A helper function to query the provided {@link PackageManager} for a list of Activities that
- * can be launched from Launcher.
+ * This test checks for asynchronously-caused errors (crashes or ANRs) and fails in case any
+ * were found. This prevents us from needing to fail unrelated testcases when, for instance
+ * a background thread causes a crash or ANR.
+ * <p />
+ * Because this behavior depends on the contents of static member {@link mAsyncErrors}, we clear
+ * that state here as a side-effect so that if two successive runs happen in the same process,
+ * the asynchronous errors in the second test run won't include errors produced during the first
+ * run.
*/
- static List<ResolveInfo> getLauncherActivities(PackageManager pm) {
- final Intent launchable = new Intent(Intent.ACTION_MAIN);
- launchable.addCategory(Intent.CATEGORY_LAUNCHER);
- final List<ResolveInfo> activities = pm.queryIntentActivities(launchable, 0);
- return activities;
+ public void testZZReportAsyncErrors() throws Exception {
+ try {
+ if (!mAsyncErrors.isEmpty()) {
+ fail(String.format("Got %d asynchronous errors:\n%s", mAsyncErrors.size(),
+ reportWrappedListContents(mAsyncErrors)));
+ }
+ } finally {
+ // Reset state just in case we should get another set of runs in the same process
+ mAsyncErrors.clear();
+ }
}
- /**
- * A helper function to create an {@link Intent} to run, given a {@link ResolveInfo} specifying
- * an activity to be launched.
- */
- static Intent intentForActivity(ResolveInfo app) {
- // build an Intent to launch the specified app
- final ComponentName component = new ComponentName(app.activityInfo.packageName,
- app.activityInfo.name);
- final Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setComponent(component);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- return intent;
- }
/**
* A method to run the specified Activity and return a {@link Collection} of the Activities that
@@ -129,8 +148,7 @@
// We check for any Crash or ANR dialogs that are already up, and we ignore them. This is
// so that we don't report crashes that were caused by prior apps (which those particular
- // tests should have caught and reported already). Otherwise, test failures would cascade
- // from the initial broken app to many/all of the tests following that app's launch.
+ // tests should have caught and reported already).
final Collection<ProcessError> preErrProcs =
ProcessError.fromCollection(mActivityManager.getProcessesInErrorState());
@@ -155,8 +173,24 @@
// possible to occur.
final Collection<ProcessError> errProcs =
ProcessError.fromCollection(mActivityManager.getProcessesInErrorState());
- // Take the difference between the error processes we see now, and the ones that were
- // present when we started
+
+ // Distinguish the asynchronous crashes/ANRs from the synchronous ones by checking the
+ // crash package name against the package name for {@code app}
+ if (errProcs != null) {
+ Iterator<ProcessError> errIter = errProcs.iterator();
+ while (errIter.hasNext()) {
+ ProcessError err = errIter.next();
+ if (!packageMatches(app, err)) {
+ // async! Drop into mAsyncErrors and don't report now
+ mAsyncErrors.add(err);
+ errIter.remove();
+ }
+ }
+ }
+ // Take the difference between the remaining current error processes and the ones that were
+ // present when we started. The result is guaranteed to be:
+ // 1) Errors that are pertinent to this app's package
+ // 2) Errors that are pertinent to this particular app invocation
if (errProcs != null && preErrProcs != null) {
errProcs.removeAll(preErrProcs);
}
@@ -164,27 +198,63 @@
return errProcs;
}
- /**
- * A test that runs all Launcher-launchable activities and verifies that no ANRs or crashes
- * happened while doing so.
- */
- public void testRunAllActivities() throws Exception {
- final Set<ProcessError> errSet = new HashSet<ProcessError>();
+ private String checkForProcessErrors() throws Exception {
+ List<ProcessErrorStateInfo> errList;
+ errList = mActivityManager.getProcessesInErrorState();
- for (ResolveInfo app : getLauncherActivities(mPackageManager)) {
- final Collection<ProcessError> errProcs = runOneActivity(app);
- if (errProcs != null) {
- errSet.addAll(errProcs);
- }
- }
+ // note: this contains information about each process that is currently in an error
+ // condition. if the list is empty (null) then "we're good".
- if (!errSet.isEmpty()) {
- fail(String.format("Got %d errors:\n%s", errSet.size(),
- reportWrappedListContents(errSet)));
- }
+ // if the list is non-empty, then it's useful to report the contents of the list
+ final String reportMsg = reportListContents(errList);
+ return reportMsg;
}
- String reportWrappedListContents(Collection<ProcessError> errList) {
+ /**
+ * A helper function that checks whether the specified error could have been caused by the
+ * specified app.
+ *
+ * @param app The app to check against
+ * @param err The error that we're considering
+ */
+ private static boolean packageMatches(ResolveInfo app, ProcessError err) {
+ final String appPkg = app.activityInfo.packageName;
+ final String errPkg = err.info.processName;
+ Log.d(TAG, String.format("packageMatches(%s, %s)", appPkg, errPkg));
+ return appPkg.equals(errPkg);
+ }
+
+ /**
+ * A helper function to query the provided {@link PackageManager} for a list of Activities that
+ * can be launched from Launcher.
+ */
+ static List<ResolveInfo> getLauncherActivities(PackageManager pm) {
+ final Intent launchable = new Intent(Intent.ACTION_MAIN);
+ launchable.addCategory(Intent.CATEGORY_LAUNCHER);
+ final List<ResolveInfo> activities = pm.queryIntentActivities(launchable, 0);
+ return activities;
+ }
+
+ /**
+ * A helper function to create an {@link Intent} to run, given a {@link ResolveInfo} specifying
+ * an activity to be launched.
+ */
+ static Intent intentForActivity(ResolveInfo app) {
+ final ComponentName component = new ComponentName(app.activityInfo.packageName,
+ app.activityInfo.name);
+ final Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setComponent(component);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ return intent;
+ }
+
+ /**
+ * Report error reports for {@link ProcessErrorStateInfo} instances that are wrapped inside of
+ * {@link ProcessError} instances. Just unwraps and calls
+ * {@see reportListContents(Collection<ProcessErrorStateInfo>)}.
+ */
+ static String reportWrappedListContents(Collection<ProcessError> errList) {
List<ProcessErrorStateInfo> newList = new ArrayList<ProcessErrorStateInfo>(errList.size());
for (ProcessError err : errList) {
newList.add(err.info);
@@ -198,7 +268,7 @@
* @param errList The error report containing one or more error records.
* @return Returns a string containing all of the errors.
*/
- private String reportListContents(Collection<ProcessErrorStateInfo> errList) {
+ private static String reportListContents(Collection<ProcessErrorStateInfo> errList) {
if (errList == null) return null;
StringBuilder builder = new StringBuilder();
diff --git a/tests/SmokeTest/tests/src/com/android/smoketest/SmokeTestRunner.java b/tests/SmokeTest/tests/src/com/android/smoketest/SmokeTestRunner.java
index 51331fe..db549a1 100644
--- a/tests/SmokeTest/tests/src/com/android/smoketest/SmokeTestRunner.java
+++ b/tests/SmokeTest/tests/src/com/android/smoketest/SmokeTestRunner.java
@@ -47,9 +47,6 @@
final PackageManager pm = getTargetContext().getPackageManager();
final List<ResolveInfo> apps = ProcessErrorsTest.getLauncherActivities(pm);
- // FIXME: figure out some way to control the reported class names for these anonymous
- // FIXME: class instances.
-
final TestCase setupTest = new ProcessErrorsTest() {
@Override
public void runTest() throws Exception {
@@ -88,6 +85,15 @@
suite.addTest(appTest);
}
+ final TestCase asyncErrorTest = new ProcessErrorsTest() {
+ @Override
+ public void runTest() throws Exception {
+ testZZReportAsyncErrors();
+ }
+ };
+ asyncErrorTest.setName("testAsynchronousErrors");
+ suite.addTest(asyncErrorTest);
+
return suite;
}
}
diff --git a/tools/layoutlib/bridge/src/android/animation/AnimationThread.java b/tools/layoutlib/bridge/src/android/animation/AnimationThread.java
index b46134a..b10ec9f 100644
--- a/tools/layoutlib/bridge/src/android/animation/AnimationThread.java
+++ b/tools/layoutlib/bridge/src/android/animation/AnimationThread.java
@@ -84,20 +84,22 @@
public void run() {
Bridge.prepareThread();
try {
+ /* FIXME: The ANIMATION_FRAME message no longer exists. Instead, the
+ * animation timing loop is completely based on a Choreographer objects
+ * that schedules animation and drawing frames. The animation handler is
+ * no longer even a handler; it is just a Runnable enqueued on the Choreographer.
Handler_Delegate.setCallback(new IHandlerCallback() {
@Override
public void sendMessageAtTime(Handler handler, Message msg, long uptimeMillis) {
- if (msg.what == ValueAnimator.ANIMATION_START /*||
- FIXME: The ANIMATION_FRAME message no longer exists. Instead,
- the animation timing loop is based on a Choreographer object
- that schedules animation and drawing frames.
- msg.what == ValueAnimator.ANIMATION_FRAME*/) {
+ if (msg.what == ValueAnimator.ANIMATION_START ||
+ msg.what == ValueAnimator.ANIMATION_FRAME) {
mQueue.add(new MessageBundle(handler, msg, uptimeMillis));
} else {
// just ignore.
}
}
});
+ */
// call out to the pre-animation work, which should start an animation or more.
Result result = preAnimation();
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 4ec2e02..26229be 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -270,25 +270,6 @@
&& doBooleanCommand("DRIVER RXFILTER-START");
}
- public int getPowerMode() {
- String ret = doStringCommand("DRIVER GETPOWER");
- if (!TextUtils.isEmpty(ret)) {
- // reply comes back in the form "powermode = XX" where XX is the
- // number we're interested in.
- String[] tokens = ret.split(" = ");
- try {
- if (tokens.length == 2) return Integer.parseInt(tokens[1]);
- } catch (NumberFormatException e) {
- return -1;
- }
- }
- return -1;
- }
-
- public boolean setPowerMode(int mode) {
- return doBooleanCommand("DRIVER POWERMODE " + mode);
- }
-
public int getBand() {
String ret = doStringCommand("DRIVER GETBAND");
if (!TextUtils.isEmpty(ret)) {
@@ -366,12 +347,10 @@
}
public void enableBackgroundScan(boolean enable) {
- //Note: BGSCAN-START and BGSCAN-STOP are documented in core/res/res/values/config.xml
- //and will need an update if the names are changed
if (enable) {
- doBooleanCommand("DRIVER BGSCAN-START");
+ doBooleanCommand("SET pno 1");
} else {
- doBooleanCommand("DRIVER BGSCAN-STOP");
+ doBooleanCommand("SET pno 0");
}
}
@@ -467,6 +446,14 @@
return doBooleanCommand("SET interface=" + iface + " p2p_group_idle " + time);
}
+ public void setPowerSave(boolean enabled) {
+ if (enabled) {
+ doBooleanCommand("SET ps 1");
+ } else {
+ doBooleanCommand("SET ps 0");
+ }
+ }
+
public boolean setP2pPowerSave(String iface, boolean enabled) {
if (enabled) {
return doBooleanCommand("P2P_SET interface=" + iface + " ps 1");
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index ac0fbfa..3503633 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -305,13 +305,11 @@
static final int CMD_RECONNECT = BASE + 75;
/* Reassociate to a network */
static final int CMD_REASSOCIATE = BASE + 76;
- /* Controls power mode and suspend mode optimizations
+ /* Controls suspend mode optimizations
*
- * When high perf mode is enabled, power mode is set to
- * POWER_MODE_ACTIVE and suspend mode optimizations are disabled
+ * When high perf mode is enabled, suspend mode optimizations are disabled
*
- * When high perf mode is disabled, power mode is set to
- * POWER_MODE_AUTO and suspend mode optimizations are enabled
+ * When high perf mode is disabled, suspend mode optimizations are enabled
*
* Suspend mode optimizations include:
* - packet filtering
@@ -374,11 +372,8 @@
*/
private static final int DEFAULT_MAX_DHCP_RETRIES = 9;
- static final int POWER_MODE_ACTIVE = 1;
- static final int POWER_MODE_AUTO = 0;
-
- /* Tracks the power mode for restoration after a DHCP request/renewal goes through */
- private int mPowerMode = POWER_MODE_AUTO;
+ /* Tracks if power save is enabled in driver */
+ private boolean mPowerSaveEnabled = true;;
/**
* Default framework scan interval in milliseconds. This is used in the scenario in which
@@ -1683,21 +1678,18 @@
mWifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED);
}
- mPowerMode = mWifiNative.getPowerMode();
- if (mPowerMode < 0) {
- // Handle the case where supplicant driver does not support
- // getPowerModeCommand.
- mPowerMode = WifiStateMachine.POWER_MODE_AUTO;
- }
- if (mPowerMode != WifiStateMachine.POWER_MODE_ACTIVE) {
- mWifiNative.setPowerMode(WifiStateMachine.POWER_MODE_ACTIVE);
+ /* Disable power save during DHCP */
+ if (mPowerSaveEnabled) {
+ mPowerSaveEnabled = false;
+ mWifiNative.setPowerSave(mPowerSaveEnabled);
}
}
void handlePostDhcpSetup() {
- /* restore power mode */
- mWifiNative.setPowerMode(mPowerMode);
+ /* Restore power save */
+ mPowerSaveEnabled = true;
+ mWifiNative.setPowerSave(mPowerSaveEnabled);
// Set the coexistence mode back to its default value
mWifiNative.setBluetoothCoexistenceMode(
@@ -2549,6 +2541,8 @@
mWifiNative.stopFilteringMulticastV4Packets();
}
+ mWifiNative.setPowerSave(mPowerSaveEnabled);
+
if (mIsScanMode) {
mWifiNative.setScanResultHandling(SCAN_ONLY_MODE);
mWifiNative.disconnect();
@@ -2820,15 +2814,15 @@
break;
case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
SupplicantState state = handleSupplicantStateChange(message);
- // Due to a WEXT bug, during the time of driver start/stop
- // we can go into a driver stopped state in an unexpected way.
- // The sequence eventually puts interface
- // up and we should be back to a connected state
+ // A driver/firmware hang can now put the interface in a down state.
+ // We detect the interface going down and recover from it
if (!SupplicantState.isDriverActive(state)) {
if (mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) {
handleNetworkDisconnect();
}
+ log("Detected an interface down, restart driver");
transitionTo(mDriverStoppedState);
+ sendMessage(CMD_START_DRIVER);
break;
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
index 3751727..8942ff1 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
@@ -27,8 +27,9 @@
import java.util.HashMap;
/**
- * A class representing a Wi-Fi P2p device list
+ * A class representing a Wi-Fi P2p device list.
*
+ * Note that the operations are not thread safe.
* {@see WifiP2pManager}
*/
public class WifiP2pDeviceList implements Parcelable {
@@ -83,6 +84,13 @@
}
/** @hide */
+ public void updateStatus(String deviceAddress, int status) {
+ if (deviceAddress == null) return;
+ WifiP2pDevice d = mDevices.get(deviceAddress);
+ d.status = status;
+ }
+
+ /** @hide */
public WifiP2pDevice get(String deviceAddress) {
if (deviceAddress == null) return null;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index b25bf91..ef77d45 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -30,6 +30,7 @@
import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceInfo;
import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceResponse;
import android.os.Binder;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.Handler;
import android.os.Looper;
@@ -265,6 +266,41 @@
*/
public static final String EXTRA_WIFI_P2P_DEVICE = "wifiP2pDevice";
+ /**
+ * The lookup key for a {@link #String} object.
+ * Retrieve with {@link android.os.Bundle#getString(String)}.
+ * @hide
+ */
+ public static final String APP_PKG_BUNDLE_KEY = "appPkgName";
+
+ /**
+ * The lookup key for a {@link #Boolean} object.
+ * Retrieve with {@link android.os.Bundle#getBoolean(String)}.
+ * @hide
+ */
+ public static final String RESET_DIALOG_LISTENER_BUNDLE_KEY = "dialogResetFlag";
+
+ /**
+ * The lookup key for a {@link #String} object.
+ * Retrieve with {@link android.os.Bundle#getString(String)}.
+ * @hide
+ */
+ public static final String WPS_PIN_BUNDLE_KEY = "wpsPin";
+
+ /**
+ * The lookup key for a {@link android.net.wifi.p2p.WifiP2pDevice} object
+ * Retrieve with {@link android.os.Bundle#getParcelable(String)}.
+ * @hide
+ */
+ public static final String P2P_DEV_BUNDLE_KEY = "wifiP2pDevice";
+
+ /**
+ * The lookup key for a {@link android.net.wifi.p2p.WifiP2pConfig} object
+ * Retrieve with {@link android.os.Bundle#getParcelable(String)}.
+ * @hide
+ */
+ public static final String P2P_CONFIG_BUNDLE_KEY = "wifiP2pConfig";
+
IWifiP2pManager mService;
private static final int BASE = Protocol.BASE_WIFI_P2P_MANAGER;
@@ -388,6 +424,18 @@
/** @hide */
public static final int SET_DEVICE_NAME_SUCCEEDED = BASE + 53;
+ /** @hide */
+ public static final int SET_DIALOG_LISTENER = BASE + 54;
+ /** @hide */
+ public static final int DIALOG_LISTENER_DETACHED = BASE + 55;
+ /** @hide */
+ public static final int DIALOG_LISTENER_ATTACHED = BASE + 56;
+
+ /** @hide */
+ public static final int CONNECTION_REQUESTED = BASE + 57;
+ /** @hide */
+ public static final int SHOW_PIN_REQUESTED = BASE + 58;
+
/**
* Create a new WifiP2pManager instance. Applications use
* {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
@@ -427,6 +475,14 @@
*/
public static final int NO_SERVICE_REQUESTS = 3;
+ /**
+ * Passed with {@link DialogListener#onDetached}.
+ * Indicates that the registered listener was detached from the system because
+ * the application went into background.
+ * @hide
+ */
+ public static final int NOT_IN_FOREGROUND = 4;
+
/** Interface for callback invocation when framework channel is lost */
public interface ChannelListener {
/**
@@ -475,7 +531,7 @@
public void onGroupInfoAvailable(WifiP2pGroup group);
}
- /**
+ /**
* Interface for callback invocation when service discovery response other than
* Upnp or Bonjour is received
*/
@@ -559,15 +615,59 @@
/**
+ * Interface for callback invocation when dialog events are received.
+ * see {@link #setDialogListener}.
+ * @hide
+ */
+ public interface DialogListener {
+
+ /**
+ * Called by the system when a request to show WPS pin is received.
+ *
+ * @param pin WPS pin.
+ */
+ public void onShowPinRequested(String pin);
+
+ /**
+ * Called by the system when a request to establish the connection is received.
+ *
+ * Application can then call {@link #connect} with the given config if the request
+ * is acceptable.
+ *
+ * @param device the source device.
+ * @param config p2p configuration.
+ */
+ public void onConnectionRequested(WifiP2pDevice device, WifiP2pConfig config);
+
+ /**
+ * Called by the system when this listener was attached to the system.
+ */
+ public void onAttached();
+
+ /**
+ * Called by the system when this listener was detached from the system or
+ * failed to attach.
+ *
+ * Application can request again using {@link #setDialogListener} when it is
+ * in the foreground.
+ *
+ * @param reason The reason for failure could be one of {@link #ERROR},
+ * {@link #BUSY}, {@link #P2P_UNSUPPORTED} or {@link #NOT_IN_FOREGROUND}
+ */
+ public void onDetached(int reason);
+ }
+
+ /**
* A channel that connects the application to the Wifi p2p framework.
* Most p2p operations require a Channel as an argument. An instance of Channel is obtained
* by doing a call on {@link #initialize}
*/
public static class Channel {
- Channel(Looper looper, ChannelListener l) {
+ Channel(Context context, Looper looper, ChannelListener l) {
mAsyncChannel = new AsyncChannel();
mHandler = new P2pHandler(looper);
mChannelListener = l;
+ mContext = context;
}
private final static int INVALID_LISTENER_KEY = 0;
private ChannelListener mChannelListener;
@@ -578,9 +678,11 @@
private HashMap<Integer, Object> mListenerMap = new HashMap<Integer, Object>();
private Object mListenerMapLock = new Object();
private int mListenerKey = 0;
+ private DialogListener mDialogListener;
- AsyncChannel mAsyncChannel;
- P2pHandler mHandler;
+ private AsyncChannel mAsyncChannel;
+ private P2pHandler mHandler;
+ Context mContext;
class P2pHandler extends Handler {
P2pHandler(Looper looper) {
super(looper);
@@ -656,6 +758,34 @@
WifiP2pServiceResponse resp = (WifiP2pServiceResponse) message.obj;
handleServiceResponse(resp);
break;
+ case WifiP2pManager.CONNECTION_REQUESTED:
+ if (mDialogListener != null) {
+ Bundle bundle = message.getData();
+ mDialogListener.onConnectionRequested(
+ (WifiP2pDevice)bundle.getParcelable(
+ P2P_DEV_BUNDLE_KEY),
+ (WifiP2pConfig)bundle.getParcelable(
+ P2P_CONFIG_BUNDLE_KEY));
+ }
+ break;
+ case WifiP2pManager.SHOW_PIN_REQUESTED:
+ if (mDialogListener != null) {
+ Bundle bundle = message.getData();
+ mDialogListener.onShowPinRequested(
+ bundle.getString(WPS_PIN_BUNDLE_KEY));
+ }
+ break;
+ case WifiP2pManager.DIALOG_LISTENER_ATTACHED:
+ if (mDialogListener != null) {
+ mDialogListener.onAttached();
+ }
+ break;
+ case WifiP2pManager.DIALOG_LISTENER_DETACHED:
+ if (mDialogListener != null) {
+ mDialogListener.onDetached(message.arg1);
+ mDialogListener = null;
+ }
+ break;
default:
Log.d(TAG, "Ignored " + message);
break;
@@ -721,6 +851,10 @@
return mListenerMap.remove(key);
}
}
+
+ private void setDialogListener(DialogListener listener) {
+ mDialogListener = listener;
+ }
}
private static void checkChannel(Channel c) {
@@ -748,7 +882,7 @@
Messenger messenger = getMessenger();
if (messenger == null) return null;
- Channel c = new Channel(srcLooper, listener);
+ Channel c = new Channel(srcContext, srcLooper, listener);
if (c.mAsyncChannel.connectSync(srcContext, c.mHandler, messenger)
== AsyncChannel.STATUS_SUCCESSFUL) {
return c;
@@ -1126,6 +1260,41 @@
}
+ /**
+ * Set dialog listener to over-ride system dialogs on p2p events. This function
+ * allows an application to receive notifications on connection requests from
+ * peers so that it can customize the user experience for connection with
+ * peers.
+ *
+ * <p> The function call immediately returns after sending a request
+ * to the framework. The application is notified of a success or failure to attach
+ * to the system through listener callbacks {@link DialogListener#onAttached} or
+ * {@link DialogListener#onDetached}.
+ *
+ * <p> Note that only foreground application will be successful in overriding the
+ * system dialogs.
+ * @hide
+ *
+ * @param c is the channel created at {@link #initialize}
+ * @param listener for callback on a dialog event.
+ */
+ public void setDialogListener(Channel c, DialogListener listener) {
+ checkChannel(c);
+ c.setDialogListener(listener);
+
+ /**
+ * mAsyncChannel should always stay private and inaccessible from the app
+ * to prevent an app from sending a message with a fake app name to gain
+ * control over the dialogs
+ */
+ Message msg = Message.obtain();
+ Bundle bundle = new Bundle();
+ bundle.putString(APP_PKG_BUNDLE_KEY, c.mContext.getPackageName());
+ bundle.putBoolean(RESET_DIALOG_LISTENER_BUNDLE_KEY, listener == null);
+ msg.what = SET_DIALOG_LISTENER;
+ msg.setData(bundle);
+ c.mAsyncChannel.sendMessage(msg);
+ }
/**
* Get a reference to WifiP2pService handler. This is used to establish
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 77e6187..f0adb25 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -16,10 +16,13 @@
package android.net.wifi.p2p;
+import android.app.Activity;
+import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.app.ActivityManager.RunningTaskInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -46,15 +49,19 @@
import android.net.wifi.p2p.nsd.WifiP2pServiceRequest;
import android.net.wifi.p2p.nsd.WifiP2pServiceResponse;
import android.os.Binder;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.INetworkManagementService;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.os.Messenger;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
+import android.os.Parcelable.Creator;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Slog;
@@ -102,6 +109,8 @@
INetworkManagementService mNwService;
private DhcpStateMachine mDhcpStateMachine;
+ private ActivityManager mActivityMgr;
+
private P2pStateMachine mP2pStateMachine;
private AsyncChannel mReplyChannel = new AsyncChannel();
private AsyncChannel mWifiChannel;
@@ -148,7 +157,7 @@
/* When a group has been explicitly created by an app, we persist the group
* even after all clients have been disconnected until an explicit remove
* is invoked */
- private boolean mPersistGroup;
+ private boolean mAutonomousGroup;
/* Track whether we are in p2p discovery. This is used to avoid sending duplicate
* broadcasts
@@ -167,6 +176,13 @@
/* clients(application) information list. */
private HashMap<Messenger, ClientInfo> mClientInfoList = new HashMap<Messenger, ClientInfo>();
+ /* The foreground application's messenger.
+ * The connection request is notified only to foreground application */
+ private Messenger mForegroundAppMessenger;
+
+ /* the package name of foreground application. */
+ private String mForegroundAppPkgName;
+
/* Is chosen as a unique range to avoid conflict with
the range defined in Tethering.java */
private static final String[] DHCP_RANGE = {"192.168.49.2", "192.168.49.254"};
@@ -177,6 +193,8 @@
//STOPSHIP: get this from native side
mInterface = "p2p0";
+ mActivityMgr = (ActivityManager)context.getSystemService(Activity.ACTIVITY_SERVICE);
+
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, NETWORKTYPE, "");
mP2pSupported = mContext.getPackageManager().hasSystemFeature(
@@ -261,6 +279,9 @@
// Saved WifiP2pGroup from invitation request
private WifiP2pGroup mSavedP2pGroup;
+ // Saved WifiP2pDevice from provisioning request
+ private WifiP2pDevice mSavedProvDiscDevice;
+
P2pStateMachine(String name, boolean p2pSupported) {
super(name);
@@ -380,6 +401,18 @@
case WifiP2pManager.REQUEST_GROUP_INFO:
replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, mGroup);
break;
+ case WifiP2pManager.SET_DIALOG_LISTENER:
+ String appPkgName = (String)message.getData().getString(
+ WifiP2pManager.APP_PKG_BUNDLE_KEY);
+ boolean isReset = message.getData().getBoolean(
+ WifiP2pManager.RESET_DIALOG_LISTENER_BUNDLE_KEY);
+ if (setDialogListenerApp(message.replyTo, appPkgName, isReset)) {
+ replyToMessage(message, WifiP2pManager.DIALOG_LISTENER_ATTACHED);
+ } else {
+ replyToMessage(message, WifiP2pManager.DIALOG_LISTENER_DETACHED,
+ WifiP2pManager.NOT_IN_FOREGROUND);
+ }
+ break;
// Ignore
case WifiMonitor.P2P_INVITATION_RESULT_EVENT:
case WifiMonitor.SCAN_RESULTS_EVENT:
@@ -393,7 +426,7 @@
case PEER_CONNECTION_USER_REJECT:
case GROUP_CREATING_TIMED_OUT:
break;
- /* unexpected group created, remove */
+ /* unexpected group created, remove */
case WifiMonitor.P2P_GROUP_STARTED_EVENT:
mGroup = (WifiP2pGroup) message.obj;
loge("Unexpected group creation, remove " + mGroup);
@@ -447,6 +480,10 @@
replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_FAILED,
WifiP2pManager.P2P_UNSUPPORTED);
break;
+ case WifiP2pManager.SET_DIALOG_LISTENER:
+ replyToMessage(message, WifiP2pManager.DIALOG_LISTENER_DETACHED,
+ WifiP2pManager.P2P_UNSUPPORTED);
+ break;
case WifiP2pManager.REMOVE_LOCAL_SERVICE:
replyToMessage(message, WifiP2pManager.REMOVE_LOCAL_SERVICE_FAILED,
WifiP2pManager.P2P_UNSUPPORTED);
@@ -714,33 +751,53 @@
switch (message.what) {
case WifiP2pManager.CONNECT:
if (DBG) logd(getName() + " sending connect");
- mSavedPeerConfig = (WifiP2pConfig) message.obj;
- mPersistGroup = false;
- int netId = configuredNetworkId(mSavedPeerConfig.deviceAddress);
- if (netId >= 0) {
- //TODO: if failure, remove config and do a regular p2pConnect()
- mWifiNative.p2pReinvoke(netId, mSavedPeerConfig.deviceAddress);
- } else {
+ WifiP2pConfig config = (WifiP2pConfig) message.obj;
+ mAutonomousGroup = false;
+
+ if (mSavedPeerConfig != null && config.deviceAddress.equals(
+ mSavedPeerConfig.deviceAddress)) {
+ mSavedPeerConfig = config;
+
//Stop discovery before issuing connect
mWifiNative.p2pStopFind();
- //If peer is a GO, we do not need to send provisional discovery,
- //the supplicant takes care of it.
if (mWifiNative.isGroupOwner(mSavedPeerConfig.deviceAddress)) {
- if (DBG) logd("Sending join to GO");
p2pConnectWithPinDisplay(mSavedPeerConfig, JOIN_GROUP);
- transitionTo(mGroupNegotiationState);
} else {
- if (DBG) logd("Sending prov disc");
- transitionTo(mProvisionDiscoveryState);
+ p2pConnectWithPinDisplay(mSavedPeerConfig, FORM_GROUP);
+ }
+ transitionTo(mGroupNegotiationState);
+ } else {
+ mSavedPeerConfig = config;
+ int netId = configuredNetworkId(mSavedPeerConfig.deviceAddress);
+ if (netId >= 0) {
+ //TODO: if failure, remove config and do a regular p2pConnect()
+ mWifiNative.p2pReinvoke(netId, mSavedPeerConfig.deviceAddress);
+ } else {
+ //Stop discovery before issuing connect
+ mWifiNative.p2pStopFind();
+ //If peer is a GO, we do not need to send provisional discovery,
+ //the supplicant takes care of it.
+ if (mWifiNative.isGroupOwner(mSavedPeerConfig.deviceAddress)) {
+ if (DBG) logd("Sending join to GO");
+ p2pConnectWithPinDisplay(mSavedPeerConfig, JOIN_GROUP);
+ transitionTo(mGroupNegotiationState);
+ } else {
+ if (DBG) logd("Sending prov disc");
+ transitionTo(mProvisionDiscoveryState);
+ }
}
}
- updateDeviceStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED);
+ mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED);
sendP2pPeersChangedBroadcast();
replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
break;
case WifiMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT:
mSavedPeerConfig = (WifiP2pConfig) message.obj;
- transitionTo(mUserAuthorizingInvitationState);
+
+ if (!sendConnectNoticeToApp(mPeers.get(mSavedPeerConfig.deviceAddress),
+ mSavedPeerConfig)) {
+ transitionTo(mUserAuthorizingInvitationState);
+ }
break;
case WifiMonitor.P2P_INVITATION_RECEIVED_EVENT:
WifiP2pGroup group = (WifiP2pGroup) message.obj;
@@ -756,7 +813,7 @@
//Check if we have the owner in peer list and use appropriate
//wps method. Default is to use PBC.
- if ((owner = getDeviceFromPeerList(owner.deviceAddress)) != null) {
+ if ((owner = mPeers.get(owner.deviceAddress)) != null) {
if (owner.wpsPbcSupported()) {
mSavedPeerConfig.wps.setup = WpsInfo.PBC;
} else if (owner.wpsKeypadSupported()) {
@@ -765,29 +822,23 @@
mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY;
}
}
- transitionTo(mUserAuthorizingInvitationState);
+
+ //TODO In the p2p client case, we should set source address correctly.
+ if (!sendConnectNoticeToApp(mPeers.get(mSavedPeerConfig.deviceAddress),
+ mSavedPeerConfig)) {
+ transitionTo(mUserAuthorizingInvitationState);
+ }
break;
case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT:
case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT:
- WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj;
- mSavedPeerConfig = new WifiP2pConfig();
- mSavedPeerConfig.deviceAddress = provDisc.device.deviceAddress;
- if (message.what == WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT) {
- mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD;
- if (DBG) logd("Keypad prov disc request");
- } else if (message.what == WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT) {
- mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY;
- mSavedPeerConfig.wps.pin = provDisc.pin;
- if (DBG) logd("Display prov disc request");
- } else {
- mSavedPeerConfig.wps.setup = WpsInfo.PBC;
- if (DBG) logd("PBC prov disc request");
- }
- transitionTo(mUserAuthorizingInvitationState);
- break;
+ //We let the supplicant handle the provision discovery response
+ //and wait instead for the GO_NEGOTIATION_REQUEST_EVENT.
+ //Handling provision discovery and issuing a p2p_connect before
+ //group negotiation comes through causes issues
+ break;
case WifiP2pManager.CREATE_GROUP:
- mPersistGroup = true;
+ mAutonomousGroup = true;
if (mWifiNative.p2pGroupAdd()) {
replyToMessage(message, WifiP2pManager.CREATE_GROUP_SUCCEEDED);
} else {
@@ -849,12 +900,16 @@
@Override
public void enter() {
if (DBG) logd(getName());
- notifyInvitationReceived();
+ if (!sendConnectNoticeToApp(mPeers.get(mSavedPeerConfig.deviceAddress),
+ mSavedPeerConfig)) {
+ notifyInvitationReceived();
+ }
}
@Override
public boolean processMessage(Message message) {
if (DBG) logd(getName() + message.toString());
+ boolean ret = HANDLED;
switch (message.what) {
case PEER_CONNECTION_USER_ACCEPT:
//TODO: handle persistence
@@ -863,7 +918,7 @@
} else {
p2pConnectWithPinDisplay(mSavedPeerConfig, FORM_GROUP);
}
- updateDeviceStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED);
+ mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED);
sendP2pPeersChangedBroadcast();
transitionTo(mGroupNegotiationState);
break;
@@ -875,7 +930,7 @@
default:
return NOT_HANDLED;
}
- return HANDLED;
+ return ret;
}
@Override
@@ -933,7 +988,9 @@
if (DBG) logd("Found a match " + mSavedPeerConfig);
mSavedPeerConfig.wps.pin = provDisc.pin;
mWifiNative.p2pConnect(mSavedPeerConfig, FORM_GROUP);
- notifyInvitationSent(provDisc.pin, device.deviceAddress);
+ if (!sendShowPinReqToFrontApp(provDisc.pin)) {
+ notifyInvitationSent(provDisc.pin, device.deviceAddress);
+ }
transitionTo(mGroupNegotiationState);
}
break;
@@ -970,7 +1027,7 @@
P2pStateMachine.this, mGroup.getInterface());
mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
WifiP2pDevice groupOwner = mGroup.getOwner();
- updateDeviceStatus(groupOwner.deviceAddress, WifiP2pDevice.CONNECTED);
+ mPeers.updateStatus(groupOwner.deviceAddress, WifiP2pDevice.CONNECTED);
sendP2pPeersChangedBroadcast();
}
mSavedPeerConfig = null;
@@ -1005,7 +1062,7 @@
sendP2pConnectionChangedBroadcast();
}
- if (!mPersistGroup) {
+ if (!mAutonomousGroup) {
mWifiNative.setP2pGroupIdle(mGroup.getInterface(), GROUP_IDLE_TIME_S);
}
}
@@ -1018,8 +1075,12 @@
WifiP2pDevice device = (WifiP2pDevice) message.obj;
String deviceAddress = device.deviceAddress;
if (deviceAddress != null) {
+ if (mSavedProvDiscDevice != null &&
+ deviceAddress.equals(mSavedProvDiscDevice.deviceAddress)) {
+ mSavedProvDiscDevice = null;
+ }
mGroup.addClient(deviceAddress);
- updateDeviceStatus(deviceAddress, WifiP2pDevice.CONNECTED);
+ mPeers.updateStatus(deviceAddress, WifiP2pDevice.CONNECTED);
if (DBG) logd(getName() + " ap sta connected");
sendP2pPeersChangedBroadcast();
} else {
@@ -1030,10 +1091,10 @@
device = (WifiP2pDevice) message.obj;
deviceAddress = device.deviceAddress;
if (deviceAddress != null) {
- updateDeviceStatus(deviceAddress, WifiP2pDevice.AVAILABLE);
+ mPeers.updateStatus(deviceAddress, WifiP2pDevice.AVAILABLE);
if (mGroup.removeClient(deviceAddress)) {
if (DBG) logd("Removed client " + deviceAddress);
- if (!mPersistGroup && mGroup.isClientListEmpty()) {
+ if (!mAutonomousGroup && mGroup.isClientListEmpty()) {
Slog.d(TAG, "Client list empty, remove non-persistent p2p group");
mWifiNative.p2pGroupRemove(mGroup.getInterface());
}
@@ -1112,14 +1173,45 @@
break;
case WifiP2pManager.CONNECT:
WifiP2pConfig config = (WifiP2pConfig) message.obj;
- logd("Inviting device : " + config.deviceAddress);
- if (mWifiNative.p2pInvite(mGroup, config.deviceAddress)) {
- updateDeviceStatus(config.deviceAddress, WifiP2pDevice.INVITED);
- sendP2pPeersChangedBroadcast();
+ if (config.deviceAddress == null ||
+ (mSavedProvDiscDevice != null &&
+ mSavedProvDiscDevice.deviceAddress.equals(
+ config.deviceAddress))) {
+ if (config.wps.setup == WpsInfo.PBC) {
+ mWifiNative.startWpsPbc(mGroup.getInterface(), null);
+ } else {
+ if (config.wps.pin == null) {
+ String pin = mWifiNative.startWpsPinDisplay(mGroup.getInterface());
+ try {
+ Integer.parseInt(pin);
+ if (!sendShowPinReqToFrontApp(pin)) {
+ notifyInvitationSent(pin,
+ config.deviceAddress != null ?
+ config.deviceAddress : "any");
+ }
+ } catch (NumberFormatException ignore) {
+ // do nothing if pin is invalid
+ }
+ } else {
+ mWifiNative.startWpsPinKeypad(mGroup.getInterface(),
+ config.wps.pin);
+ }
+ }
+ if (config.deviceAddress != null) {
+ mPeers.updateStatus(config.deviceAddress, WifiP2pDevice.INVITED);
+ sendP2pPeersChangedBroadcast();
+ }
replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
} else {
- replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
- WifiP2pManager.ERROR);
+ logd("Inviting device : " + config.deviceAddress);
+ if (mWifiNative.p2pInvite(mGroup, config.deviceAddress)) {
+ mPeers.updateStatus(config.deviceAddress, WifiP2pDevice.INVITED);
+ sendP2pPeersChangedBroadcast();
+ replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
+ } else {
+ replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
+ WifiP2pManager.ERROR);
+ }
}
// TODO: figure out updating the status to declined when invitation is rejected
break;
@@ -1127,6 +1219,7 @@
case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT:
WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj;
+ mSavedProvDiscDevice = provDisc.device;
mSavedPeerConfig = new WifiP2pConfig();
mSavedPeerConfig.deviceAddress = provDisc.device.deviceAddress;
if (message.what == WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT) {
@@ -1137,7 +1230,9 @@
} else {
mSavedPeerConfig.wps.setup = WpsInfo.PBC;
}
- transitionTo(mUserAuthorizingJoinState);
+ if (!sendConnectNoticeToApp(mSavedProvDiscDevice, mSavedPeerConfig)) {
+ transitionTo(mUserAuthorizingJoinState);
+ }
break;
case WifiMonitor.P2P_GROUP_STARTED_EVENT:
Slog.e(TAG, "Duplicate group creation event notice, ignore");
@@ -1149,6 +1244,7 @@
}
public void exit() {
+ mSavedProvDiscDevice = null;
updateThisDevice(WifiP2pDevice.AVAILABLE);
setWifiP2pInfoOnGroupTermination();
mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
@@ -1160,6 +1256,7 @@
@Override
public void enter() {
if (DBG) logd(getName());
+
notifyInvitationReceived();
}
@@ -1174,9 +1271,10 @@
break;
case PEER_CONNECTION_USER_ACCEPT:
if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) {
- mWifiNative.startWpsPbc(null);
+ mWifiNative.startWpsPbc(mGroup.getInterface(), null);
} else {
- mWifiNative.startWpsPinKeypad(mSavedPeerConfig.wps.pin);
+ mWifiNative.startWpsPinKeypad(mGroup.getInterface(),
+ mSavedPeerConfig.wps.pin);
}
mSavedPeerConfig = null;
transitionTo(mGroupCreatedState);
@@ -1367,14 +1465,6 @@
dialog.show();
}
- private void updateDeviceStatus(String deviceAddress, int status) {
- for (WifiP2pDevice d : mPeers.getDeviceList()) {
- if (d.deviceAddress.equals(deviceAddress)) {
- d.status = status;
- }
- }
- }
-
//TODO: implement when wpa_supplicant is fixed
private int configuredNetworkId(String deviceAddress) {
return -1;
@@ -1393,29 +1483,21 @@
}
private String getDeviceName(String deviceAddress) {
- for (WifiP2pDevice d : mPeers.getDeviceList()) {
- if (d.deviceAddress.equals(deviceAddress)) {
+ WifiP2pDevice d = mPeers.get(deviceAddress);
+ if (d != null) {
return d.deviceName;
- }
}
//Treat the address as name if there is no match
return deviceAddress;
}
- private WifiP2pDevice getDeviceFromPeerList(String deviceAddress) {
- for (WifiP2pDevice d : mPeers.getDeviceList()) {
- if (d.deviceAddress.equals(deviceAddress)) {
- return d;
- }
- }
- return null;
- }
-
private void p2pConnectWithPinDisplay(WifiP2pConfig config, boolean join) {
String pin = mWifiNative.p2pConnect(config, join);
try {
Integer.parseInt(pin);
- notifyInvitationSent(pin, config.deviceAddress);
+ if (!sendShowPinReqToFrontApp(pin)) {
+ notifyInvitationSent(pin, config.deviceAddress);
+ }
} catch (NumberFormatException ignore) {
// do nothing if p2pConnect did not return a pin
}
@@ -1776,6 +1858,139 @@
return clientInfo;
}
+ /**
+ * Send detached message to dialog listener in the foreground application.
+ * @param reason
+ */
+ private void sendDetachedMsg(int reason) {
+ if (mForegroundAppMessenger == null) return;
+
+ Message msg = Message.obtain();
+ msg.what = WifiP2pManager.DIALOG_LISTENER_DETACHED;
+ msg.arg1 = reason;
+ try {
+ mForegroundAppMessenger.send(msg);
+ } catch (RemoteException e) {
+ }
+ mForegroundAppMessenger = null;
+ mForegroundAppPkgName = null;
+ }
+
+ /**
+ * Send a request to show wps pin to dialog listener in the foreground application.
+ * @param pin WPS pin
+ * @return
+ */
+ private boolean sendShowPinReqToFrontApp(String pin) {
+ if (!isForegroundApp(mForegroundAppPkgName)) {
+ sendDetachedMsg(WifiP2pManager.NOT_IN_FOREGROUND);
+ return false;
+ }
+ Message msg = Message.obtain();
+ msg.what = WifiP2pManager.SHOW_PIN_REQUESTED;
+ Bundle bundle = new Bundle();
+ bundle.putString(WifiP2pManager.WPS_PIN_BUNDLE_KEY, pin);
+ msg.setData(bundle);
+ return sendDialogMsgToFrontApp(msg);
+ }
+
+ /**
+ * Send a request to establish the connection to dialog listener in the foreground
+ * application.
+ * @param dev source device
+ * @param config
+ * @return
+ */
+ private boolean sendConnectNoticeToApp(WifiP2pDevice dev, WifiP2pConfig config) {
+ if (dev == null) {
+ dev = new WifiP2pDevice(config.deviceAddress);
+ }
+
+ if (!isForegroundApp(mForegroundAppPkgName)) {
+ if (DBG) logd("application is NOT foreground");
+ sendDetachedMsg(WifiP2pManager.NOT_IN_FOREGROUND);
+ return false;
+ }
+
+ Message msg = Message.obtain();
+ msg.what = WifiP2pManager.CONNECTION_REQUESTED;
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(WifiP2pManager.P2P_DEV_BUNDLE_KEY, dev);
+ bundle.putParcelable(WifiP2pManager.P2P_CONFIG_BUNDLE_KEY, config);
+ msg.setData(bundle);
+ return sendDialogMsgToFrontApp(msg);
+ }
+
+ /**
+ * Send dialog event message to front application's dialog listener.
+ * @param msg
+ * @return true if success.
+ */
+ private boolean sendDialogMsgToFrontApp(Message msg) {
+ try {
+ mForegroundAppMessenger.send(msg);
+ } catch (RemoteException e) {
+ mForegroundAppMessenger = null;
+ mForegroundAppPkgName = null;
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Set dialog listener application.
+ * @param m
+ * @param appPkgName if null, reset the listener.
+ * @param isReset if true, try to reset.
+ * @return
+ */
+ private boolean setDialogListenerApp(Messenger m,
+ String appPkgName, boolean isReset) {
+
+ if (mForegroundAppPkgName != null && !mForegroundAppPkgName.equals(appPkgName)) {
+ if (isForegroundApp(mForegroundAppPkgName)) {
+ // The current dialog listener is foreground app's.
+ if (DBG) logd("application is NOT foreground");
+ return false;
+ }
+ // detach an old listener.
+ sendDetachedMsg(WifiP2pManager.NOT_IN_FOREGROUND);
+ }
+
+ if (isReset) {
+ if (DBG) logd("reset dialog listener");
+ mForegroundAppMessenger = null;
+ mForegroundAppPkgName = null;
+ return true;
+ }
+
+ if (!isForegroundApp(appPkgName)) {
+ return false;
+ }
+
+ mForegroundAppMessenger = m;
+ mForegroundAppPkgName = appPkgName;
+ if (DBG) logd("set dialog listener. app=" + appPkgName);
+ return true;
+ }
+
+ /**
+ * Return true if the specified package name is foreground app's.
+ *
+ * @param pkgName application package name.
+ * @return
+ */
+ private boolean isForegroundApp(String pkgName) {
+ if (pkgName == null) return false;
+
+ List<RunningTaskInfo> tasks = mActivityMgr.getRunningTasks(1);
+ if (tasks.size() == 0) {
+ return false;
+ }
+
+ return pkgName.equals(tasks.get(0).baseActivity.getPackageName());
+ }
+
}
/**
@@ -1806,4 +2021,5 @@
mServList = new ArrayList<WifiP2pServiceInfo>();
}
}
+
}