summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt18
-rw-r--r--core/java/android/os/PowerManager.java2
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java29
-rw-r--r--core/java/android/speech/tts/ITextToSpeechService.aidl7
-rw-r--r--core/java/android/speech/tts/TextToSpeech.java138
-rw-r--r--core/java/android/speech/tts/TextToSpeechService.java130
-rw-r--r--core/java/android/util/SparseLongArray.java2
-rw-r--r--core/java/android/view/View.java15
-rw-r--r--core/java/android/view/ViewRootImpl.java2
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java216
-rw-r--r--core/java/android/widget/Editor.java56
-rw-r--r--core/java/android/widget/NumberPicker.java26
-rw-r--r--core/java/android/widget/TextView.java195
-rw-r--r--core/java/com/android/internal/view/menu/MenuItemImpl.java5
-rw-r--r--core/jni/android_view_DisplayEventReceiver.cpp42
-rw-r--r--core/res/res/drawable-hdpi/kg_add_widget.pngbin971 -> 970 bytes
-rw-r--r--core/res/res/drawable-hdpi/kg_add_widget_disabled.pngbin0 -> 1066 bytes
-rw-r--r--core/res/res/drawable-hdpi/kg_add_widget_pressed.pngbin0 -> 1004 bytes
-rw-r--r--core/res/res/drawable-ldrtl-hdpi/popup_inline_error.9.pngbin0 -> 2388 bytes
-rw-r--r--core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above.9.pngbin0 -> 2409 bytes
-rw-r--r--core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_dark.9.pngbin0 -> 940 bytes
-rw-r--r--core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_light.9.pngbin0 -> 932 bytes
-rw-r--r--core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_dark.9.pngbin0 -> 915 bytes
-rw-r--r--core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_light.9.pngbin0 -> 919 bytes
-rw-r--r--core/res/res/drawable-ldrtl-ldpi/popup_inline_error.9.pngbin0 -> 1115 bytes
-rw-r--r--core/res/res/drawable-ldrtl-ldpi/popup_inline_error_above.9.pngbin0 -> 1150 bytes
-rw-r--r--core/res/res/drawable-ldrtl-mdpi/popup_inline_error.9.pngbin0 -> 1536 bytes
-rw-r--r--core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above.9.pngbin0 -> 1546 bytes
-rw-r--r--core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_dark.9.pngbin0 -> 646 bytes
-rw-r--r--core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_light.9.pngbin0 -> 636 bytes
-rw-r--r--core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_dark.9.pngbin0 -> 626 bytes
-rw-r--r--core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_light.9.pngbin0 -> 622 bytes
-rw-r--r--core/res/res/drawable-ldrtl-xhdpi/popup_inline_error.9.pngbin0 -> 4334 bytes
-rw-r--r--core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above.9.pngbin0 -> 4335 bytes
-rw-r--r--core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_dark.9.pngbin0 -> 1264 bytes
-rw-r--r--core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_light.9.pngbin0 -> 1255 bytes
-rw-r--r--core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_dark.9.pngbin0 -> 1238 bytes
-rw-r--r--core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_light.9.pngbin0 -> 1229 bytes
-rw-r--r--core/res/res/drawable-mdpi/kg_add_widget.pngbin776 -> 788 bytes
-rw-r--r--core/res/res/drawable-mdpi/kg_add_widget_disabled.pngbin0 -> 832 bytes
-rw-r--r--core/res/res/drawable-mdpi/kg_add_widget_pressed.pngbin0 -> 809 bytes
-rw-r--r--core/res/res/drawable-xhdpi/kg_add_widget.pngbin1214 -> 1228 bytes
-rw-r--r--core/res/res/drawable-xhdpi/kg_add_widget_disabled.pngbin0 -> 1351 bytes
-rw-r--r--core/res/res/drawable-xhdpi/kg_add_widget_pressed.pngbin0 -> 1251 bytes
-rw-r--r--core/res/res/drawable/keyguard_add_widget_button.xml21
-rw-r--r--core/res/res/layout/keyguard_add_widget.xml2
-rw-r--r--core/res/res/values-af/strings.xml18
-rw-r--r--core/res/res/values-am/strings.xml18
-rw-r--r--core/res/res/values-ar/strings.xml18
-rw-r--r--core/res/res/values-be/strings.xml18
-rw-r--r--core/res/res/values-bg/strings.xml18
-rw-r--r--core/res/res/values-cs/strings.xml26
-rw-r--r--core/res/res/values-da/strings.xml18
-rw-r--r--core/res/res/values-de/strings.xml30
-rw-r--r--core/res/res/values-es-rUS/strings.xml18
-rw-r--r--core/res/res/values-et/strings.xml18
-rw-r--r--core/res/res/values-fi/strings.xml18
-rw-r--r--core/res/res/values-fr/strings.xml18
-rw-r--r--core/res/res/values-hi/strings.xml18
-rw-r--r--core/res/res/values-hr/strings.xml18
-rw-r--r--core/res/res/values-hu/strings.xml18
-rw-r--r--core/res/res/values-in/strings.xml18
-rw-r--r--core/res/res/values-it/strings.xml18
-rw-r--r--core/res/res/values-iw/strings.xml18
-rw-r--r--core/res/res/values-ko/strings.xml18
-rw-r--r--core/res/res/values-lt/strings.xml18
-rw-r--r--core/res/res/values-lv/strings.xml18
-rw-r--r--core/res/res/values-ms/strings.xml18
-rw-r--r--core/res/res/values-nb/strings.xml20
-rw-r--r--core/res/res/values-nl/strings.xml18
-rw-r--r--core/res/res/values-pl/strings.xml2
-rw-r--r--core/res/res/values-pt-rPT/strings.xml18
-rw-r--r--core/res/res/values-pt/strings.xml18
-rw-r--r--core/res/res/values-ru/strings.xml6
-rw-r--r--core/res/res/values-sl/strings.xml18
-rw-r--r--core/res/res/values-sv/strings.xml18
-rw-r--r--core/res/res/values-sw/strings.xml20
-rw-r--r--core/res/res/values-tl/strings.xml18
-rw-r--r--core/res/res/values-tr/strings.xml18
-rw-r--r--core/res/res/values-uk/strings.xml18
-rw-r--r--core/res/res/values-vi/strings.xml18
-rw-r--r--core/res/res/values-zh-rCN/strings.xml18
-rw-r--r--core/res/res/values/attrs.xml6
-rw-r--r--core/res/res/values/config.xml10
-rw-r--r--core/res/res/values/symbols.xml4
-rw-r--r--docs/html/guide/google/gcm/gcm.jd1
-rw-r--r--docs/html/guide/topics/resources/more-resources.jd4
-rw-r--r--graphics/java/android/graphics/Bitmap.java8
-rw-r--r--graphics/java/android/graphics/Path.java8
-rw-r--r--graphics/java/android/graphics/Point.java29
-rw-r--r--graphics/java/android/graphics/PointF.java25
-rw-r--r--graphics/java/android/graphics/SurfaceTexture.java2
-rw-r--r--graphics/java/android/graphics/drawable/DrawableContainer.java2
-rw-r--r--graphics/java/android/graphics/drawable/GradientDrawable.java8
-rw-r--r--media/java/android/media/AudioService.java22
-rw-r--r--packages/BackupRestoreConfirmation/res/values-ru/strings.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/ImageWallpaper.java57
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java17
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java290
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java36
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java46
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java9
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java77
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/PagedView.java2
-rw-r--r--services/java/com/android/server/InputMethodManagerService.java24
-rw-r--r--services/java/com/android/server/NetworkTimeUpdateService.java51
-rw-r--r--services/java/com/android/server/NotificationManagerService.java8
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityManagerService.java64
-rw-r--r--services/java/com/android/server/power/PowerManagerService.java13
-rw-r--r--services/java/com/android/server/wm/AppWindowAnimator.java4
-rw-r--r--services/java/com/android/server/wm/AppWindowToken.java3
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java58
-rw-r--r--services/java/com/android/server/wm/WindowStateAnimator.java9
-rw-r--r--tests/AppLaunch/Android.mk17
-rw-r--r--tests/AppLaunch/AndroidManifest.xml13
-rw-r--r--tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java216
-rw-r--r--tests/MemoryUsage/Android.mk3
-rw-r--r--tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java53
119 files changed, 2011 insertions, 791 deletions
diff --git a/api/current.txt b/api/current.txt
index a54a0bc..d597cb9 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -23497,6 +23497,24 @@ package android.util {
method public int valueAt(int);
}
+ public class SparseLongArray implements java.lang.Cloneable {
+ ctor public SparseLongArray();
+ ctor public SparseLongArray(int);
+ method public void append(int, long);
+ method public void clear();
+ method public android.util.SparseLongArray clone();
+ method public void delete(int);
+ method public long get(int);
+ method public long get(int, long);
+ method public int indexOfKey(int);
+ method public int indexOfValue(long);
+ method public int keyAt(int);
+ method public void put(int, long);
+ method public void removeAt(int);
+ method public int size();
+ method public long valueAt(int);
+ }
+
public class StateSet {
method public static java.lang.String dump(int[]);
method public static boolean isWildCard(int[]);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 4a01113..736762f 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -182,6 +182,8 @@ public final class PowerManager {
* </p><p>
* Since not all devices have proximity sensors, use {@link #isWakeLockLevelSupported}
* to determine whether this wake lock level is supported.
+ * </p><p>
+ * Cannot be used with {@link #ACQUIRE_CAUSES_WAKEUP}.
* </p>
*
* {@hide}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 6d5705d..500bb2c 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -84,7 +84,7 @@ public abstract class WallpaperService extends Service {
* tag.
*/
public static final String SERVICE_META_DATA = "android.service.wallpaper";
-
+
static final String TAG = "WallpaperService";
static final boolean DEBUG = false;
@@ -100,7 +100,6 @@ public abstract class WallpaperService extends Service {
private static final int MSG_WINDOW_MOVED = 10035;
private static final int MSG_TOUCH_EVENT = 10040;
- private Looper mCallbackLooper;
private final ArrayList<Engine> mActiveEngines
= new ArrayList<Engine>();
@@ -961,13 +960,7 @@ public abstract class WallpaperService extends Service {
IWallpaperEngineWrapper(WallpaperService context,
IWallpaperConnection conn, IBinder windowToken,
int windowType, boolean isPreview, int reqWidth, int reqHeight) {
- if (DEBUG && mCallbackLooper != null) {
- mCallbackLooper.setMessageLogging(new LogPrinter(Log.VERBOSE, TAG));
- }
- mCaller = new HandlerCaller(context,
- mCallbackLooper != null
- ? mCallbackLooper : context.getMainLooper(),
- this);
+ mCaller = new HandlerCaller(context, context.getMainLooper(), this);
mConnection = conn;
mWindowToken = windowToken;
mWindowType = windowType;
@@ -1105,13 +1098,14 @@ public abstract class WallpaperService extends Service {
mTarget = context;
}
+ @Override
public void attach(IWallpaperConnection conn, IBinder windowToken,
int windowType, boolean isPreview, int reqWidth, int reqHeight) {
new IWallpaperEngineWrapper(mTarget, conn, windowToken,
windowType, isPreview, reqWidth, reqHeight);
}
}
-
+
@Override
public void onCreate() {
super.onCreate();
@@ -1134,20 +1128,7 @@ public abstract class WallpaperService extends Service {
public final IBinder onBind(Intent intent) {
return new IWallpaperServiceWrapper(this);
}
-
- /**
- * This allows subclasses to change the thread that most callbacks
- * occur on. Currently hidden because it is mostly needed for the
- * image wallpaper (which runs in the system process and doesn't want
- * to get stuck running on that seriously in use main thread). Not
- * exposed right now because the semantics of this are not totally
- * well defined and some callbacks can still happen on the main thread).
- * @hide
- */
- public void setCallbackLooper(Looper looper) {
- mCallbackLooper = looper;
- }
-
+
/**
* Must be implemented to return a new instance of the wallpaper's engine.
* Note that multiple instances may be active at the same time, such as
diff --git a/core/java/android/speech/tts/ITextToSpeechService.aidl b/core/java/android/speech/tts/ITextToSpeechService.aidl
index ab63187..580d52c 100644
--- a/core/java/android/speech/tts/ITextToSpeechService.aidl
+++ b/core/java/android/speech/tts/ITextToSpeechService.aidl
@@ -131,6 +131,8 @@ interface ITextToSpeechService {
/**
* Notifies the engine that it should load a speech synthesis language.
*
+ * @param caller a binder representing the identity of the calling
+ * TextToSpeech object.
* @param lang ISO-3 language code.
* @param country ISO-3 country code. May be empty or null.
* @param variant Language variant. May be empty or null.
@@ -141,13 +143,14 @@ interface ITextToSpeechService {
* {@link TextToSpeech#LANG_MISSING_DATA}
* {@link TextToSpeech#LANG_NOT_SUPPORTED}.
*/
- int loadLanguage(in String lang, in String country, in String variant);
+ int loadLanguage(in IBinder caller, in String lang, in String country, in String variant);
/**
* Sets the callback that will be notified when playback of utterance from the
* given app are completed.
*
- * @param callingApp Package name for the app whose utterance the callback will handle.
+ * @param caller Instance a binder representing the identity of the calling
+ * TextToSpeech object.
* @param cb The callback.
*/
void setCallback(in IBinder caller, ITextToSpeechCallback cb);
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 9d570fc..db4febe 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -24,6 +24,7 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.media.AudioManager;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
@@ -1048,7 +1049,8 @@ public class TextToSpeech {
// the available parts.
// Note that the language is not actually set here, instead it is cached so it
// will be associated with all upcoming utterances.
- int result = service.loadLanguage(language, country, variant);
+
+ int result = service.loadLanguage(getCallerIdentity(), language, country, variant);
if (result >= LANG_AVAILABLE){
if (result < LANG_COUNTRY_VAR_AVAILABLE) {
variant = "";
@@ -1066,21 +1068,30 @@ public class TextToSpeech {
}
/**
- * Returns a Locale instance describing the language currently being used by the TextToSpeech
- * engine.
+ * Returns a Locale instance describing the language currently being used for synthesis
+ * requests sent to the TextToSpeech engine.
+ *
+ * In Android 4.2 and before (API <= 17) this function returns the language that is currently
+ * being used by the TTS engine. That is the last language set by this or any other
+ * client by a {@link TextToSpeech#setLanguage} call to the same engine.
*
- * @return language, country (if any) and variant (if any) used by the engine stored in a Locale
- * instance, or {@code null} on error.
+ * In Android versions after 4.2 this function returns the language that is currently being
+ * used for the synthesis requests sent from this client. That is the last language set
+ * by a {@link TextToSpeech#setLanguage} call on this instance.
+ *
+ * @return language, country (if any) and variant (if any) used by the client stored in a
+ * Locale instance, or {@code null} on error.
*/
public Locale getLanguage() {
return runAction(new Action<Locale>() {
@Override
- public Locale run(ITextToSpeechService service) throws RemoteException {
- String[] locStrings = service.getLanguage();
- if (locStrings != null && locStrings.length == 3) {
- return new Locale(locStrings[0], locStrings[1], locStrings[2]);
- }
- return null;
+ public Locale run(ITextToSpeechService service) {
+ /* No service call, but we're accessing mParams, hence need for
+ wrapping it as an Action instance */
+ String lang = mParams.getString(Engine.KEY_PARAM_LANGUAGE, "");
+ String country = mParams.getString(Engine.KEY_PARAM_COUNTRY, "");
+ String variant = mParams.getString(Engine.KEY_PARAM_VARIANT, "");
+ return new Locale(lang, country, variant);
}
}, null, "getLanguage");
}
@@ -1276,9 +1287,11 @@ public class TextToSpeech {
return mEnginesHelper.getEngines();
}
-
private class Connection implements ServiceConnection {
private ITextToSpeechService mService;
+
+ private OnServiceConnectedAsyncTask mOnServiceConnectedAsyncTask;
+
private final ITextToSpeechCallback.Stub mCallback = new ITextToSpeechCallback.Stub() {
@Override
public void onDone(String utteranceId) {
@@ -1305,23 +1318,59 @@ public class TextToSpeech {
}
};
+ private class OnServiceConnectedAsyncTask extends AsyncTask<Void, Void, Integer> {
+ private final ComponentName mName;
+ private final ITextToSpeechService mConnectedService;
+
+ public OnServiceConnectedAsyncTask(ComponentName name, IBinder service) {
+ mName = name;
+ mConnectedService = ITextToSpeechService.Stub.asInterface(service);
+ }
+
+ @Override
+ protected Integer doInBackground(Void... params) {
+ synchronized(mStartLock) {
+ if (isCancelled()) {
+ return null;
+ }
+
+ try {
+ mConnectedService.setCallback(getCallerIdentity(), mCallback);
+ Log.i(TAG, "Setuped connection to " + mName);
+ return SUCCESS;
+ } catch (RemoteException re) {
+ Log.e(TAG, "Error connecting to service, setCallback() failed");
+ return ERROR;
+ }
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Integer result) {
+ synchronized(mStartLock) {
+ if (mOnServiceConnectedAsyncTask == this) {
+ mOnServiceConnectedAsyncTask = null;
+ }
+
+ mServiceConnection = Connection.this;
+ mService = mConnectedService;
+
+ dispatchOnInit(result);
+ }
+ }
+ }
+
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
- Log.i(TAG, "Connected to " + name);
synchronized(mStartLock) {
- if (mServiceConnection != null) {
- // Disconnect any previous service connection
- mServiceConnection.disconnect();
- }
- mServiceConnection = this;
- mService = ITextToSpeechService.Stub.asInterface(service);
- try {
- mService.setCallback(getCallerIdentity(), mCallback);
- dispatchOnInit(SUCCESS);
- } catch (RemoteException re) {
- Log.e(TAG, "Error connecting to service, setCallback() failed");
- dispatchOnInit(ERROR);
+ Log.i(TAG, "Connected to " + name);
+
+ if (mOnServiceConnectedAsyncTask != null) {
+ mOnServiceConnectedAsyncTask.cancel(false);
}
+
+ mOnServiceConnectedAsyncTask = new OnServiceConnectedAsyncTask(name, service);
+ mOnServiceConnectedAsyncTask.execute();
}
}
@@ -1329,28 +1378,45 @@ public class TextToSpeech {
return mCallback;
}
- @Override
- public void onServiceDisconnected(ComponentName name) {
+ /**
+ * Clear connection related fields and cancel mOnServiceConnectedAsyncTask if set.
+ *
+ * @return true if we cancel mOnServiceConnectedAsyncTask in progress.
+ */
+ private boolean clearServiceConnection() {
synchronized(mStartLock) {
+ boolean result = false;
+ if (mOnServiceConnectedAsyncTask != null) {
+ result = mOnServiceConnectedAsyncTask.cancel(false);
+ mOnServiceConnectedAsyncTask = null;
+ }
+
mService = null;
// If this is the active connection, clear it
if (mServiceConnection == this) {
mServiceConnection = null;
}
+ return result;
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ Log.i(TAG, "Asked to disconnect from " + name);
+ if (clearServiceConnection()) {
+ /* We need to protect against a rare case where engine
+ * dies just after successful connection - and we process onServiceDisconnected
+ * before OnServiceConnectedAsyncTask.onPostExecute. onServiceDisconnected cancels
+ * OnServiceConnectedAsyncTask.onPostExecute and we don't call dispatchOnInit
+ * with ERROR as argument.
+ */
+ dispatchOnInit(ERROR);
}
}
public void disconnect() {
mContext.unbindService(this);
-
- synchronized (mStartLock) {
- mService = null;
- // If this is the active connection, clear it
- if (mServiceConnection == this) {
- mServiceConnection = null;
- }
-
- }
+ clearServiceConnection();
}
public <R> R runAction(Action<R> action, R errorResult, String method, boolean reconnect) {
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index d124e68..99ea64d 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -34,7 +34,6 @@ import android.text.TextUtils;
import android.util.Log;
import java.io.File;
-import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Set;
@@ -129,6 +128,8 @@ public abstract class TextToSpeechService extends Service {
*
* Can be called on multiple threads.
*
+ * Its return values HAVE to be consistent with onLoadLanguage.
+ *
* @param lang ISO-3 language code.
* @param country ISO-3 country code. May be empty or null.
* @param variant Language variant. May be empty or null.
@@ -163,6 +164,8 @@ public abstract class TextToSpeechService extends Service {
* at some point in the future.
*
* Can be called on multiple threads.
+ * In <= Android 4.2 (<= API 17) can be called on main and service binder threads.
+ * In > Android 4.2 (> API 17) can be called on main and synthesis threads.
*
* @param lang ISO-3 language code.
* @param country ISO-3 country code. May be empty or null.
@@ -256,7 +259,6 @@ public abstract class TextToSpeechService extends Service {
}
private class SynthHandler extends Handler {
-
private SpeechItem mCurrentSpeechItem = null;
public SynthHandler(Looper looper) {
@@ -275,7 +277,7 @@ public abstract class TextToSpeechService extends Service {
private synchronized SpeechItem maybeRemoveCurrentSpeechItem(Object callerIdentity) {
if (mCurrentSpeechItem != null &&
- mCurrentSpeechItem.getCallerIdentity() == callerIdentity) {
+ (mCurrentSpeechItem.getCallerIdentity() == callerIdentity)) {
SpeechItem current = mCurrentSpeechItem;
mCurrentSpeechItem = null;
return current;
@@ -296,7 +298,6 @@ public abstract class TextToSpeechService extends Service {
if (current != null) {
current.stop();
}
-
// The AudioPlaybackHandler will be destroyed by the caller.
}
@@ -306,8 +307,15 @@ public abstract class TextToSpeechService extends Service {
* Called on a service binder thread.
*/
public int enqueueSpeechItem(int queueMode, final SpeechItem speechItem) {
+ UtteranceProgressDispatcher utterenceProgress = null;
+ if (speechItem instanceof UtteranceProgressDispatcher) {
+ utterenceProgress = (UtteranceProgressDispatcher) speechItem;
+ }
+
if (!speechItem.isValid()) {
- speechItem.dispatchOnError();
+ if (utterenceProgress != null) {
+ utterenceProgress.dispatchOnError();
+ }
return TextToSpeech.ERROR;
}
@@ -325,6 +333,7 @@ public abstract class TextToSpeechService extends Service {
}
};
Message msg = Message.obtain(this, runnable);
+
// The obj is used to remove all callbacks from the given app in
// stopForApp(String).
//
@@ -334,7 +343,9 @@ public abstract class TextToSpeechService extends Service {
return TextToSpeech.SUCCESS;
} else {
Log.w(TAG, "SynthThread has quit");
- speechItem.dispatchOnError();
+ if (utterenceProgress != null) {
+ utterenceProgress.dispatchOnError();
+ }
return TextToSpeech.ERROR;
}
}
@@ -370,7 +381,7 @@ public abstract class TextToSpeechService extends Service {
}
public int stopAll() {
- // Stop the current speech item unconditionally.
+ // Stop the current speech item unconditionally .
SpeechItem current = setCurrentSpeechItem(null);
if (current != null) {
current.stop();
@@ -393,7 +404,7 @@ public abstract class TextToSpeechService extends Service {
/**
* An item in the synth thread queue.
*/
- private abstract class SpeechItem implements UtteranceProgressDispatcher {
+ private abstract class SpeechItem {
private final Object mCallerIdentity;
protected final Bundle mParams;
private final int mCallerUid;
@@ -412,6 +423,15 @@ public abstract class TextToSpeechService extends Service {
return mCallerIdentity;
}
+
+ public int getCallerUid() {
+ return mCallerUid;
+ }
+
+ public int getCallerPid() {
+ return mCallerPid;
+ }
+
/**
* Checker whether the item is valid. If this method returns false, the item should not
* be played.
@@ -436,6 +456,8 @@ public abstract class TextToSpeechService extends Service {
return playImpl();
}
+ protected abstract int playImpl();
+
/**
* Stops the speech item.
* Must not be called more than once.
@@ -452,6 +474,23 @@ public abstract class TextToSpeechService extends Service {
stopImpl();
}
+ protected abstract void stopImpl();
+
+ protected synchronized boolean isStopped() {
+ return mStopped;
+ }
+ }
+
+ /**
+ * An item in the synth thread queue that process utterance.
+ */
+ private abstract class UtteranceSpeechItem extends SpeechItem
+ implements UtteranceProgressDispatcher {
+
+ public UtteranceSpeechItem(Object caller, int callerUid, int callerPid, Bundle params) {
+ super(caller, callerUid, callerPid, params);
+ }
+
@Override
public void dispatchOnDone() {
final String utteranceId = getUtteranceId();
@@ -476,22 +515,6 @@ public abstract class TextToSpeechService extends Service {
}
}
- public int getCallerUid() {
- return mCallerUid;
- }
-
- public int getCallerPid() {
- return mCallerPid;
- }
-
- protected synchronized boolean isStopped() {
- return mStopped;
- }
-
- protected abstract int playImpl();
-
- protected abstract void stopImpl();
-
public int getStreamType() {
return getIntParam(Engine.KEY_PARAM_STREAM, Engine.DEFAULT_STREAM);
}
@@ -519,9 +542,10 @@ public abstract class TextToSpeechService extends Service {
protected float getFloatParam(String key, float defaultValue) {
return mParams == null ? defaultValue : mParams.getFloat(key, defaultValue);
}
+
}
- class SynthesisSpeechItem extends SpeechItem {
+ class SynthesisSpeechItem extends UtteranceSpeechItem {
// Never null.
private final String mText;
private final SynthesisRequest mSynthesisRequest;
@@ -658,7 +682,7 @@ public abstract class TextToSpeechService extends Service {
}
}
- private class AudioSpeechItem extends SpeechItem {
+ private class AudioSpeechItem extends UtteranceSpeechItem {
private final AudioPlaybackQueueItem mItem;
public AudioSpeechItem(Object callerIdentity, int callerUid, int callerPid,
Bundle params, Uri uri) {
@@ -684,7 +708,7 @@ public abstract class TextToSpeechService extends Service {
}
}
- private class SilenceSpeechItem extends SpeechItem {
+ private class SilenceSpeechItem extends UtteranceSpeechItem {
private final long mDuration;
public SilenceSpeechItem(Object callerIdentity, int callerUid, int callerPid,
@@ -711,6 +735,41 @@ public abstract class TextToSpeechService extends Service {
}
}
+ private class LoadLanguageItem extends SpeechItem {
+ private final String mLanguage;
+ private final String mCountry;
+ private final String mVariant;
+
+ public LoadLanguageItem(Object callerIdentity, int callerUid, int callerPid,
+ Bundle params, String language, String country, String variant) {
+ super(callerIdentity, callerUid, callerPid, params);
+ mLanguage = language;
+ mCountry = country;
+ mVariant = variant;
+ }
+
+ @Override
+ public boolean isValid() {
+ return true;
+ }
+
+ @Override
+ protected int playImpl() {
+ int result = TextToSpeechService.this.onLoadLanguage(mLanguage, mCountry, mVariant);
+ if (result == TextToSpeech.LANG_AVAILABLE ||
+ result == TextToSpeech.LANG_COUNTRY_AVAILABLE ||
+ result == TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE) {
+ return TextToSpeech.SUCCESS;
+ }
+ return TextToSpeech.ERROR;
+ }
+
+ @Override
+ protected void stopImpl() {
+ // No-op
+ }
+ }
+
@Override
public IBinder onBind(Intent intent) {
if (TextToSpeech.Engine.INTENT_ACTION_TTS_SERVICE.equals(intent.getAction())) {
@@ -822,12 +881,25 @@ public abstract class TextToSpeechService extends Service {
* are enforced.
*/
@Override
- public int loadLanguage(String lang, String country, String variant) {
+ public int loadLanguage(IBinder caller, String lang, String country, String variant) {
if (!checkNonNull(lang)) {
return TextToSpeech.ERROR;
}
+ int retVal = onIsLanguageAvailable(lang, country, variant);
+
+ if (retVal == TextToSpeech.LANG_AVAILABLE ||
+ retVal == TextToSpeech.LANG_COUNTRY_AVAILABLE ||
+ retVal == TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE) {
- return onLoadLanguage(lang, country, variant);
+ SpeechItem item = new LoadLanguageItem(caller, Binder.getCallingUid(),
+ Binder.getCallingPid(), null, lang, country, variant);
+
+ if (mSynthHandler.enqueueSpeechItem(TextToSpeech.QUEUE_ADD, item) !=
+ TextToSpeech.SUCCESS) {
+ return TextToSpeech.ERROR;
+ }
+ }
+ return retVal;
}
@Override
diff --git a/core/java/android/util/SparseLongArray.java b/core/java/android/util/SparseLongArray.java
index a08d5cb..2f7a6fe 100644
--- a/core/java/android/util/SparseLongArray.java
+++ b/core/java/android/util/SparseLongArray.java
@@ -22,8 +22,6 @@ import com.android.internal.util.ArrayUtils;
* SparseLongArrays map integers to longs. Unlike a normal array of longs,
* there can be gaps in the indices. It is intended to be more efficient
* than using a HashMap to map Integers to Longs.
- *
- * @hide
*/
public class SparseLongArray implements Cloneable {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c3b7e85..7799bb9 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -623,6 +623,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* @attr ref android.R.styleable#View_hapticFeedbackEnabled
* @attr ref android.R.styleable#View_keepScreenOn
* @attr ref android.R.styleable#View_layerType
+ * @attr ref android.R.styleable#View_layoutDirection
* @attr ref android.R.styleable#View_longClickable
* @attr ref android.R.styleable#View_minHeight
* @attr ref android.R.styleable#View_minWidth
@@ -660,6 +661,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* @attr ref android.R.styleable#View_soundEffectsEnabled
* @attr ref android.R.styleable#View_tag
* @attr ref android.R.styleable#View_textAlignment
+ * @attr ref android.R.styleable#View_textDirection
* @attr ref android.R.styleable#View_transformPivotX
* @attr ref android.R.styleable#View_transformPivotY
* @attr ref android.R.styleable#View_translationX
@@ -5854,6 +5856,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* {@link #LAYOUT_DIRECTION_RTL},
* {@link #LAYOUT_DIRECTION_INHERIT} or
* {@link #LAYOUT_DIRECTION_LOCALE}.
+ *
* @attr ref android.R.styleable#View_layoutDirection
*
* @hide
@@ -5909,6 +5912,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*
* For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
* is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
+ *
+ * @attr ref android.R.styleable#View_layoutDirection
*/
@ViewDebug.ExportedProperty(category = "layout", mapping = {
@ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
@@ -16684,6 +16689,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* {@link #TEXT_DIRECTION_RTL},
* {@link #TEXT_DIRECTION_LOCALE}
*
+ * @attr ref android.R.styleable#View_textDirection
+ *
* @hide
*/
@ViewDebug.ExportedProperty(category = "text", mapping = {
@@ -16713,6 +16720,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
* proceeds up the parent chain of the view to get the value. If there is no parent, then it will
* return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
+ *
+ * @attr ref android.R.styleable#View_textDirection
*/
public void setTextDirection(int textDirection) {
if (getRawTextDirection() != textDirection) {
@@ -16741,6 +16750,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* {@link #TEXT_DIRECTION_LTR},
* {@link #TEXT_DIRECTION_RTL},
* {@link #TEXT_DIRECTION_LOCALE}
+ *
+ * @attr ref android.R.styleable#View_textDirection
*/
public int getTextDirection() {
return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
@@ -16873,6 +16884,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* {@link #TEXT_ALIGNMENT_VIEW_START},
* {@link #TEXT_ALIGNMENT_VIEW_END}
*
+ * @attr ref android.R.styleable#View_textAlignment
+ *
* @hide
*/
@ViewDebug.ExportedProperty(category = "text", mapping = {
@@ -16936,6 +16949,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* {@link #TEXT_ALIGNMENT_TEXT_END},
* {@link #TEXT_ALIGNMENT_VIEW_START},
* {@link #TEXT_ALIGNMENT_VIEW_END}
+ *
+ * @attr ref android.R.styleable#View_textAlignment
*/
@ViewDebug.ExportedProperty(category = "text", mapping = {
@ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 325d9f5..fbaec71 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1936,6 +1936,7 @@ public final class ViewRootImpl implements ViewParent,
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "layout");
try {
host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
+ mInLayout = false;
int numViewsRequestingLayout = mLayoutRequesters.size();
if (numViewsRequestingLayout > 0) {
// requestLayout() was called during layout: unusual, but try to handle correctly
@@ -1944,6 +1945,7 @@ public final class ViewRootImpl implements ViewParent,
mLayoutRequesters.get(i).requestLayout();
}
// Now run layout one more time
+ mInLayout = true;
host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
mHandlingLayoutInLayoutRequest = false;
mLayoutRequesters.clear();
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 1500905..03288ba 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -1137,54 +1137,176 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
* @return The string representation.
*/
public static String eventTypeToString(int eventType) {
- switch (eventType) {
- case TYPE_VIEW_CLICKED:
- return "TYPE_VIEW_CLICKED";
- case TYPE_VIEW_LONG_CLICKED:
- return "TYPE_VIEW_LONG_CLICKED";
- case TYPE_VIEW_SELECTED:
- return "TYPE_VIEW_SELECTED";
- case TYPE_VIEW_FOCUSED:
- return "TYPE_VIEW_FOCUSED";
- case TYPE_VIEW_TEXT_CHANGED:
- return "TYPE_VIEW_TEXT_CHANGED";
- case TYPE_WINDOW_STATE_CHANGED:
- return "TYPE_WINDOW_STATE_CHANGED";
- case TYPE_VIEW_HOVER_ENTER:
- return "TYPE_VIEW_HOVER_ENTER";
- case TYPE_VIEW_HOVER_EXIT:
- return "TYPE_VIEW_HOVER_EXIT";
- case TYPE_NOTIFICATION_STATE_CHANGED:
- return "TYPE_NOTIFICATION_STATE_CHANGED";
- case TYPE_TOUCH_EXPLORATION_GESTURE_START:
- return "TYPE_TOUCH_EXPLORATION_GESTURE_START";
- case TYPE_TOUCH_EXPLORATION_GESTURE_END:
- return "TYPE_TOUCH_EXPLORATION_GESTURE_END";
- case TYPE_WINDOW_CONTENT_CHANGED:
- return "TYPE_WINDOW_CONTENT_CHANGED";
- case TYPE_VIEW_TEXT_SELECTION_CHANGED:
- return "TYPE_VIEW_TEXT_SELECTION_CHANGED";
- case TYPE_VIEW_SCROLLED:
- return "TYPE_VIEW_SCROLLED";
- case TYPE_ANNOUNCEMENT:
- return "TYPE_ANNOUNCEMENT";
- case TYPE_VIEW_ACCESSIBILITY_FOCUSED:
- return "TYPE_VIEW_ACCESSIBILITY_FOCUSED";
- case TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED:
- return "TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED";
- case TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY:
- return "TYPE_CURRENT_AT_GRANULARITY_MOVEMENT_CHANGED";
- case TYPE_GESTURE_DETECTION_START:
- return "TYPE_GESTURE_DETECTION_START";
- case TYPE_GESTURE_DETECTION_END:
- return "TYPE_GESTURE_DETECTION_END";
- case TYPE_TOUCH_INTERACTION_START:
- return "TYPE_TOUCH_INTERACTION_START";
- case TYPE_TOUCH_INTERACTION_END:
- return "TYPE_TOUCH_INTERACTION_END";
- default:
- return null;
+ if (eventType == TYPES_ALL_MASK) {
+ return "TYPES_ALL_MASK";
}
+ StringBuilder builder = new StringBuilder();
+ int eventTypeCount = 0;
+ while (eventType != 0) {
+ final int eventTypeFlag = 1 << Integer.numberOfTrailingZeros(eventType);
+ eventType &= ~eventTypeFlag;
+ switch (eventTypeFlag) {
+ case TYPE_VIEW_CLICKED: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_VIEW_CLICKED");
+ eventTypeCount++;
+ } break;
+ case TYPE_VIEW_LONG_CLICKED: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_VIEW_LONG_CLICKED");
+ eventTypeCount++;
+ } break;
+ case TYPE_VIEW_SELECTED: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_VIEW_SELECTED");
+ eventTypeCount++;
+ } break;
+ case TYPE_VIEW_FOCUSED: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_VIEW_FOCUSED");
+ eventTypeCount++;
+ } break;
+ case TYPE_VIEW_TEXT_CHANGED: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_VIEW_TEXT_CHANGED");
+ eventTypeCount++;
+ } break;
+ case TYPE_WINDOW_STATE_CHANGED: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_WINDOW_STATE_CHANGED");
+ eventTypeCount++;
+ } break;
+ case TYPE_VIEW_HOVER_ENTER: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_VIEW_HOVER_ENTER");
+ eventTypeCount++;
+ } break;
+ case TYPE_VIEW_HOVER_EXIT: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_VIEW_HOVER_EXIT");
+ eventTypeCount++;
+ } break;
+ case TYPE_NOTIFICATION_STATE_CHANGED: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_NOTIFICATION_STATE_CHANGED");
+ eventTypeCount++;
+ } break;
+ case TYPE_TOUCH_EXPLORATION_GESTURE_START: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_TOUCH_EXPLORATION_GESTURE_START");
+ eventTypeCount++;
+ } break;
+ case TYPE_TOUCH_EXPLORATION_GESTURE_END: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_TOUCH_EXPLORATION_GESTURE_END");
+ eventTypeCount++;
+ } break;
+ case TYPE_WINDOW_CONTENT_CHANGED: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_WINDOW_CONTENT_CHANGED");
+ eventTypeCount++;
+ } break;
+ case TYPE_VIEW_TEXT_SELECTION_CHANGED: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_VIEW_TEXT_SELECTION_CHANGED");
+ eventTypeCount++;
+ } break;
+ case TYPE_VIEW_SCROLLED: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_VIEW_SCROLLED");
+ eventTypeCount++;
+ } break;
+ case TYPE_ANNOUNCEMENT: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_ANNOUNCEMENT");
+ eventTypeCount++;
+ } break;
+ case TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_VIEW_ACCESSIBILITY_FOCUSED");
+ eventTypeCount++;
+ } break;
+ case TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED");
+ eventTypeCount++;
+ } break;
+ case TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_CURRENT_AT_GRANULARITY_MOVEMENT_CHANGED");
+ eventTypeCount++;
+ } break;
+ case TYPE_GESTURE_DETECTION_START: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_GESTURE_DETECTION_START");
+ eventTypeCount++;
+ } break;
+ case TYPE_GESTURE_DETECTION_END: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_GESTURE_DETECTION_END");
+ eventTypeCount++;
+ } break;
+ case TYPE_TOUCH_INTERACTION_START: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_TOUCH_INTERACTION_START");
+ eventTypeCount++;
+ } break;
+ case TYPE_TOUCH_INTERACTION_END: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_TOUCH_INTERACTION_END");
+ eventTypeCount++;
+ } break;
+ }
+ }
+ if (eventTypeCount > 1) {
+ builder.insert(0, '[');
+ builder.append(']');
+ }
+ return builder.toString();
}
/**
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index a086f8f..217bedb 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -309,13 +309,15 @@ public class Editor {
}
private void setErrorIcon(Drawable icon) {
- final Drawables dr = mTextView.mDrawables;
- if (dr != null) {
- mTextView.setCompoundDrawables(dr.mDrawableLeft, dr.mDrawableTop, icon,
- dr.mDrawableBottom);
- } else {
- mTextView.setCompoundDrawables(null, null, icon, null);
+ Drawables dr = mTextView.mDrawables;
+ if (dr == null) {
+ mTextView.mDrawables = dr = new Drawables();
}
+ dr.setErrorDrawable(icon, mTextView);
+
+ mTextView.resetResolvedDrawables();
+ mTextView.invalidate();
+ mTextView.requestLayout();
}
private void hideError() {
@@ -329,7 +331,7 @@ public class Editor {
}
/**
- * Returns the Y offset to make the pointy top of the error point
+ * Returns the X offset to make the pointy top of the error point
* at the middle of the error icon.
*/
private int getErrorX() {
@@ -340,8 +342,23 @@ public class Editor {
final float scale = mTextView.getResources().getDisplayMetrics().density;
final Drawables dr = mTextView.mDrawables;
- return mTextView.getWidth() - mErrorPopup.getWidth() - mTextView.getPaddingRight() -
- (dr != null ? dr.mDrawableSizeRight : 0) / 2 + (int) (25 * scale + 0.5f);
+
+ final int layoutDirection = mTextView.getLayoutDirection();
+ int errorX;
+ int offset;
+ switch (layoutDirection) {
+ default:
+ case View.LAYOUT_DIRECTION_LTR:
+ offset = - (dr != null ? dr.mDrawableSizeRight : 0) / 2 + (int) (25 * scale + 0.5f);
+ errorX = mTextView.getWidth() - mErrorPopup.getWidth() -
+ mTextView.getPaddingRight() + offset;
+ break;
+ case View.LAYOUT_DIRECTION_RTL:
+ offset = (dr != null ? dr.mDrawableSizeLeft : 0) / 2 - (int) (25 * scale + 0.5f);
+ errorX = mTextView.getPaddingLeft() + offset;
+ break;
+ }
+ return errorX;
}
/**
@@ -358,16 +375,27 @@ public class Editor {
mTextView.getCompoundPaddingBottom() - compoundPaddingTop;
final Drawables dr = mTextView.mDrawables;
- int icontop = compoundPaddingTop +
- (vspace - (dr != null ? dr.mDrawableHeightRight : 0)) / 2;
+
+ final int layoutDirection = mTextView.getLayoutDirection();
+ int height;
+ switch (layoutDirection) {
+ default:
+ case View.LAYOUT_DIRECTION_LTR:
+ height = (dr != null ? dr.mDrawableHeightRight : 0);
+ break;
+ case View.LAYOUT_DIRECTION_RTL:
+ height = (dr != null ? dr.mDrawableHeightLeft : 0);
+ break;
+ }
+
+ int icontop = compoundPaddingTop + (vspace - height) / 2;
/*
* The "2" is the distance between the point and the top edge
* of the background.
*/
final float scale = mTextView.getResources().getDisplayMetrics().density;
- return icontop + (dr != null ? dr.mDrawableHeightRight : 0) - mTextView.getHeight() -
- (int) (2 * scale + 0.5f);
+ return icontop + height - mTextView.getHeight() - (int) (2 * scale + 0.5f);
}
void createInputContentTypeIfNeeded() {
@@ -3721,7 +3749,7 @@ public class Editor {
super(v, width, height);
mView = v;
// Make sure the TextView has a background set as it will be used the first time it is
- // shown and positionned. Initialized with below background, which should have
+ // shown and positioned. Initialized with below background, which should have
// dimensions identical to the above version for this to work (and is more likely).
mPopupInlineErrorBackgroundId = getResourceId(mPopupInlineErrorBackgroundId,
com.android.internal.R.styleable.Theme_errorMessageBackground);
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 6cfeb15..74ded18 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1314,7 +1314,12 @@ public class NumberPicker extends LinearLayout {
/**
* Sets the min value of the picker.
*
- * @param minValue The min value.
+ * @param minValue The min value inclusive.
+ *
+ * <strong>Note:</strong> The length of the displayed values array
+ * set via {@link #setDisplayedValues(String[])} must be equal to the
+ * range of selectable numbers which is equal to
+ * {@link #getMaxValue()} - {@link #getMinValue()} + 1.
*/
public void setMinValue(int minValue) {
if (mMinValue == minValue) {
@@ -1347,7 +1352,12 @@ public class NumberPicker extends LinearLayout {
/**
* Sets the max value of the picker.
*
- * @param maxValue The max value.
+ * @param maxValue The max value inclusive.
+ *
+ * <strong>Note:</strong> The length of the displayed values array
+ * set via {@link #setDisplayedValues(String[])} must be equal to the
+ * range of selectable numbers which is equal to
+ * {@link #getMaxValue()} - {@link #getMinValue()} + 1.
*/
public void setMaxValue(int maxValue) {
if (mMaxValue == maxValue) {
@@ -1381,6 +1391,10 @@ public class NumberPicker extends LinearLayout {
* Sets the values to be displayed.
*
* @param displayedValues The displayed values.
+ *
+ * <strong>Note:</strong> The length of the displayed values array
+ * must be equal to the range of selectable numbers which is equal to
+ * {@link #getMaxValue()} - {@link #getMinValue()} + 1.
*/
public void setDisplayedValues(String[] displayedValues) {
if (mDisplayedValues == displayedValues) {
@@ -1391,14 +1405,6 @@ public class NumberPicker extends LinearLayout {
// Allow text entry rather than strictly numeric entry.
mInputText.setRawInputType(InputType.TYPE_CLASS_TEXT
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
- // Make sure the min, max, respect the size of the displayed
- // values. This will take care of the current value as well.
- if (getMinValue() >= displayedValues.length) {
- setMinValue(0);
- }
- if (getMaxValue() >= displayedValues.length) {
- setMaxValue(displayedValues.length - 1);
- }
} else {
mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 67cf55d..6f19f66 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -285,15 +285,144 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private TextUtils.TruncateAt mEllipsize;
static class Drawables {
+ final static int DRAWABLE_NONE = -1;
+ final static int DRAWABLE_RIGHT = 0;
+ final static int DRAWABLE_LEFT = 1;
+
final Rect mCompoundRect = new Rect();
+
Drawable mDrawableTop, mDrawableBottom, mDrawableLeft, mDrawableRight,
- mDrawableStart, mDrawableEnd;
+ mDrawableStart, mDrawableEnd, mDrawableError, mDrawableTemp;
+
int mDrawableSizeTop, mDrawableSizeBottom, mDrawableSizeLeft, mDrawableSizeRight,
- mDrawableSizeStart, mDrawableSizeEnd;
+ mDrawableSizeStart, mDrawableSizeEnd, mDrawableSizeError, mDrawableSizeTemp;
+
int mDrawableWidthTop, mDrawableWidthBottom, mDrawableHeightLeft, mDrawableHeightRight,
- mDrawableHeightStart, mDrawableHeightEnd;
+ mDrawableHeightStart, mDrawableHeightEnd, mDrawableHeightError, mDrawableHeightTemp;
+
int mDrawablePadding;
+
+ int mDrawableSaved = DRAWABLE_NONE;
+
+ public void resolveWithLayoutDirection(int layoutDirection) {
+ switch(layoutDirection) {
+ case LAYOUT_DIRECTION_RTL:
+ if (mDrawableStart != null) {
+ mDrawableRight = mDrawableStart;
+
+ mDrawableSizeRight = mDrawableSizeStart;
+ mDrawableHeightRight = mDrawableHeightStart;
+ }
+ if (mDrawableEnd != null) {
+ mDrawableLeft = mDrawableEnd;
+
+ mDrawableSizeLeft = mDrawableSizeEnd;
+ mDrawableHeightLeft = mDrawableHeightEnd;
+ }
+ break;
+
+ case LAYOUT_DIRECTION_LTR:
+ default:
+ if (mDrawableStart != null) {
+ mDrawableLeft = mDrawableStart;
+
+ mDrawableSizeLeft = mDrawableSizeStart;
+ mDrawableHeightLeft = mDrawableHeightStart;
+ }
+ if (mDrawableEnd != null) {
+ mDrawableRight = mDrawableEnd;
+
+ mDrawableSizeRight = mDrawableSizeEnd;
+ mDrawableHeightRight = mDrawableHeightEnd;
+ }
+ break;
+ }
+ applyErrorDrawableIfNeeded(layoutDirection);
+ updateDrawablesLayoutDirection(layoutDirection);
+ }
+
+ private void updateDrawablesLayoutDirection(int layoutDirection) {
+ if (mDrawableLeft != null) {
+ mDrawableLeft.setLayoutDirection(layoutDirection);
+ }
+ if (mDrawableRight != null) {
+ mDrawableRight.setLayoutDirection(layoutDirection);
+ }
+ if (mDrawableTop != null) {
+ mDrawableTop.setLayoutDirection(layoutDirection);
+ }
+ if (mDrawableBottom != null) {
+ mDrawableBottom.setLayoutDirection(layoutDirection);
+ }
+ }
+
+ public void setErrorDrawable(Drawable dr, TextView tv) {
+ if (mDrawableError != dr && mDrawableError != null) {
+ mDrawableError.setCallback(null);
+ }
+ mDrawableError = dr;
+
+ final Rect compoundRect = mCompoundRect;
+ int[] state = tv.getDrawableState();
+
+ if (mDrawableError != null) {
+ mDrawableError.setState(state);
+ mDrawableError.copyBounds(compoundRect);
+ mDrawableError.setCallback(tv);
+ mDrawableSizeError = compoundRect.width();
+ mDrawableHeightError = compoundRect.height();
+ } else {
+ mDrawableSizeError = mDrawableHeightError = 0;
+ }
+ }
+
+ private void applyErrorDrawableIfNeeded(int layoutDirection) {
+ // first restore the initial state if needed
+ switch (mDrawableSaved) {
+ case DRAWABLE_LEFT:
+ mDrawableLeft = mDrawableTemp;
+ mDrawableSizeLeft = mDrawableSizeTemp;
+ mDrawableHeightLeft = mDrawableHeightTemp;
+ break;
+ case DRAWABLE_RIGHT:
+ mDrawableRight = mDrawableTemp;
+ mDrawableSizeRight = mDrawableSizeTemp;
+ mDrawableHeightRight = mDrawableHeightTemp;
+ break;
+ case DRAWABLE_NONE:
+ default:
+ }
+ // then, if needed, assign the Error drawable to the correct location
+ if (mDrawableError != null) {
+ switch(layoutDirection) {
+ case LAYOUT_DIRECTION_RTL:
+ mDrawableSaved = DRAWABLE_LEFT;
+
+ mDrawableTemp = mDrawableLeft;
+ mDrawableSizeTemp = mDrawableSizeLeft;
+ mDrawableHeightTemp = mDrawableHeightLeft;
+
+ mDrawableLeft = mDrawableError;
+ mDrawableSizeLeft = mDrawableSizeError;
+ mDrawableHeightLeft = mDrawableHeightError;
+ break;
+ case LAYOUT_DIRECTION_LTR:
+ default:
+ mDrawableSaved = DRAWABLE_RIGHT;
+
+ mDrawableTemp = mDrawableRight;
+ mDrawableSizeTemp = mDrawableSizeRight;
+ mDrawableHeightTemp = mDrawableHeightRight;
+
+ mDrawableRight = mDrawableError;
+ mDrawableSizeRight = mDrawableSizeError;
+ mDrawableHeightRight = mDrawableHeightError;
+ break;
+ }
+ }
+ }
}
+
Drawables mDrawables;
private CharWrapper mCharWrapper;
@@ -8260,63 +8389,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return;
}
mLastLayoutDirection = layoutDirection;
- // No drawable to resolve
- if (mDrawables == null) {
- return;
- }
- // No relative drawable to resolve
- if (mDrawables.mDrawableStart == null && mDrawables.mDrawableEnd == null) {
- return;
- }
-
- Drawables dr = mDrawables;
- switch(layoutDirection) {
- case LAYOUT_DIRECTION_RTL:
- if (dr.mDrawableStart != null) {
- dr.mDrawableRight = dr.mDrawableStart;
-
- dr.mDrawableSizeRight = dr.mDrawableSizeStart;
- dr.mDrawableHeightRight = dr.mDrawableHeightStart;
- }
- if (dr.mDrawableEnd != null) {
- dr.mDrawableLeft = dr.mDrawableEnd;
- dr.mDrawableSizeLeft = dr.mDrawableSizeEnd;
- dr.mDrawableHeightLeft = dr.mDrawableHeightEnd;
- }
- break;
-
- case LAYOUT_DIRECTION_LTR:
- default:
- if (dr.mDrawableStart != null) {
- dr.mDrawableLeft = dr.mDrawableStart;
-
- dr.mDrawableSizeLeft = dr.mDrawableSizeStart;
- dr.mDrawableHeightLeft = dr.mDrawableHeightStart;
- }
- if (dr.mDrawableEnd != null) {
- dr.mDrawableRight = dr.mDrawableEnd;
-
- dr.mDrawableSizeRight = dr.mDrawableSizeEnd;
- dr.mDrawableHeightRight = dr.mDrawableHeightEnd;
- }
- break;
- }
- updateDrawablesLayoutDirection(dr, layoutDirection);
- }
-
- private void updateDrawablesLayoutDirection(Drawables dr, int layoutDirection) {
- if (dr.mDrawableLeft != null) {
- dr.mDrawableLeft.setLayoutDirection(layoutDirection);
- }
- if (dr.mDrawableRight != null) {
- dr.mDrawableRight.setLayoutDirection(layoutDirection);
- }
- if (dr.mDrawableTop != null) {
- dr.mDrawableTop.setLayoutDirection(layoutDirection);
- }
- if (dr.mDrawableBottom != null) {
- dr.mDrawableBottom.setLayoutDirection(layoutDirection);
+ // Resolve drawables
+ if (mDrawables != null) {
+ mDrawables.resolveWithLayoutDirection(layoutDirection);
}
}
@@ -8324,6 +8400,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* @hide
*/
protected void resetResolvedDrawables() {
+ super.resetResolvedDrawables();
mLastLayoutDirection = -1;
}
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index 9f7441d..7189610 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -93,6 +93,7 @@ public final class MenuItemImpl implements MenuItem {
*/
private ContextMenuInfo mMenuInfo;
+ private static String sLanguage;
private static String sPrependShortcutLabel;
private static String sEnterShortcutLabel;
private static String sDeleteShortcutLabel;
@@ -114,7 +115,9 @@ public final class MenuItemImpl implements MenuItem {
MenuItemImpl(MenuBuilder menu, int group, int id, int categoryOrder, int ordering,
CharSequence title, int showAsAction) {
- if (sPrependShortcutLabel == null) {
+ String lang = menu.getContext().getResources().getConfiguration().locale.toString();
+ if (sPrependShortcutLabel == null || !lang.equals(sLanguage)) {
+ sLanguage = lang;
// This is instantiated from the UI thread, so no chance of sync issues
sPrependShortcutLabel = menu.getContext().getResources().getString(
com.android.internal.R.string.prepend_shortcut_label);
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index 3d9d005..64fb27b 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -62,7 +62,7 @@ private:
bool mWaitingForVsync;
virtual int handleEvent(int receiveFd, int events, void* data);
- bool readLastVsyncMessage(nsecs_t* outTimestamp, int32_t* id, uint32_t* outCount);
+ bool processPendingEvents(nsecs_t* outTimestamp, int32_t* id, uint32_t* outCount);
void dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count);
void dispatchHotplug(nsecs_t timestamp, int32_t id, bool connected);
};
@@ -111,7 +111,7 @@ status_t NativeDisplayEventReceiver::scheduleVsync() {
nsecs_t vsyncTimestamp;
int32_t vsyncDisplayId;
uint32_t vsyncCount;
- readLastVsyncMessage(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount);
+ processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount);
status_t status = mReceiver.requestNextVsync();
if (status) {
@@ -141,43 +141,47 @@ int NativeDisplayEventReceiver::handleEvent(int receiveFd, int events, void* dat
nsecs_t vsyncTimestamp;
int32_t vsyncDisplayId;
uint32_t vsyncCount;
- if (!readLastVsyncMessage(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
- ALOGV("receiver %p ~ Woke up but there was no vsync pulse!", this);
- return 1; // keep the callback, did not obtain a vsync pulse
+ if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
+ ALOGV("receiver %p ~ Vsync pulse: timestamp=%lld, id=%d, count=%d",
+ this, vsyncTimestamp, vsyncDisplayId, vsyncCount);
+ mWaitingForVsync = false;
+ dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
}
- ALOGV("receiver %p ~ Vsync pulse: timestamp=%lld, id=%d, count=%d",
- this, vsyncTimestamp, vsyncDisplayId, vsyncCount);
- mWaitingForVsync = false;
-
- dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
return 1; // keep the callback
}
-bool NativeDisplayEventReceiver::readLastVsyncMessage(
+bool NativeDisplayEventReceiver::processPendingEvents(
nsecs_t* outTimestamp, int32_t* outId, uint32_t* outCount) {
+ bool gotVsync = false;
DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
ssize_t n;
while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
ALOGV("receiver %p ~ Read %d events.", this, int(n));
- while (n-- > 0) {
- const DisplayEventReceiver::Event& ev = buf[n];
- if (ev.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
+ for (ssize_t i = 0; i < n; i++) {
+ const DisplayEventReceiver::Event& ev = buf[i];
+ switch (ev.header.type) {
+ case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
+ // Later vsync events will just overwrite the info from earlier
+ // ones. That's fine, we only care about the most recent.
+ gotVsync = true;
*outTimestamp = ev.header.timestamp;
*outId = ev.header.id;
*outCount = ev.vsync.count;
- return true; // stop at last vsync in the buffer
- }
-
- if (ev.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) {
+ break;
+ case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
dispatchHotplug(ev.header.timestamp, ev.header.id, ev.hotplug.connected);
+ break;
+ default:
+ ALOGW("receiver %p ~ ignoring unknown event type %#x", this, ev.header.type);
+ break;
}
}
}
if (n < 0) {
ALOGW("Failed to get events from display event receiver, status=%d", status_t(n));
}
- return false;
+ return gotVsync;
}
void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count) {
diff --git a/core/res/res/drawable-hdpi/kg_add_widget.png b/core/res/res/drawable-hdpi/kg_add_widget.png
index 723d97a..68971a5 100644
--- a/core/res/res/drawable-hdpi/kg_add_widget.png
+++ b/core/res/res/drawable-hdpi/kg_add_widget.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/kg_add_widget_disabled.png b/core/res/res/drawable-hdpi/kg_add_widget_disabled.png
new file mode 100644
index 0000000..f24cf642
--- /dev/null
+++ b/core/res/res/drawable-hdpi/kg_add_widget_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/kg_add_widget_pressed.png b/core/res/res/drawable-hdpi/kg_add_widget_pressed.png
new file mode 100644
index 0000000..55112ca
--- /dev/null
+++ b/core/res/res/drawable-hdpi/kg_add_widget_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/popup_inline_error.9.png b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error.9.png
new file mode 100644
index 0000000..8b43f4e
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above.9.png b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above.9.png
new file mode 100644
index 0000000..20e9002
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_dark.9.png b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_dark.9.png
new file mode 100644
index 0000000..b5f397c
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_light.9.png b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_light.9.png
new file mode 100644
index 0000000..a04d695
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_dark.9.png b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_dark.9.png
new file mode 100644
index 0000000..8567b1f
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_light.9.png b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_light.9.png
new file mode 100644
index 0000000..7d1754c
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-ldpi/popup_inline_error.9.png b/core/res/res/drawable-ldrtl-ldpi/popup_inline_error.9.png
new file mode 100644
index 0000000..d2efb62
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-ldpi/popup_inline_error.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-ldpi/popup_inline_error_above.9.png b/core/res/res/drawable-ldrtl-ldpi/popup_inline_error_above.9.png
new file mode 100644
index 0000000..04d200d
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-ldpi/popup_inline_error_above.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/popup_inline_error.9.png b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error.9.png
new file mode 100644
index 0000000..27e8d4f
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above.9.png b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above.9.png
new file mode 100644
index 0000000..4ae2b91
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_dark.9.png b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_dark.9.png
new file mode 100644
index 0000000..8cc3b69
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_light.9.png b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_light.9.png
new file mode 100644
index 0000000..7a84200
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_dark.9.png b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_dark.9.png
new file mode 100644
index 0000000..8fc2e2e
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_light.9.png b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_light.9.png
new file mode 100644
index 0000000..687a691
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error.9.png b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error.9.png
new file mode 100644
index 0000000..db91a56
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above.9.png b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above.9.png
new file mode 100644
index 0000000..90820b5
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_dark.9.png b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_dark.9.png
new file mode 100644
index 0000000..5989975
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_light.9.png b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_light.9.png
new file mode 100644
index 0000000..3b3f87d
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_dark.9.png b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_dark.9.png
new file mode 100644
index 0000000..75baba2
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_light.9.png b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_light.9.png
new file mode 100644
index 0000000..6c0203d
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/kg_add_widget.png b/core/res/res/drawable-mdpi/kg_add_widget.png
index 5b0a5a4..136ae17 100644
--- a/core/res/res/drawable-mdpi/kg_add_widget.png
+++ b/core/res/res/drawable-mdpi/kg_add_widget.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/kg_add_widget_disabled.png b/core/res/res/drawable-mdpi/kg_add_widget_disabled.png
new file mode 100644
index 0000000..02e0f0e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/kg_add_widget_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/kg_add_widget_pressed.png b/core/res/res/drawable-mdpi/kg_add_widget_pressed.png
new file mode 100644
index 0000000..34a7aaa
--- /dev/null
+++ b/core/res/res/drawable-mdpi/kg_add_widget_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/kg_add_widget.png b/core/res/res/drawable-xhdpi/kg_add_widget.png
index 9c84de2..ca48be2 100644
--- a/core/res/res/drawable-xhdpi/kg_add_widget.png
+++ b/core/res/res/drawable-xhdpi/kg_add_widget.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/kg_add_widget_disabled.png b/core/res/res/drawable-xhdpi/kg_add_widget_disabled.png
new file mode 100644
index 0000000..55fa1ac
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/kg_add_widget_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/kg_add_widget_pressed.png b/core/res/res/drawable-xhdpi/kg_add_widget_pressed.png
new file mode 100644
index 0000000..4b86727
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/kg_add_widget_pressed.png
Binary files differ
diff --git a/core/res/res/drawable/keyguard_add_widget_button.xml b/core/res/res/drawable/keyguard_add_widget_button.xml
new file mode 100644
index 0000000..c26f81d
--- /dev/null
+++ b/core/res/res/drawable/keyguard_add_widget_button.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true" android:drawable="@drawable/kg_add_widget_pressed" />
+ <item android:state_enabled="false" android:drawable="@drawable/kg_add_widget_disabled" />
+ <item android:drawable="@drawable/kg_add_widget" />
+</selector>
diff --git a/core/res/res/layout/keyguard_add_widget.xml b/core/res/res/layout/keyguard_add_widget.xml
index db166ac..d043fdb 100644
--- a/core/res/res/layout/keyguard_add_widget.xml
+++ b/core/res/res/layout/keyguard_add_widget.xml
@@ -36,7 +36,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="24dp"
- android:src="@drawable/kg_add_widget"
+ android:src="@drawable/keyguard_add_widget_button"
android:contentDescription="@string/keyguard_accessibility_add_widget"/>
</FrameLayout>
</com.android.internal.policy.impl.keyguard.KeyguardWidgetFrame>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 83cd587..4d5a019 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"weke"</string>
<string name="year" msgid="4001118221013892076">"jaar"</string>
<string name="years" msgid="6881577717993213522">"jaar"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 sekonde"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sekondes"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 minuut"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minute"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 uur"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ure"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Videoprobleem"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Hierdie video is nie geldig vir stroming na hierdie toestel nie."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Kan nie hierdie video speel nie."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 550e111..c929f96 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"ሳምንቶች"</string>
<string name="year" msgid="4001118221013892076">"ዓመት"</string>
<string name="years" msgid="6881577717993213522">"ዓመታት"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 ሰከንድ"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> ሰከንዶች"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 ደቂቃ"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> ደቂቃዎች"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 ሰዓት"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ሰዓታት"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"የቪዲዮ ችግር"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"ይቅርታ፣ ይህ ቪዲዮ በዚህ መሣሪያ ለመልቀቅ ትክክል አይደለም።"</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"ይሄን ቪዲዮ ማጫወት አልተቻለም።"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index bd762e9..7b40a26 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"أسابيع"</string>
<string name="year" msgid="4001118221013892076">"سنة"</string>
<string name="years" msgid="6881577717993213522">"أعوام"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"ثانية واحدة"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> من الثواني"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"دقيقة واحدة"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> من الدقائق"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"ساعة واحدة"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> من الساعات"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"مشكلة في الفيديو"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"عذرًا، هذا الفيديو غير صالح للبث على هذا الجهاز."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"لا يمكنك تشغيل هذا الفيديو."</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index d42ec98..adbcace 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"тыд."</string>
<string name="year" msgid="4001118221013892076">"год"</string>
<string name="years" msgid="6881577717993213522">"г."</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 секунда"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> с"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 хвіліна"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> хв."</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 гадзіна"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> гадз."</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Праблема з відэа"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Відэа не падыходзіць для патокавай перадачы на ​​гэту прыладу."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Немагчыма прайграць гэта відэа."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index d6e8ff8..a3d9e76 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"седмици"</string>
<string name="year" msgid="4001118221013892076">"година"</string>
<string name="years" msgid="6881577717993213522">"години"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 секунда"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> секунди"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 минута"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> минути"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 час"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> часа"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Проблем с видеоклипа"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Този видеоклип не е валиден за поточно предаване към това устройство."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Този видеоклип не може да се пусне."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 87129e7..5710c25 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -362,7 +362,7 @@
<string name="permlab_deletePackages" msgid="184385129537705938">"smazání aplikací"</string>
<string name="permdesc_deletePackages" msgid="7411480275167205081">"Umožňuje aplikaci smazat balíčky Android. Škodlivé aplikace mohou toto oprávnění použít ke smazání důležitých aplikací."</string>
<string name="permlab_clearAppUserData" msgid="274109191845842756">"smazání dat ostatních aplikací"</string>
- <string name="permdesc_clearAppUserData" msgid="4625323684125459488">"Umožňuje aplikaci smazat data uživatele."</string>
+ <string name="permdesc_clearAppUserData" msgid="4625323684125459488">"Umožňuje aplikaci vymazat data uživatele."</string>
<string name="permlab_deleteCacheFiles" msgid="3128665571837408675">"smazání mezipaměti ostatních aplikací"</string>
<string name="permdesc_deleteCacheFiles" msgid="3812998599006730196">"Umožňuje aplikaci smazat soubory v mezipaměti."</string>
<string name="permlab_getPackageSize" msgid="7472921768357981986">"výpočet místa pro ukládání aplikací"</string>
@@ -446,7 +446,7 @@
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Povoluje aplikaci ovládat základní funkce displejů přes Wi-Fi."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"změna vašeho nastavení zvuku"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Umožňuje aplikaci změnit globální nastavení zvuku, například hlasitost či reproduktor pro výstup zvuku."</string>
- <string name="permlab_recordAudio" msgid="3876049771427466323">"nahrání zvuku"</string>
+ <string name="permlab_recordAudio" msgid="3876049771427466323">"nahrávání zvuku"</string>
<string name="permdesc_recordAudio" msgid="4906839301087980680">"Umožňuje aplikaci zaznamenat zvuk pomocí mikrofonu. Toto oprávnění umožňuje aplikaci kdykoliv zaznamenat zvuk bez vašeho svolení."</string>
<string name="permlab_camera" msgid="3616391919559751192">"pořizování fotografií a videí"</string>
<string name="permdesc_camera" msgid="8497216524735535009">"Umožňuje aplikaci pořizovat fotografie a videa pomocí fotoaparátu. Toto oprávnění umožňuje aplikaci používat fotoaparát kdykoliv i bez vašeho svolení."</string>
@@ -587,8 +587,8 @@
<string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"testování přístupu do chráněného úložiště"</string>
<string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Umožňuje aplikaci testovat oprávnění pro úložiště USB, které bude dostupné v budoucích zařízeních."</string>
<string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Umožňuje aplikaci testovat oprávnění pro kartu SD, která bude dostupná v budoucích zařízeních."</string>
- <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"úprava nebo smazání obsahu v úložišti USB"</string>
- <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"úprava nebo smazání obsahu na kartě SD"</string>
+ <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"úprava nebo mazání obsahu v úložišti USB"</string>
+ <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"úprava nebo mazání obsahu na kartě SD"</string>
<string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"Umožňuje aplikaci zapisovat do úložiště USB."</string>
<string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Umožňuje aplikaci zapisovat na kartu SD."</string>
<string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"Upravit/smazat interní úlož."</string>
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"týd."</string>
<string name="year" msgid="4001118221013892076">"rokem"</string>
<string name="years" msgid="6881577717993213522">"lety"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 sekunda"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> s"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 minuta"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> min"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 hodina"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> h"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Potíže s videem"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Toto video nelze přenášet datovým proudem do tohoto zařízení."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Toto video nelze přehrát."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index c5e15d1..c139fae 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"uger"</string>
<string name="year" msgid="4001118221013892076">"år"</string>
<string name="years" msgid="6881577717993213522">"år"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"Ét sekund"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sekunder"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"Ét minut"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutter"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"Én time"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> timer"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Videoproblem"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Denne video kan ikke streames på denne enhed."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Videoen kan ikke afspilles."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 0688951..a2082a2 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -121,7 +121,7 @@
<string name="httpErrorRedirectLoop" msgid="8679596090392779516">"Die Seite enthält zu viele Server-Redirects."</string>
<string name="httpErrorUnsupportedScheme" msgid="5015730812906192208">"Das Protokoll wird nicht unterstützt."</string>
<string name="httpErrorFailedSslHandshake" msgid="96549606000658641">"Es konnte keine sichere Verbindung hergestellt werden."</string>
- <string name="httpErrorBadUrl" msgid="3636929722728881972">"Die Seite kann nicht geöffnet werden, da die URL ungültig ist."</string>
+ <string name="httpErrorBadUrl" msgid="3636929722728881972">"Die Seite kann nicht geöffnet werden, weil die URL ungültig ist."</string>
<string name="httpErrorFile" msgid="2170788515052558676">"Auf die Datei konnte nicht zugegriffen werden."</string>
<string name="httpErrorFileNotFound" msgid="6203856612042655084">"Die angeforderte Datei wurde nicht gefunden."</string>
<string name="httpErrorTooManyRequests" msgid="1235396927087188253">"Es werden zurzeit zu viele Anfragen verarbeitet. Versuchen Sie es später erneut."</string>
@@ -382,8 +382,8 @@
<string name="permlab_diagnostic" msgid="8076743953908000342">"Lese-/Schreibberechtigung für zu Diagnosegruppe gehörige Elemente"</string>
<string name="permdesc_diagnostic" msgid="6608295692002452283">"Ermöglicht der App, alle Elemente in der Diagnosegruppe zu lesen und zu bearbeiten, etwa Dateien in \"/dev\". Dies könnte eine potenzielle Gefährdung für die Stabilität und Sicherheit des Systems darstellen und sollte NUR für hardwarespezifische Diagnosen des Herstellers oder Mobilfunkanbieters verwendet werden."</string>
<string name="permlab_changeComponentState" msgid="6335576775711095931">"App-Komponenten aktivieren oder deaktivieren"</string>
- <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"Ermöglicht der App, Komponenten einer anderen App zu aktivieren oder zu deaktivieren. Schädliche Apps können so wichtige Tabletfunktionen deaktivieren. Bei der Erteilung dieser Berechtigung ist Vorsicht geboten, da die App-Komponenten unbrauchbar, inkonsistent oder instabil werden können."</string>
- <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"Ermöglicht der App, Komponenten einer anderen App zu aktivieren oder zu deaktivieren. Schädliche Apps können so wichtige Telefonfunktionen deaktivieren. Bei der Erteilung dieser Berechtigung ist Vorsicht geboten, da die App-Komponenten unbrauchbar, inkonsistent oder instabil werden können."</string>
+ <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"Ermöglicht der App, Komponenten einer anderen App zu aktivieren oder zu deaktivieren. Schädliche Apps können so wichtige Tabletfunktionen deaktivieren. Bei der Erteilung dieser Berechtigung ist Vorsicht geboten, weil die App-Komponenten unbrauchbar, inkonsistent oder instabil werden können."</string>
+ <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"Ermöglicht der App, Komponenten einer anderen App zu aktivieren oder zu deaktivieren. Schädliche Apps können so wichtige Telefonfunktionen deaktivieren. Bei der Erteilung dieser Berechtigung ist Vorsicht geboten, weil die App-Komponenten unbrauchbar, inkonsistent oder instabil werden können."</string>
<string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"Berechtigungen erteilen oder entziehen"</string>
<string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Hiermit kann eine App sich selbst oder anderen Apps bestimmte Berechtigungen erteilen oder entziehen. Schädliche Apps können hierdurch Zugriff auf Funktionen erlangen, den Sie nicht gewährt haben."</string>
<string name="permlab_setPreferredApplications" msgid="8463181628695396391">"Bevorzugte Apps festlegen"</string>
@@ -398,8 +398,8 @@
<string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"Ermöglicht der App, sich selbst zu starten, sobald das System gebootet wurde. Dadurch kann es länger dauern, bis das Tablet gestartet wird, und durch die ständige Aktivität der App wird die gesamte Leistung des Tablets beeinträchtigt."</string>
<string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"Ermöglicht der App, sich selbst zu starten, sobald das System gebootet wurde. Dadurch kann es länger dauern, bis das Telefon gestartet wird, und durch die ständige Aktivität der App wird die gesamte Leistung des Telefons beeinträchtigt."</string>
<string name="permlab_broadcastSticky" msgid="7919126372606881614">"dauerhaften Broadcast senden"</string>
- <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Ermöglicht der App, dauerhafte Broadcasts zu senden, die auch nach Ende des Broadcasts bestehen bleiben. Ein zu intensiver Einsatz kann das Tablet langsam oder instabil machen, da zu viel Arbeitsspeicher belegt wird."</string>
- <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Ermöglicht der App, dauerhafte Broadcasts zu senden, die auch nach Ende des Broadcasts bestehen bleiben. Ein zu intensiver Einsatz kann das Telefon langsam oder instabil machen, da zu viel Arbeitsspeicher belegt wird."</string>
+ <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Ermöglicht der App, weiluerhafte Broadcasts zu senden, die auch nach Ende des Broadcasts bestehen bleiben. Ein zu intensiver Einsatz kann das Tablet langsam oder instabil machen, weil zu viel Arbeitsspeicher belegt wird."</string>
+ <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Ermöglicht der App, weiluerhafte Broadcasts zu senden, die auch nach Ende des Broadcasts bestehen bleiben. Ein zu intensiver Einsatz kann das Telefon langsam oder instabil machen, weil zu viel Arbeitsspeicher belegt wird."</string>
<string name="permlab_readContacts" msgid="8348481131899886131">"Kontakte lesen"</string>
<string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Ermöglicht der App, Daten zu den auf Ihrem Tablet gespeicherten Kontakten zu lesen, einschließlich der Häufigkeit, mit der Sie bestimmte Personen angerufen, diesen E-Mails gesendet oder anderweitig mit ihnen kommuniziert haben. Die Berechtigung erlaubt Apps, Ihre Kontaktdaten zu speichern, und schädliche Apps können Kontaktdaten ohne Ihr Wissen weiterleiten."</string>
<string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Ermöglicht der App, Daten zu den auf Ihrem Telefon gespeicherten Kontakten zu lesen, einschließlich der Häufigkeit, mit der Sie bestimmte Personen angerufen, diesen E-Mails gesendet oder anderweitig mit ihnen kommuniziert haben. Die Berechtigung erlaubt Apps, Ihre Kontaktdaten zu speichern, und schädliche Apps können Kontaktdaten ohne Ihr Wissen weiterleiten."</string>
@@ -485,7 +485,7 @@
<string name="permlab_hardware_test" msgid="4148290860400659146">"Hardware testen"</string>
<string name="permdesc_hardware_test" msgid="6597964191208016605">"Ermöglicht der App, verschiedene Peripherie-Geräte zu Hardware-Testzwecken zu steuern"</string>
<string name="permlab_callPhone" msgid="3925836347681847954">"Telefonnummern direkt anrufen"</string>
- <string name="permdesc_callPhone" msgid="3740797576113760827">"Ermöglicht der App, Telefonnummern zu wählen, ohne dass ein Eingreifen Ihrerseits nötig ist. Dies kann zu unerwarteten Kosten und Anrufen führen. Beachten Sie, dass die App keine Notrufnummern wählen kann. Schädliche Apps verursachen möglicherweise Kosten, indem sie Anrufe ohne Ihre Bestätigung tätigen."</string>
+ <string name="permdesc_callPhone" msgid="3740797576113760827">"Ermöglicht der App, ohne Ihr Eingreifen Telefonnummern zu wählen. Dies kann zu unerwarteten Kosten und Anrufen führen. Beachten Sie, dass die App keine Notrufnummern wählen kann. Schädliche Apps verursachen möglicherweise Kosten, indem sie Anrufe ohne Ihre Bestätigung tätigen."</string>
<string name="permlab_callPrivileged" msgid="4198349211108497879">"Alle Telefonnummern direkt anrufen"</string>
<string name="permdesc_callPrivileged" msgid="1689024901509996810">"Ermöglicht der App, ohne Ihr Eingreifen eine beliebige Telefonnummer zu wählen, einschließlich Notrufnummern. Schädliche Apps können so unnötige und illegale Notrufe tätigen."</string>
<string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"CDMA-Tablet-Einrichtung direkt starten"</string>
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"Wochen"</string>
<string name="year" msgid="4001118221013892076">"Jahr"</string>
<string name="years" msgid="6881577717993213522">"Jahre"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 Sekunde"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> Sekunden"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 Minute"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> Minuten"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 Stunde"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> Stunden"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Videoprobleme"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Dieses Video ist nicht für Streaming auf diesem Gerät gültig."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Video kann nicht wiedergegeben werden."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index ce6ec13..79163fa 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"semanas"</string>
<string name="year" msgid="4001118221013892076">"año"</string>
<string name="years" msgid="6881577717993213522">"años"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 segundo"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> segundos"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 minuto"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutos"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 hora"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> horas"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problemas de video"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"No es posible transmitir este video al dispositivo."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"No se puede reproducir el video."</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 1cb4e43..bc6c5dc 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"nädalat"</string>
<string name="year" msgid="4001118221013892076">"aasta"</string>
<string name="years" msgid="6881577717993213522">"aastat"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 sekund"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sekundit"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 minut"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutit"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 tund"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> tundi"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Probleem videoga"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"See video ei sobi voogesituseks selles seadmes."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Videot ei saa esitada."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 6a4b3af..8acf9c6 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"viikkoa"</string>
<string name="year" msgid="4001118221013892076">"vuosi"</string>
<string name="years" msgid="6881577717993213522">"vuotta"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 sekunti"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sekuntia"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 minuutti"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minuuttia"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 tunti"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> tuntia"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Video-ongelma"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Tätä videota ei voi suoratoistaa tällä laitteella."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Videota ei voida toistaa."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 84948f4..bb39c1e 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"semaines"</string>
<string name="year" msgid="4001118221013892076">"année"</string>
<string name="years" msgid="6881577717993213522">"années"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 seconde"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> secondes"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 minute"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutes"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 heure"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> heures"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problème vidéo"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Impossible de lire cette vidéo en streaming sur cet appareil."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Impossible de lire la vidéo."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 18e7469..d2234ec 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"सप्ताह"</string>
<string name="year" msgid="4001118221013892076">"वर्ष"</string>
<string name="years" msgid="6881577717993213522">"वर्ष"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 सेकंड"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> सेकंड"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 मिनट"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> मिनट"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 घंटा"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> घंटे"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"वीडियो समस्‍याएं"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"यह वीडियो इस उपकरण पर स्ट्रीमिंग के लिए मान्‍य नहीं है."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"यह वीडियो नहीं चलाया जा सकता."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 423e537..5964a32 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"tjedna"</string>
<string name="year" msgid="4001118221013892076">"godina"</string>
<string name="years" msgid="6881577717993213522">"godina"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 sekundu"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> s"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 minutu"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> min"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 sat"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> h"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problem s videozapisom"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Ovaj videozapis nije valjan za streaming na ovaj uređaj."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Ovaj videozapis nije moguće reproducirati."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 3fc75e4..7e0035b 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"hét"</string>
<string name="year" msgid="4001118221013892076">"év"</string>
<string name="years" msgid="6881577717993213522">"év"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 másodperc"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> másodperc"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 perc"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> perc"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 óra"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> óra"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Videoprobléma"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Ezt a videót nem lehet megjeleníteni ezen az eszközön."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Nem lehet lejátszani ezt a videót."</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 7b22f97..a4c6bc2 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"minggu"</string>
<string name="year" msgid="4001118221013892076">"tahun"</string>
<string name="years" msgid="6881577717993213522">"tahun"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 detik"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> detik"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 menit"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> menit"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 jam"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> jam"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Masalah video"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Video ini tidak valid untuk pengaliran ke perangkat ini."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Tidak dapat memutar video ini."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 4ed4994..ab57809 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"settimane"</string>
<string name="year" msgid="4001118221013892076">"anno"</string>
<string name="years" msgid="6881577717993213522">"anni"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 secondo"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> secondi"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 minuto"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minuti"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 ora"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ore"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problemi video"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Questo video non è valido per lo streaming su questo dispositivo."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Impossibile riprodurre il video."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 0150000..76a2daa 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"שבועות"</string>
<string name="year" msgid="4001118221013892076">"שנה"</string>
<string name="years" msgid="6881577717993213522">"שנים"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"שנייה אחת"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> שניות"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"דקה אחת"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> דקות"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"שעה אחת"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> שעות"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"בעיה בווידאו"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"סרטון זה אינו חוקי להעברה כמדיה זורמת למכשיר זה."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"לא ניתן להפעיל סרטון זה."</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index f2c596c..ff0f5d4 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"주"</string>
<string name="year" msgid="4001118221013892076">"년"</string>
<string name="years" msgid="6881577717993213522">"년"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1초"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g>초"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1분"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g>분"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1시간"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g>시간"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"영상 문제"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"이 기기로 스트리밍하기에 적합하지 않은 동영상입니다."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"동영상을 재생할 수 없습니다."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 875b122..0b25abe 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"sav."</string>
<string name="year" msgid="4001118221013892076">"metai"</string>
<string name="years" msgid="6881577717993213522">"metai"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 sek."</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sek."</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 min."</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> min."</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 val."</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> val."</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Vaizdo įrašo problema"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Šis vaizdo įrašas netinkamas srautiniu būdu perduoti į šį įrenginį."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Negalima paleisti šio vaizdo įrašo."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 4f7b6a1..3ef2f61 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"nedēļas"</string>
<string name="year" msgid="4001118221013892076">"gads"</string>
<string name="years" msgid="6881577717993213522">"gadi"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 s"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> s"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 min"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> min"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 h"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> h"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Video problēma"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Šis video nav derīgs straumēšanai uz šo ierīci."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Nevar atskaņot šo video."</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index b051f25..4346a39 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"minggu"</string>
<string name="year" msgid="4001118221013892076">"tahun"</string>
<string name="years" msgid="6881577717993213522">"tahun"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 saat"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> saat"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 minit"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minit"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 jam"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> jam"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Masalah video"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Maaf, video ini tidak sah untuk penstriman ke peranti ini."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Tidak dapat mainkan video ini."</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 9c2b82e..a5e473b 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -571,7 +571,7 @@
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Lar appen deaktivere tastelåsen og eventuell tilknyttet passordsikkerhet. Et eksempel er at telefonen deaktiverer tastelåsen når du mottar et innkommende anrop, og deretter aktiverer tastelåsen igjen når samtalen er ferdig."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"lese synkroniseringsinnstillinger"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Lar appen lese synkroniseringsinnstillingene for en konto. For eksempel kan den finne ut om Personer-appen er synkronisert med en konto."</string>
- <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"slår synkronisering av og på"</string>
+ <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"slå synkronisering av og på"</string>
<string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Lar appen endre synkroniseringsinnstillingene for en konto. For eksempel kan dette brukes til å synkronisere Personer-appen med en konto."</string>
<string name="permlab_readSyncStats" msgid="7396577451360202448">"lese synkroniseringsstatistikk"</string>
<string name="permdesc_readSyncStats" msgid="1510143761757606156">"Lar appen lese synkroniseringsstatistikk for en konto, inkludert loggen over synkroniseringsaktiviteter og hvor mye data som er synkronisert."</string>
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"uker"</string>
<string name="year" msgid="4001118221013892076">"år"</string>
<string name="years" msgid="6881577717993213522">"år"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"Ett sekund"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sekunder"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"Ett minutt"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutter"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"Én time"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> timer"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Videoproblem"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Denne videoen er ikke gyldig for direkteavspilling på enheten."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Kan ikke spille av denne videoen."</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 103c298..ec6d073 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"weken"</string>
<string name="year" msgid="4001118221013892076">"jaar"</string>
<string name="years" msgid="6881577717993213522">"jaren"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 seconde"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> seconden"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 minuut"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minuten"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 uur"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> uur"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Probleem met video"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Deze video kan niet worden gestreamd naar dit apparaat."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Deze video kan niet worden afgespeeld."</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 3c21f45..281b782 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -762,7 +762,7 @@
<string name="lockscreen_password_wrong" msgid="5737815393253165301">"Spróbuj ponownie."</string>
<string name="faceunlock_multiple_failures" msgid="754137583022792429">"Przekroczono maksymalną liczbę prób rozpoznania twarzy."</string>
<string name="lockscreen_plugged_in" msgid="8057762828355572315">"Ładowanie (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
- <string name="lockscreen_charged" msgid="321635745684060624">"Naładowana"</string>
+ <string name="lockscreen_charged" msgid="321635745684060624">"Naładowany"</string>
<string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
<string name="lockscreen_low_battery" msgid="1482873981919249740">"Podłącz ładowarkę."</string>
<string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Brak karty SIM"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 3e4ebde..50adccc 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"semanas"</string>
<string name="year" msgid="4001118221013892076">"ano"</string>
<string name="years" msgid="6881577717993213522">"anos"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 segundo"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> segundos"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 minuto"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutos"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 hora"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> horas"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problema com o vídeo"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Este vídeo não é válido para transmissão em fluxo contínuo neste aparelho."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Não é possível reproduzir este vídeo."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 23feb25..1ba453c 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"semanas"</string>
<string name="year" msgid="4001118221013892076">"ano"</string>
<string name="years" msgid="6881577717993213522">"anos"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"Um segundo"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> segundos"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"Um minuto"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutos"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"Uma hora"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> horas"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problema com o vídeo"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Este vídeo não é válido para transmissão neste dispositivo."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Não é possível reproduzir este vídeo."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 2501dc7..906217d 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -182,7 +182,7 @@
<string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Доступ к устройствам и сетям через Bluetooth."</string>
<string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Настройки звука"</string>
<string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Изменение настроек звука."</string>
- <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Воздействие на батарею"</string>
+ <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Батарея"</string>
<string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Использование функций, приводящих к быстрой разрядке батареи."</string>
<string name="permgrouplab_calendar" msgid="5863508437783683902">"Календарь"</string>
<string name="permgroupdesc_calendar" msgid="5777534316982184416">"Прямой доступ к календарю и мероприятиям."</string>
@@ -1147,7 +1147,7 @@
<string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"НОВОЕ: "</font></string>
<string name="perms_description_app" msgid="5139836143293299417">"Источник: <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
<string name="no_permissions" msgid="7283357728219338112">"Не требуется разрешений"</string>
- <string name="perm_costs_money" msgid="4902470324142151116">"за это может взиматься плата"</string>
+ <string name="perm_costs_money" msgid="4902470324142151116">"это может стоить вам денег!"</string>
<string name="usb_storage_activity_title" msgid="4465055157209648641">"Запоминающее устройство USB"</string>
<string name="usb_storage_title" msgid="5901459041398751495">"USB-подключение установлено"</string>
<string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Устройство подключено к компьютеру через USB-порт. Нажмите кнопку ниже, чтобы скопировать файлы с компьютера на USB-накопитель Android-устройства."</string>
@@ -1377,7 +1377,7 @@
<string name="fingerprints" msgid="4516019619850763049">"Отпечатки:"</string>
<string name="sha256_fingerprint" msgid="4391271286477279263">"Отпечаток SHA-256:"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"Отпечаток SHA-1:"</string>
- <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Просмотреть все"</string>
+ <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Показать все"</string>
<string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Выберите"</string>
<string name="share_action_provider_share_with" msgid="5247684435979149216">"Открыть доступ"</string>
<string name="status_bar_device_locked" msgid="3092703448690669768">"Устройство заблокировано."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 5294bcd..bef7237 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"tednov"</string>
<string name="year" msgid="4001118221013892076">"leto"</string>
<string name="years" msgid="6881577717993213522">"let"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 sekunda"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> s"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 minuta"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> min"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 ura"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> h"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Težava z videoposnetkom"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Ta videoposnetek ni veljaven za pretakanje v to napravo."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Tega videoposnetka ni mogoče predvajati."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index b9e5848..89d2b87 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"veckor"</string>
<string name="year" msgid="4001118221013892076">"år"</string>
<string name="years" msgid="6881577717993213522">"år"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 sekund"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sekunder"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 minut"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minuter"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 timme"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> timmar"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Videoproblem"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Videon kan tyvärr inte spelas upp i den här enheten."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Det går inte att spela upp videon."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 06bc23e..4b6758a4 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -257,7 +257,7 @@
<string name="permdesc_getTasks" msgid="7454215995847658102">"Inaruhusu programu kurudisha taarifa kuhusu kazi zinazoendeshwa sasa na hivi karibuni. Hii inaweza kuruhusu programu kugundua taarifa kuhusu ni programu zipi zinazotumika kwenye kifaa."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"Tagusana na watumiaji"</string>
<string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Inaruhusu programu kutenda vitendo kwa watumiaji tofauti kwenye kifaa. Programu hasidi huenda zikatumia hii ili kukiuka ulinzi kati ya watumiaji."</string>
- <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"leseni kamili ili kutagusana na watumiaji"</string>
+ <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"leseni kamili ili kushirikiana na watumiaji"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Inaruhusu miingialiano yote inayowezekana kwa watumiaji."</string>
<string name="permlab_manageUsers" msgid="1676150911672282428">"dhibiti watumiaji"</string>
<string name="permdesc_manageUsers" msgid="8409306667645355638">"Inaruhusu programu kudhibiti watumiaji kwenye kifaa, pamoja na hoji, uundaji na ufutaji."</string>
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"wiki"</string>
<string name="year" msgid="4001118221013892076">"mwaka"</string>
<string name="years" msgid="6881577717993213522">"miaka"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"Sekunde 1"</item>
+ <item quantity="other" msgid="1886107766577166786">"Sekunde <xliff:g id="COUNT">%d</xliff:g>"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"Dakika 1"</item>
+ <item quantity="other" msgid="3165187169224908775">"Dakika <xliff:g id="COUNT">%d</xliff:g>"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"Saa 1"</item>
+ <item quantity="other" msgid="3863962854246773930">"Saa <xliff:g id="COUNT">%d</xliff:g>"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Shida ya video"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Video hii si halali kutiririshwa kwa kifaa hiki."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Haiwezi kucheza video hii."</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 3dccbe4..1578e7d 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"mga linggo"</string>
<string name="year" msgid="4001118221013892076">"taon"</string>
<string name="years" msgid="6881577717993213522">"mga taon"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 segundo"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> (na) segundo"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 minuto"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> (na) minuto"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 oras"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> (na) oras"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problema sa video"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Hindi wasto ang video na ito para sa streaming sa device na ito."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Hindi ma-play ang video na ito."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 5d44b72..d8ca187 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"hafta"</string>
<string name="year" msgid="4001118221013892076">"yıl"</string>
<string name="years" msgid="6881577717993213522">"yıl"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 saniye"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> saniye"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 dakika"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> dakika"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 saat"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> saat"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Video sorunu"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Bu video bu cihazda akış için uygun değil."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Bu video oynatılamıyor."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index ce54f39..6ccc115 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"тижн."</string>
<string name="year" msgid="4001118221013892076">"рік"</string>
<string name="years" msgid="6881577717993213522">"р."</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 с"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> с"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 хв"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> хв"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 год"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> год"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Проблема з відео"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Відео не придатне для потокового передавання в цей пристрій."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Неможливо відтворити це відео."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 59e9209..2afbb49 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"tuần"</string>
<string name="year" msgid="4001118221013892076">"năm"</string>
<string name="years" msgid="6881577717993213522">"năm"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 giây"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> giây"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 phút"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> phút"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 giờ"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> giờ"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Sự cố video"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Video này không hợp lệ để phát trực tuyến đến thiết bị này."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Không thể phát video này."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index ea9ea1d..6d8d220 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -994,12 +994,18 @@
<string name="weeks" msgid="6509623834583944518">"周"</string>
<string name="year" msgid="4001118221013892076">"年"</string>
<string name="years" msgid="6881577717993213522">"年"</string>
- <!-- no translation found for duration_seconds:one (6962015528372969481) -->
- <!-- no translation found for duration_seconds:other (1886107766577166786) -->
- <!-- no translation found for duration_minutes:one (4915414002546085617) -->
- <!-- no translation found for duration_minutes:other (3165187169224908775) -->
- <!-- no translation found for duration_hours:one (8917467491248809972) -->
- <!-- no translation found for duration_hours:other (3863962854246773930) -->
+ <plurals name="duration_seconds">
+ <item quantity="one" msgid="6962015528372969481">"1 秒"</item>
+ <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> 秒"</item>
+ </plurals>
+ <plurals name="duration_minutes">
+ <item quantity="one" msgid="4915414002546085617">"1 分钟"</item>
+ <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> 分钟"</item>
+ </plurals>
+ <plurals name="duration_hours">
+ <item quantity="one" msgid="8917467491248809972">"1 小时"</item>
+ <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> 小时"</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"视频问题"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"抱歉,该视频不适合在此设备上播放。"</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"无法播放此视频。"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 8f77704..451d3ef 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2107,8 +2107,8 @@
<enum name="locale" value="3" />
</attr>
- <!-- Direction of the text. A heuristic is used to determine the resolved text direction
- of paragraphs. -->
+ <!-- Defines the direction of the text. A heuristic is used to determine the resolved text
+ direction of paragraphs. -->
<attr name="textDirection" format="integer">
<!-- Default -->
<enum name="inherit" value="0" />
@@ -2128,7 +2128,7 @@
<enum name="locale" value="5" />
</attr>
- <!-- Alignment of the text. A heuristic is used to determine the resolved
+ <!-- Defines the alignment of the text. A heuristic is used to determine the resolved
text alignment. -->
<attr name="textAlignment" format="integer">
<!-- Default -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index ea28a51..3523db6 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -882,6 +882,16 @@
<!-- Remote server that can provide NTP responses. -->
<string translatable="false" name="config_ntpServer">2.android.pool.ntp.org</string>
+ <!-- Normal polling frequency in milliseconds -->
+ <integer name="config_ntpPollingInterval">864000000</integer>
+ <!-- Try-again polling interval in milliseconds, in case the network request failed -->
+ <integer name="config_ntpPollingIntervalShorter">60000</integer>
+ <!-- Number of times to try again with the shorter interval, before backing
+ off until the normal polling interval. A value < 0 indicates infinite. -->
+ <integer name="config_ntpRetry">3</integer>
+ <!-- If the time difference is greater than this threshold in milliseconds,
+ then update the time. -->
+ <integer name="config_ntpThreshold">5000</integer>
<!-- Timeout to wait for NTP server response. -->
<integer name="config_ntpTimeout">20000</integer>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e83575b..592ebb7 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -281,6 +281,10 @@
<java-symbol type="integer" name="config_cursorWindowSize" />
<java-symbol type="integer" name="config_longPressOnPowerBehavior" />
<java-symbol type="integer" name="config_max_pan_devices" />
+ <java-symbol type="integer" name="config_ntpPollingInterval" />
+ <java-symbol type="integer" name="config_ntpPollingIntervalShorter" />
+ <java-symbol type="integer" name="config_ntpRetry" />
+ <java-symbol type="integer" name="config_ntpThreshold" />
<java-symbol type="integer" name="config_ntpTimeout" />
<java-symbol type="integer" name="config_wifi_framework_scan_interval" />
<java-symbol type="integer" name="config_wifi_supplicant_scan_interval" />
diff --git a/docs/html/guide/google/gcm/gcm.jd b/docs/html/guide/google/gcm/gcm.jd
index 501ea37..7fc192b 100644
--- a/docs/html/guide/google/gcm/gcm.jd
+++ b/docs/html/guide/google/gcm/gcm.jd
@@ -80,7 +80,6 @@ Messaging (GCM):</p>
<ul>
<li>It allows 3rd-party application servers to send messages to
their Android applications.</li>
- <li>GCM makes no guarantees about delivery or the order of messages.</li>
<li>An Android application on an Android device doesn't need to be running to receive
messages. The system will wake up the Android application via Intent broadcast when the message arrives, as long as the application is set up with the proper
broadcast receiver and permissions.</li>
diff --git a/docs/html/guide/topics/resources/more-resources.jd b/docs/html/guide/topics/resources/more-resources.jd
index d37b9f8..9fa1a2d 100644
--- a/docs/html/guide/topics/resources/more-resources.jd
+++ b/docs/html/guide/topics/resources/more-resources.jd
@@ -540,7 +540,7 @@ resource ID.</dd>
<dt>resource reference:</dt>
<dd>
-In Java: <code>R.array.<em>string_array_name</em></code><br/>
+In Java: <code>R.array.<em>integer_array_name</em></code><br/>
In XML: <code>@[<em>package</em>:]array.<em>integer_array_name</em></code>
</dd>
@@ -565,7 +565,7 @@ In XML: <code>@[<em>package</em>:]array.<em>integer_array_name</em></code>
<dd><strong>Required.</strong> This must be the root node.
<p>No attributes.</p>
</dd>
- <dt id="integer-array-element"><code>&lt;string-array&gt;</code></dt>
+ <dt id="integer-array-element"><code>&lt;integer-array&gt;</code></dt>
<dd>Defines an array of integers. Contains one or more child {@code &lt;item>} elements.
<p class="caps">attributes:</p>
<dl class="atn-list">
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 688fd7a..89abdef 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -82,6 +82,7 @@ public final class Bitmap implements Parcelable {
if (sDefaultDensity >= 0) {
return sDefaultDensity;
}
+ //noinspection deprecation
sDefaultDensity = DisplayMetrics.DENSITY_DEVICE;
return sDefaultDensity;
}
@@ -360,6 +361,9 @@ public final class Bitmap implements Parcelable {
* that if this bitmap stores its pixels pre-multiplied
* (see {@link #isPremultiplied()}, the values in the buffer will also be
* pre-multiplied.</p>
+ * <p>After this method returns, the current position of the buffer is
+ * updated: the position is incremented by the number of elements written
+ * in the buffer.</p>
*/
public void copyPixelsToBuffer(Buffer dst) {
int elements = dst.remaining();
@@ -394,6 +398,10 @@ public final class Bitmap implements Parcelable {
* overwriting the bitmap's pixels. The data in the buffer is not changed
* in any way (unlike setPixels(), which converts from unpremultipled 32bit
* to whatever the bitmap's native format is.</p>
+ * <p>After this method returns, the current position of the buffer is
+ * updated: the position is incremented by the number of elements read from
+ * the buffer. If you need to read the bitmap from the buffer again you must
+ * first rewind the buffer.</p>
*/
public void copyPixelsFromBuffer(Buffer src) {
checkRecycled("copyPixelsFromBuffer called on recycled bitmap");
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index b4f1e84..f6b5ffc 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -59,6 +59,10 @@ public class Path {
int valNative = 0;
if (src != null) {
valNative = src.mNativePath;
+ isSimplePath = src.isSimplePath;
+ if (src.rects != null) {
+ rects = new Region(src.rects);
+ }
}
mNativePath = init2(valNative);
mDetectSimplePaths = HardwareRenderer.isAvailable();
@@ -544,6 +548,7 @@ public class Path {
int dstNative = 0;
if (dst != null) {
dstNative = dst.mNativePath;
+ dst.isSimplePath = false;
}
native_offset(mNativePath, dx, dy, dstNative);
}
@@ -555,6 +560,7 @@ public class Path {
* @param dy The amount in the Y direction to offset the entire path
*/
public void offset(float dx, float dy) {
+ isSimplePath = false;
native_offset(mNativePath, dx, dy);
}
@@ -580,6 +586,7 @@ public class Path {
public void transform(Matrix matrix, Path dst) {
int dstNative = 0;
if (dst != null) {
+ dst.isSimplePath = false;
dstNative = dst.mNativePath;
}
native_transform(mNativePath, matrix.native_instance, dstNative);
@@ -591,6 +598,7 @@ public class Path {
* @param matrix The matrix to apply to the path
*/
public void transform(Matrix matrix) {
+ isSimplePath = false;
native_transform(mNativePath, matrix.native_instance);
}
diff --git a/graphics/java/android/graphics/Point.java b/graphics/java/android/graphics/Point.java
index 338e880..e0d8ccc 100644
--- a/graphics/java/android/graphics/Point.java
+++ b/graphics/java/android/graphics/Point.java
@@ -70,20 +70,29 @@ public class Point implements Parcelable {
return this.x == x && this.y == y;
}
- @Override public boolean equals(Object o) {
- if (o instanceof Point) {
- Point p = (Point) o;
- return this.x == p.x && this.y == p.y;
- }
- return false;
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Point point = (Point) o;
+
+ if (x != point.x) return false;
+ if (y != point.y) return false;
+
+ return true;
}
- @Override public int hashCode() {
- return x * 32713 + y;
+ @Override
+ public int hashCode() {
+ int result = x;
+ result = 31 * result + y;
+ return result;
}
- @Override public String toString() {
- return "Point(" + x + ", " + y+ ")";
+ @Override
+ public String toString() {
+ return "Point(" + x + ", " + y + ")";
}
/**
diff --git a/graphics/java/android/graphics/PointF.java b/graphics/java/android/graphics/PointF.java
index e00271f..ee38dbb 100644
--- a/graphics/java/android/graphics/PointF.java
+++ b/graphics/java/android/graphics/PointF.java
@@ -73,6 +73,31 @@ public class PointF implements Parcelable {
return this.x == x && this.y == y;
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ PointF pointF = (PointF) o;
+
+ if (Float.compare(pointF.x, x) != 0) return false;
+ if (Float.compare(pointF.y, y) != 0) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (x != +0.0f ? Float.floatToIntBits(x) : 0);
+ result = 31 * result + (y != +0.0f ? Float.floatToIntBits(y) : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "PointF(" + x + ", " + y + ")";
+ }
+
/**
* Return the euclidian distance from (0,0) to the point
*/
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 59f06dd..b919ba4 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -197,7 +197,7 @@ public class SurfaceTexture {
public void attachToGLContext(int texName) {
int err = nativeAttachToGLContext(texName);
if (err != 0) {
- throw new RuntimeException("Error during detachFromGLContext (see logcat for details)");
+ throw new RuntimeException("Error during attachToGLContext (see logcat for details)");
}
}
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 3af2969..a0c9701 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -491,6 +491,8 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
mComputedConstantSize = orig.mComputedConstantSize;
mConstantWidth = orig.mConstantWidth;
mConstantHeight = orig.mConstantHeight;
+ mConstantMinimumWidth = orig.mConstantMinimumWidth;
+ mConstantMinimumHeight = orig.mConstantMinimumHeight;
mOpacity = orig.mOpacity;
mHaveStateful = orig.mHaveStateful;
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 0623a9e..b966bb4 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -479,7 +479,7 @@ public class GradientDrawable extends Drawable {
mFillPaint.setDither(mDither);
mFillPaint.setColorFilter(mColorFilter);
if (mColorFilter != null && !mGradientState.mHasSolidColor) {
- mFillPaint.setColor(0xff000000);
+ mFillPaint.setColor(mAlpha << 24);
}
if (haveStroke) {
mStrokePaint.setAlpha(currStrokeAlpha);
@@ -743,7 +743,7 @@ public class GradientDrawable extends Drawable {
mFillPaint.setShader(new LinearGradient(x0, y0, x1, y1,
colors, st.mPositions, Shader.TileMode.CLAMP));
if (!mGradientState.mHasSolidColor) {
- mFillPaint.setColor(0xff000000);
+ mFillPaint.setColor(mAlpha << 24);
}
} else if (st.mGradient == RADIAL_GRADIENT) {
x0 = r.left + (r.right - r.left) * st.mCenterX;
@@ -755,7 +755,7 @@ public class GradientDrawable extends Drawable {
level * st.mGradientRadius, colors, null,
Shader.TileMode.CLAMP));
if (!mGradientState.mHasSolidColor) {
- mFillPaint.setColor(0xff000000);
+ mFillPaint.setColor(mAlpha << 24);
}
} else if (st.mGradient == SWEEP_GRADIENT) {
x0 = r.left + (r.right - r.left) * st.mCenterX;
@@ -788,7 +788,7 @@ public class GradientDrawable extends Drawable {
}
mFillPaint.setShader(new SweepGradient(x0, y0, tempColors, tempPositions));
if (!mGradientState.mHasSolidColor) {
- mFillPaint.setColor(0xff000000);
+ mFillPaint.setColor(mAlpha << 24);
}
}
}
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 8c49091..2ad9de9 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -5088,18 +5088,23 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
// top of the stack for the media button event receivers : simply using the top of the
// stack would make the entry disappear from the RemoteControlDisplay in conditions such as
// notifications playing during music playback.
- // crawl the AudioFocus stack until an entry is found with the following characteristics:
+ // Crawl the AudioFocus stack from the top until an entry is found with the following
+ // characteristics:
// - focus gain on STREAM_MUSIC stream
// - non-transient focus gain on a stream other than music
FocusStackEntry af = null;
- Iterator<FocusStackEntry> stackIterator = mFocusStack.iterator();
- while(stackIterator.hasNext()) {
- FocusStackEntry fse = (FocusStackEntry)stackIterator.next();
- if ((fse.mStreamType == AudioManager.STREAM_MUSIC)
- || (fse.mFocusChangeType == AudioManager.AUDIOFOCUS_GAIN)) {
- af = fse;
- break;
+ try {
+ for (int index = mFocusStack.size()-1; index >= 0; index--) {
+ FocusStackEntry fse = mFocusStack.elementAt(index);
+ if ((fse.mStreamType == AudioManager.STREAM_MUSIC)
+ || (fse.mFocusChangeType == AudioManager.AUDIOFOCUS_GAIN)) {
+ af = fse;
+ break;
+ }
}
+ } catch (ArrayIndexOutOfBoundsException e) {
+ Log.e(TAG, "Wrong index accessing audio focus stack when updating RCD: " + e);
+ af = null;
}
if (af == null) {
clearRemoteControlDisplay_syncAfRcs();
@@ -5120,6 +5125,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
clearRemoteControlDisplay_syncAfRcs();
return;
}
+
// refresh conditions were verified: update the remote controls
// ok to call: synchronized mAudioFocusLock then on mRCStack, mRCStack is not empty
updateRemoteControlDisplay_syncAfRcs(infoChangedFlags);
diff --git a/packages/BackupRestoreConfirmation/res/values-ru/strings.xml b/packages/BackupRestoreConfirmation/res/values-ru/strings.xml
index 98b8bfc..dfbcff1 100644
--- a/packages/BackupRestoreConfirmation/res/values-ru/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-ru/strings.xml
@@ -32,7 +32,7 @@
<string name="restore_enc_password_text" msgid="6140898525580710823">"Если восстановленные данные зашифрованы, введите пароль:"</string>
<string name="toast_backup_started" msgid="550354281452756121">"Резервное копирование..."</string>
<string name="toast_backup_ended" msgid="3818080769548726424">"Резервное копирование завершено"</string>
- <string name="toast_restore_started" msgid="7881679218971277385">"Восстановление..."</string>
+ <string name="toast_restore_started" msgid="7881679218971277385">"Копирование..."</string>
<string name="toast_restore_ended" msgid="1764041639199696132">"Восстановление завершено"</string>
<string name="toast_timeout" msgid="5276598587087626877">"Время ожидания истекло"</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 9da883a..a1c5650 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -31,7 +31,6 @@ import android.os.SystemProperties;
import android.renderscript.Matrix4f;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
-import android.view.Display;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.WindowManager;
@@ -41,7 +40,6 @@ import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;
-import javax.microedition.khronos.opengles.GL;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -93,6 +91,7 @@ public class ImageWallpaper extends WallpaperService {
return "1".equals(SystemProperties.get(PROPERTY_KERNEL_QEMU, "0"));
}
+ @Override
public Engine onCreateEngine() {
mEngine = new DrawableEngine();
return mEngine;
@@ -102,8 +101,6 @@ public class ImageWallpaper extends WallpaperService {
static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
static final int EGL_OPENGL_ES2_BIT = 4;
- private final Object mLock = new Object[0];
-
// TODO: Not currently used, keeping around until we know we don't need it
@SuppressWarnings({"UnusedDeclaration"})
private WallpaperObserver mReceiver;
@@ -125,7 +122,6 @@ public class ImageWallpaper extends WallpaperService {
private EGLConfig mEglConfig;
private EGLContext mEglContext;
private EGLSurface mEglSurface;
- private GL mGL;
private static final String sSimpleVS =
"attribute vec4 position;\n" +
@@ -150,17 +146,16 @@ public class ImageWallpaper extends WallpaperService {
private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
class WallpaperObserver extends BroadcastReceiver {
+ @Override
public void onReceive(Context context, Intent intent) {
if (DEBUG) {
Log.d(TAG, "onReceive");
}
- synchronized (mLock) {
- mLastSurfaceWidth = mLastSurfaceHeight = -1;
- mBackground = null;
- mRedrawNeeded = true;
- drawFrameLocked();
- }
+ mLastSurfaceWidth = mLastSurfaceHeight = -1;
+ mBackground = null;
+ mRedrawNeeded = true;
+ drawFrame();
}
}
@@ -234,14 +229,12 @@ public class ImageWallpaper extends WallpaperService {
Log.d(TAG, "onVisibilityChanged: mVisible, visible=" + mVisible + ", " + visible);
}
- synchronized (mLock) {
- if (mVisible != visible) {
- if (DEBUG) {
- Log.d(TAG, "Visibility changed to visible=" + visible);
- }
- mVisible = visible;
- drawFrameLocked();
+ if (mVisible != visible) {
+ if (DEBUG) {
+ Log.d(TAG, "Visibility changed to visible=" + visible);
}
+ mVisible = visible;
+ drawFrame();
}
}
@@ -260,17 +253,15 @@ public class ImageWallpaper extends WallpaperService {
+ ", xPixels=" + xPixels + ", yPixels=" + yPixels);
}
- synchronized (mLock) {
- if (mXOffset != xOffset || mYOffset != yOffset) {
- if (DEBUG) {
- Log.d(TAG, "Offsets changed to (" + xOffset + "," + yOffset + ").");
- }
- mXOffset = xOffset;
- mYOffset = yOffset;
- mOffsetsChanged = true;
+ if (mXOffset != xOffset || mYOffset != yOffset) {
+ if (DEBUG) {
+ Log.d(TAG, "Offsets changed to (" + xOffset + "," + yOffset + ").");
}
- drawFrameLocked();
+ mXOffset = xOffset;
+ mYOffset = yOffset;
+ mOffsetsChanged = true;
}
+ drawFrame();
}
@Override
@@ -281,9 +272,7 @@ public class ImageWallpaper extends WallpaperService {
super.onSurfaceChanged(holder, format, width, height);
- synchronized (mLock) {
- drawFrameLocked();
- }
+ drawFrame();
}
@Override
@@ -305,12 +294,10 @@ public class ImageWallpaper extends WallpaperService {
}
super.onSurfaceRedrawNeeded(holder);
- synchronized (mLock) {
- drawFrameLocked();
- }
+ drawFrame();
}
- void drawFrameLocked() {
+ void drawFrame() {
SurfaceHolder sh = getSurfaceHolder();
final Rect frame = sh.getSurfaceFrame();
final int dw = frame.width();
@@ -657,8 +644,6 @@ public class ImageWallpaper extends WallpaperService {
throw new RuntimeException("eglMakeCurrent failed " +
GLUtils.getEGLErrorString(mEgl.eglGetError()));
}
-
- mGL = mEglContext.getGL();
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index cc9c601..a616490 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -55,6 +55,7 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.LevelListDrawable;
import android.hardware.display.DisplayManager;
import android.hardware.display.WifiDisplayStatus;
+import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.RemoteException;
@@ -85,6 +86,8 @@ class QuickSettings {
private static final String TAG = "QuickSettings";
public static final boolean SHOW_IME_TILE = false;
+ public static final boolean LONG_PRESS_TOGGLES = true;
+
private Context mContext;
private PanelBar mBar;
private QuickSettingsModel mModel;
@@ -94,6 +97,8 @@ class QuickSettings {
private WifiDisplayStatus mWifiDisplayStatus;
private PhoneStatusBar mStatusBarService;
private BluetoothState mBluetoothState;
+ private BluetoothAdapter mBluetoothAdapter;
+ private WifiManager mWifiManager;
private BrightnessController mBrightnessController;
private BluetoothController mBluetoothController;
@@ -131,6 +136,9 @@ class QuickSettings {
mModel = new QuickSettingsModel(context);
mWifiDisplayStatus = new WifiDisplayStatus();
mBluetoothState = new QuickSettingsModel.BluetoothState();
+ mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+
mHandler = new Handler();
Resources r = mContext.getResources();
@@ -391,7 +399,7 @@ class QuickSettings {
private void addSystemTiles(ViewGroup parent, LayoutInflater inflater) {
// Wi-fi
- QuickSettingsTileView wifiTile = (QuickSettingsTileView)
+ final QuickSettingsTileView wifiTile = (QuickSettingsTileView)
inflater.inflate(R.layout.quick_settings_tile, parent, false);
wifiTile.setContent(R.layout.quick_settings_tile_wifi, inflater);
wifiTile.setOnClickListener(new View.OnClickListener() {
@@ -400,6 +408,30 @@ class QuickSettings {
startSettingsActivity(android.provider.Settings.ACTION_WIFI_SETTINGS);
}
});
+ if (LONG_PRESS_TOGGLES) {
+ wifiTile.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ final boolean enable =
+ (mWifiManager.getWifiState() != WifiManager.WIFI_STATE_ENABLED);
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... args) {
+ // Disable tethering if enabling Wifi
+ final int wifiApState = mWifiManager.getWifiApState();
+ if (enable && ((wifiApState == WifiManager.WIFI_AP_STATE_ENABLING) ||
+ (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))) {
+ mWifiManager.setWifiApEnabled(null, false);
+ }
+
+ mWifiManager.setWifiEnabled(enable);
+ return null;
+ }
+ }.execute();
+ wifiTile.setPressed(false);
+ return true;
+ }} );
+ }
mModel.addWifiTile(wifiTile, new QuickSettingsModel.RefreshCallback() {
@Override
public void refreshView(QuickSettingsTileView view, State state) {
@@ -415,7 +447,7 @@ class QuickSettings {
});
parent.addView(wifiTile);
- if (mModel.deviceSupportsTelephony()) {
+ if (mModel.deviceHasMobileData()) {
// RSSI
QuickSettingsTileView rssiTile = (QuickSettingsTileView)
inflater.inflate(R.layout.quick_settings_tile, parent, false);
@@ -538,7 +570,7 @@ class QuickSettings {
// Bluetooth
if (mModel.deviceSupportsBluetooth()) {
- QuickSettingsTileView bluetoothTile = (QuickSettingsTileView)
+ final QuickSettingsTileView bluetoothTile = (QuickSettingsTileView)
inflater.inflate(R.layout.quick_settings_tile, parent, false);
bluetoothTile.setContent(R.layout.quick_settings_tile_bluetooth, inflater);
bluetoothTile.setOnClickListener(new View.OnClickListener() {
@@ -547,6 +579,19 @@ class QuickSettings {
startSettingsActivity(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS);
}
});
+ if (LONG_PRESS_TOGGLES) {
+ bluetoothTile.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ if (mBluetoothAdapter.isEnabled()) {
+ mBluetoothAdapter.disable();
+ } else {
+ mBluetoothAdapter.enable();
+ }
+ bluetoothTile.setPressed(false);
+ return true;
+ }});
+ }
mModel.addBluetoothTile(bluetoothTile, new QuickSettingsModel.RefreshCallback() {
@Override
public void refreshView(QuickSettingsTileView view, State state) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
index 4513dcb..ec42883 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -29,6 +29,7 @@ import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.drawable.Drawable;
import android.hardware.display.WifiDisplayStatus;
+import android.net.ConnectivityManager;
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;
@@ -171,6 +172,8 @@ class QuickSettingsModel implements BluetoothStateChangeCallback,
private final BugreportObserver mBugreportObserver;
private final BrightnessObserver mBrightnessObserver;
+ private final boolean mHasMobileData;
+
private QuickSettingsTileView mUserTile;
private RefreshCallback mUserCallback;
private UserState mUserState = new UserState();
@@ -249,6 +252,10 @@ class QuickSettingsModel implements BluetoothStateChangeCallback,
mBrightnessObserver = new BrightnessObserver(mHandler);
mBrightnessObserver.startObserving();
+ ConnectivityManager cm = (ConnectivityManager)
+ context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ mHasMobileData = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
+
IntentFilter alarmIntentFilter = new IntentFilter();
alarmIntentFilter.addAction(Intent.ACTION_ALARM_CHANGED);
context.registerReceiver(mAlarmIntentReceiver, alarmIntentFilter);
@@ -403,22 +410,22 @@ class QuickSettingsModel implements BluetoothStateChangeCallback,
mWifiCallback.refreshView(mWifiTile, mWifiState);
}
+ boolean deviceHasMobileData() {
+ return mHasMobileData;
+ }
+
// RSSI
void addRSSITile(QuickSettingsTileView view, RefreshCallback cb) {
mRSSITile = view;
mRSSICallback = cb;
mRSSICallback.refreshView(mRSSITile, mRSSIState);
}
- boolean deviceSupportsTelephony() {
- PackageManager pm = mContext.getPackageManager();
- return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
- }
// NetworkSignalChanged callback
@Override
public void onMobileDataSignalChanged(
boolean enabled, int mobileSignalIconId, String signalContentDescription,
int dataTypeIconId, String dataContentDescription, String enabledDesc) {
- if (deviceSupportsTelephony()) {
+ if (deviceHasMobileData()) {
// TODO: If view is in awaiting state, disable
Resources r = mContext.getResources();
mRSSIState.signalIconId = enabled && (mobileSignalIconId > 0)
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java
index dbd9999..762711d 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java
@@ -18,10 +18,9 @@ package com.android.internal.policy.impl.keyguard;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Point;
+import android.graphics.Rect;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;
@@ -53,17 +52,20 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
private final Handler mHandler = new Handler();
private final KeyguardActivityLauncher mActivityLauncher;
private final Callbacks mCallbacks;
+ private final CameraWidgetInfo mWidgetInfo;
private final WindowManager mWindowManager;
private final Point mRenderedSize = new Point();
- private final int[] mScreenLocation = new int[2];
+ private final int[] mTmpLoc = new int[2];
+ private final Rect mTmpRect = new Rect();
- private View mWidgetView;
private long mLaunchCameraStart;
private boolean mActive;
private boolean mTransitioning;
- private boolean mRecovering;
private boolean mDown;
+ private FixedSizeFrameLayout mPreview;
+ private View mFullscreenPreview;
+
private final Runnable mTransitionToCameraRunnable = new Runnable() {
@Override
public void run() {
@@ -81,19 +83,16 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
mActivityLauncher.launchCamera(worker, mSecureCameraActivityStartedRunnable);
}};
- private final Runnable mRecoverRunnable = new Runnable() {
+ private final Runnable mPostTransitionToCameraEndAction = new Runnable() {
@Override
public void run() {
- recover();
+ mHandler.post(mTransitionToCameraEndAction);
}};
- private final Runnable mRecoverEndAction = new Runnable() {
+ private final Runnable mRecoverRunnable = new Runnable() {
@Override
public void run() {
- if (!mRecovering)
- return;
- mCallbacks.onCameraLaunchedUnsuccessfully();
- reset();
+ recover();
}};
private final Runnable mRenderRunnable = new Runnable() {
@@ -119,13 +118,43 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
};
};
+ private static final class FixedSizeFrameLayout extends FrameLayout {
+ int width;
+ int height;
+
+ FixedSizeFrameLayout(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ measureChildren(
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+ setMeasuredDimension(width, height);
+ }
+ }
+
private CameraWidgetFrame(Context context, Callbacks callbacks,
- KeyguardActivityLauncher activityLauncher) {
+ KeyguardActivityLauncher activityLauncher,
+ CameraWidgetInfo widgetInfo, View previewWidget) {
super(context);
mCallbacks = callbacks;
mActivityLauncher = activityLauncher;
+ mWidgetInfo = widgetInfo;
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
KeyguardUpdateMonitor.getInstance(context).registerCallback(mCallback);
+
+ mPreview = new FixedSizeFrameLayout(context);
+ mPreview.addView(previewWidget);
+ addView(mPreview);
+
+ View clickBlocker = new View(context);
+ clickBlocker.setBackgroundColor(Color.TRANSPARENT);
+ clickBlocker.setOnClickListener(this);
+ addView(clickBlocker);
+
+ setContentDescription(context.getString(R.string.keyguard_accessibility_camera));
if (DEBUG) Log.d(TAG, "new CameraWidgetFrame instance " + instanceId());
}
@@ -137,24 +166,17 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
CameraWidgetInfo widgetInfo = launcher.getCameraWidgetInfo();
if (widgetInfo == null)
return null;
- View widgetView = widgetInfo.layoutId > 0 ?
- inflateWidgetView(context, widgetInfo) :
- inflateGenericWidgetView(context);
- if (widgetView == null)
+ View previewWidget = getPreviewWidget(context, widgetInfo);
+ if (previewWidget == null)
return null;
- ImageView preview = new ImageView(context);
- preview.setLayoutParams(new FrameLayout.LayoutParams(
- FrameLayout.LayoutParams.MATCH_PARENT,
- FrameLayout.LayoutParams.MATCH_PARENT));
- preview.setScaleType(ScaleType.FIT_CENTER);
- preview.setContentDescription(preview.getContext().getString(
- R.string.keyguard_accessibility_camera));
- CameraWidgetFrame cameraWidgetFrame = new CameraWidgetFrame(context, callbacks, launcher);
- cameraWidgetFrame.addView(preview);
- cameraWidgetFrame.mWidgetView = widgetView;
- preview.setOnClickListener(cameraWidgetFrame);
- return cameraWidgetFrame;
+ return new CameraWidgetFrame(context, callbacks, launcher, widgetInfo, previewWidget);
+ }
+
+ private static View getPreviewWidget(Context context, CameraWidgetInfo widgetInfo) {
+ return widgetInfo.layoutId > 0 ?
+ inflateWidgetView(context, widgetInfo) :
+ inflateGenericWidgetView(context);
}
private static View inflateWidgetView(Context context, CameraWidgetInfo widgetInfo) {
@@ -188,119 +210,99 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
return iv;
}
- public void render() {
- final Throwable[] thrown = new Throwable[1];
- final Bitmap[] offscreen = new Bitmap[1];
- try {
- final int width = getRootView().getWidth();
- final int height = getRootView().getHeight();
- if (mRenderedSize.x == width && mRenderedSize.y == height) {
- if (DEBUG) Log.d(TAG, String.format("Already rendered at size=%sx%s",
- width, height));
- return;
- }
- if (width == 0 || height == 0) {
- return;
- }
- final long start = SystemClock.uptimeMillis();
- offscreen[0] = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- final Canvas c = new Canvas(offscreen[0]);
- mWidgetView.measure(
- MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
- mWidgetView.layout(0, 0, width, height);
- mWidgetView.draw(c);
-
- final long end = SystemClock.uptimeMillis();
- if (DEBUG) Log.d(TAG, String.format(
- "Rendered camera widget in %sms size=%sx%s instance=%s at %s",
- end - start,
- width, height,
- instanceId(),
- end));
- mRenderedSize.set(width, height);
- } catch (Throwable t) {
- thrown[0] = t;
+ private void render() {
+ final View root = getRootView();
+ final int width = root.getWidth();
+ final int height = root.getHeight();
+ if (mRenderedSize.x == width && mRenderedSize.y == height) {
+ if (DEBUG) Log.d(TAG, String.format("Already rendered at size=%sx%s", width, height));
+ return;
+ }
+ if (width == 0 || height == 0) {
+ return;
}
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (thrown[0] == null) {
- try {
- ((ImageView) getChildAt(0)).setImageBitmap(offscreen[0]);
- } catch (Throwable t) {
- thrown[0] = t;
- }
- }
- if (thrown[0] == null)
- return;
-
- Log.w(TAG, "Error rendering camera widget", thrown[0]);
- try {
- removeAllViews();
- final View genericView = inflateGenericWidgetView(mContext);
- addView(genericView);
- } catch (Throwable t) {
- Log.w(TAG, "Error inflating generic camera widget", t);
- }
- }});
- }
-
- private void transitionToCamera() {
- if (mTransitioning || mDown) return;
+ mPreview.width = width;
+ mPreview.height = height;
+ mPreview.requestLayout();
- mTransitioning = true;
+ final int thisWidth = getWidth() - getPaddingLeft() - getPaddingRight();
+ final int thisHeight = getHeight() - getPaddingTop() - getPaddingBottom();
- final View child = getChildAt(0);
- final View root = getRootView();
+ final float pvScaleX = (float) thisWidth / width;
+ final float pvScaleY = (float) thisHeight / height;
+ final float pvScale = Math.min(pvScaleX, pvScaleY);
- final int startWidth = child.getWidth();
- final int startHeight = child.getHeight();
+ final int pvWidth = (int) (pvScale * width);
+ final int pvHeight = (int) (pvScale * height);
- final int finishWidth = root.getWidth();
- final int finishHeight = root.getHeight();
+ final float pvTransX = pvWidth < thisWidth ? (thisWidth - pvWidth) / 2 : 0;
+ final float pvTransY = pvHeight < thisHeight ? (thisHeight - pvHeight) / 2 : 0;
- final float scaleX = (float) finishWidth / startWidth;
- final float scaleY = (float) finishHeight / startHeight;
- final float scale = Math.round( Math.max(scaleX, scaleY) * 100) / 100f;
+ mPreview.setPivotX(0);
+ mPreview.setPivotY(0);
+ mPreview.setScaleX(pvScale);
+ mPreview.setScaleY(pvScale);
+ mPreview.setTranslationX(pvTransX);
+ mPreview.setTranslationY(pvTransY);
- final int[] loc = new int[2];
- root.getLocationInWindow(loc);
- final int finishCenter = loc[1] + finishHeight / 2;
+ mRenderedSize.set(width, height);
+ if (DEBUG) Log.d(TAG, String.format("Rendered camera widget size=%sx%s instance=%s",
+ width, height, instanceId()));
+ }
- child.getLocationInWindow(loc);
- final int startCenter = loc[1] + startHeight / 2;
+ private void transitionToCamera() {
+ if (mTransitioning || mDown) return;
- if (DEBUG) Log.d(TAG, String.format("Transitioning to camera. " +
- "(start=%sx%s, finish=%sx%s, scale=%s,%s, startCenter=%s, finishCenter=%s)",
- startWidth, startHeight,
- finishWidth, finishHeight,
- scaleX, scaleY,
- startCenter, finishCenter));
+ mTransitioning = true;
enableWindowExitAnimation(false);
- animate()
- .scaleX(scale)
- .scaleY(scale)
- .translationY(finishCenter - startCenter)
- .setDuration(WIDGET_ANIMATION_DURATION)
- .withEndAction(mTransitionToCameraEndAction)
- .start();
- mCallbacks.onLaunchingCamera();
- }
+ mPreview.getLocationInWindow(mTmpLoc);
+ final float pvHeight = mPreview.getHeight() * mPreview.getScaleY();
+ final float pvCenter = mTmpLoc[1] + pvHeight / 2f;
- private void recover() {
- if (DEBUG) Log.d(TAG, "recovering at " + SystemClock.uptimeMillis());
- mRecovering = true;
- animate()
+ final ViewGroup root = (ViewGroup) getRootView();
+ if (mFullscreenPreview == null) {
+ mFullscreenPreview = getPreviewWidget(mContext, mWidgetInfo);
+ mFullscreenPreview.setClickable(false);
+ root.addView(mFullscreenPreview);
+ }
+
+ root.getWindowVisibleDisplayFrame(mTmpRect);
+ final float fsHeight = mTmpRect.height();
+ final float fsCenter = mTmpRect.top + fsHeight / 2;
+
+ final float fsScaleY = pvHeight / fsHeight;
+ final float fsTransY = pvCenter - fsCenter;
+ final float fsScaleX = mPreview.getScaleX();
+
+ mPreview.setVisibility(View.GONE);
+ mFullscreenPreview.setVisibility(View.VISIBLE);
+ mFullscreenPreview.setTranslationY(fsTransY);
+ mFullscreenPreview.setScaleX(fsScaleX);
+ mFullscreenPreview.setScaleY(fsScaleY);
+ mFullscreenPreview
+ .animate()
.scaleX(1)
.scaleY(1)
+ .translationX(0)
.translationY(0)
.setDuration(WIDGET_ANIMATION_DURATION)
- .withEndAction(mRecoverEndAction)
+ .withEndAction(mPostTransitionToCameraEndAction)
.start();
+ mCallbacks.onLaunchingCamera();
+ }
+
+ private void recover() {
+ if (DEBUG) Log.d(TAG, "recovering at " + SystemClock.uptimeMillis());
+ mCallbacks.onCameraLaunchedUnsuccessfully();
+ reset();
+ }
+
+ @Override
+ public void setOnLongClickListener(OnLongClickListener l) {
+ // ignore
}
@Override
@@ -340,8 +342,8 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
return true;
}
- getLocationOnScreen(mScreenLocation);
- int rawBottom = mScreenLocation[1] + getHeight();
+ getLocationOnScreen(mTmpLoc);
+ int rawBottom = mTmpLoc[1] + getHeight();
if (event.getRawY() > rawBottom) {
if (DEBUG) Log.d(TAG, "onUserInteraction eaten: below widget");
return true;
@@ -388,14 +390,14 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
if (DEBUG) Log.d(TAG, "reset at " + SystemClock.uptimeMillis());
mLaunchCameraStart = 0;
mTransitioning = false;
- mRecovering = false;
mDown = false;
cancelTransitionToCamera();
mHandler.removeCallbacks(mRecoverRunnable);
- animate().cancel();
- setScaleX(1);
- setScaleY(1);
- setTranslationY(0);
+ mPreview.setVisibility(View.VISIBLE);
+ if (mFullscreenPreview != null) {
+ mFullscreenPreview.animate().cancel();
+ mFullscreenPreview.setVisibility(View.GONE);
+ }
enableWindowExitAnimation(true);
}
@@ -403,11 +405,18 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (DEBUG) Log.d(TAG, String.format("onSizeChanged new=%sx%s old=%sx%s at %s",
w, h, oldw, oldh, SystemClock.uptimeMillis()));
- final Handler worker = getWorkerHandler();
- (worker != null ? worker : mHandler).post(mRenderRunnable);
+ mHandler.post(mRenderRunnable);
super.onSizeChanged(w, h, oldw, oldh);
}
+ @Override
+ public void onBouncerShowing(boolean showing) {
+ if (showing) {
+ mTransitioning = false;
+ mHandler.post(mRecoverRunnable);
+ }
+ }
+
private void enableWindowExitAnimation(boolean isEnabled) {
View root = getRootView();
ViewGroup.LayoutParams lp = root.getLayoutParams();
@@ -427,15 +436,14 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged " + showing
+ " at " + SystemClock.uptimeMillis());
if (mTransitioning && !showing) {
- mTransitioning = false;
- mRecovering = false;
- mHandler.removeCallbacks(mRecoverRunnable);
- if (mLaunchCameraStart > 0) {
- long launchTime = SystemClock.uptimeMillis() - mLaunchCameraStart;
- if (DEBUG) Log.d(TAG, String.format("Camera took %sms to launch", launchTime));
- mLaunchCameraStart = 0;
- onCameraLaunched();
- }
+ mTransitioning = false;
+ mHandler.removeCallbacks(mRecoverRunnable);
+ if (mLaunchCameraStart > 0) {
+ long launchTime = SystemClock.uptimeMillis() - mLaunchCameraStart;
+ if (DEBUG) Log.d(TAG, String.format("Camera took %sms to launch", launchTime));
+ mLaunchCameraStart = 0;
+ onCameraLaunched();
+ }
}
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
index 0e25c84..11ed5bc 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -81,6 +81,7 @@ public class KeyguardHostView extends KeyguardViewBase {
private int mAppWidgetToShow;
private boolean mCheckAppWidgetConsistencyOnBootCompleted = false;
+ private boolean mCleanupAppWidgetsOnBootCompleted = false;
protected OnDismissAction mDismissAction;
@@ -155,6 +156,12 @@ public class KeyguardHostView extends KeyguardViewBase {
}
private void cleanupAppWidgetIds() {
+ // Since this method may delete a widget (which we can't do until boot completed) we
+ // may have to defer it until after boot complete.
+ if (!KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
+ mCleanupAppWidgetsOnBootCompleted = true;
+ return;
+ }
// Clean up appWidgetIds that are bound to lockscreen, but not actually used
// This is only to clean up after another bug: we used to not call
// deleteAppWidgetId when a user manually deleted a widget in keyguard. This code
@@ -190,6 +197,10 @@ public class KeyguardHostView extends KeyguardViewBase {
mSwitchPageRunnable.run();
mCheckAppWidgetConsistencyOnBootCompleted = false;
}
+ if (mCleanupAppWidgetsOnBootCompleted) {
+ cleanupAppWidgetIds();
+ mCleanupAppWidgetsOnBootCompleted = false;
+ }
}
};
@@ -260,7 +271,7 @@ public class KeyguardHostView extends KeyguardViewBase {
addWidgetsFromSettings();
if (numWidgets() >= MAX_WIDGETS) {
- setAddWidgetEnabled(false);
+ mAppWidgetContainer.setAddWidgetEnabled(false);
}
checkAppWidgetConsistency();
mSwitchPageRunnable.run();
@@ -354,15 +365,12 @@ public class KeyguardHostView extends KeyguardViewBase {
@Override
public void onAddView(View v) {
if (numWidgets() >= MAX_WIDGETS) {
- setAddWidgetEnabled(false);
+ mAppWidgetContainer.setAddWidgetEnabled(false);
}
- };
+ }
@Override
public void onRemoveView(View v, boolean deletePermanently) {
- if (numWidgets() < MAX_WIDGETS) {
- setAddWidgetEnabled(true);
- }
if (deletePermanently) {
final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId();
if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID &&
@@ -371,6 +379,13 @@ public class KeyguardHostView extends KeyguardViewBase {
}
}
}
+
+ @Override
+ public void onRemoveViewAnimationCompleted() {
+ if (numWidgets() < MAX_WIDGETS) {
+ mAppWidgetContainer.setAddWidgetEnabled(true);
+ }
+ }
};
public void userActivity() {
@@ -1044,15 +1059,6 @@ public class KeyguardHostView extends KeyguardViewBase {
return widgetCount;
}
-
- private void setAddWidgetEnabled(boolean clickable) {
- View addWidget = mAppWidgetContainer.findViewById(R.id.keyguard_add_widget);
- if (addWidget != null) {
- View addWidgetButton = addWidget.findViewById(R.id.keyguard_add_widget_view);
- addWidgetButton.setEnabled(clickable);
- }
- }
-
private void addDefaultWidgets() {
LayoutInflater inflater = LayoutInflater.from(mContext);
inflater.inflate(R.layout.keyguard_transport_control_view, this, true);
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java
index debf765..257fd27 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java
@@ -16,7 +16,6 @@
package com.android.internal.policy.impl.keyguard;
import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
@@ -27,10 +26,10 @@ import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
-import java.util.ArrayList;
-
import com.android.internal.R;
+import java.util.ArrayList;
+
public class KeyguardWidgetCarousel extends KeyguardWidgetPager {
private float mAdjacentPagesAngle;
@@ -56,17 +55,30 @@ public class KeyguardWidgetCarousel extends KeyguardWidgetPager {
return MAX_SCROLL_PROGRESS;
}
- public float getAlphaForPage(int screenCenter, int index) {
+ public float getAlphaForPage(int screenCenter, int index, boolean showSidePages) {
View child = getChildAt(index);
if (child == null) return 0f;
+ boolean inVisibleRange = index >= getNextPage() - 1 && index <= getNextPage() + 1;
float scrollProgress = getScrollProgress(screenCenter, child, index);
- if (!isOverScrollChild(index, scrollProgress)) {
+
+ if (isOverScrollChild(index, scrollProgress)) {
+ return 1.0f;
+ } else if ((showSidePages && inVisibleRange) || index == getNextPage()) {
scrollProgress = getBoundedScrollProgress(screenCenter, child, index);
float alpha = 1.0f - 1.0f * Math.abs(scrollProgress / MAX_SCROLL_PROGRESS);
return alpha;
} else {
- return 1.0f;
+ return 0f;
+ }
+ }
+
+ public float getOutlineAlphaForPage(int screenCenter, int index, boolean showSidePages) {
+ boolean inVisibleRange = index >= getNextPage() - 1 && index <= getNextPage() + 1;
+ if (inVisibleRange) {
+ return super.getOutlineAlphaForPage(screenCenter, index, showSidePages);
+ } else {
+ return 0f;
}
}
@@ -75,24 +87,32 @@ public class KeyguardWidgetCarousel extends KeyguardWidgetPager {
mChildrenOutlineFadeAnimation.cancel();
mChildrenOutlineFadeAnimation = null;
}
+ boolean showSidePages = mShowingInitialHints || isPageMoving();
if (!isReordering(false)) {
for (int i = 0; i < getChildCount(); i++) {
KeyguardWidgetFrame child = getWidgetPageAt(i);
if (child != null) {
- child.setBackgroundAlpha(getOutlineAlphaForPage(screenCenter, i));
- child.setContentAlpha(getAlphaForPage(screenCenter, i));
+ float outlineAlpha = getOutlineAlphaForPage(screenCenter, i, showSidePages);
+ float contentAlpha = getAlphaForPage(screenCenter, i,showSidePages);
+ child.setBackgroundAlpha(outlineAlpha);
+ child.setContentAlpha(contentAlpha);
}
}
}
}
public void showInitialPageHints() {
+ mShowingInitialHints = true;
int count = getChildCount();
for (int i = 0; i < count; i++) {
+ boolean inVisibleRange = i >= getNextPage() - 1 && i <= getNextPage() + 1;
KeyguardWidgetFrame child = getWidgetPageAt(i);
- if (i >= mCurrentPage - 1 && i <= mCurrentPage + 1) {
- child.fadeFrame(this, true, KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER,
- CHILDREN_OUTLINE_FADE_IN_DURATION);
+ if (inVisibleRange) {
+ child.setBackgroundAlpha(KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER);
+ child.setContentAlpha(1f);
+ } else {
+ child.setBackgroundAlpha(0f);
+ child.setContentAlpha(0f);
}
}
}
@@ -220,8 +240,8 @@ public class KeyguardWidgetCarousel extends KeyguardWidgetPager {
for (int i = 0; i < count; i++) {
KeyguardWidgetFrame child = getWidgetPageAt(i);
- float finalAlpha = getAlphaForPage(mScreenCenter, i);
- float finalOutlineAlpha = getOutlineAlphaForPage(mScreenCenter, i);
+ float finalAlpha = getAlphaForPage(mScreenCenter, i, true);
+ float finalOutlineAlpha = getOutlineAlphaForPage(mScreenCenter, i, true);
getTransformForPage(mScreenCenter, i, mTmpTransform);
boolean inVisibleRange = (i >= mCurrentPage - 1 && i <= mCurrentPage + 1);
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
index 3c79206..babb9cb 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
@@ -424,7 +424,9 @@ public class KeyguardWidgetFrame extends FrameLayout {
mBgAlphaController = caller;
}
- if (mBgAlphaController != caller) return;
+ if (mBgAlphaController != caller && mBgAlphaController != null) {
+ return;
+ }
if (mFrameFade != null) {
mFrameFade.cancel();
@@ -512,6 +514,10 @@ public class KeyguardWidgetFrame extends FrameLayout {
return false;
}
+ public void onBouncerShowing(boolean showing) {
+ // hook for subclasses
+ }
+
public void setWorkerHandler(Handler workerHandler) {
mWorkerHandler = workerHandler;
}
@@ -519,4 +525,5 @@ public class KeyguardWidgetFrame extends FrameLayout {
public Handler getWorkerHandler() {
return mWorkerHandler;
}
+
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
index 85b5472..b4fe0c7 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
@@ -70,6 +70,12 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
private Callbacks mCallbacks;
private int mWidgetToResetAfterFadeOut;
+ protected boolean mShowingInitialHints = false;
+
+ // A temporary handle to the Add-Widget view
+ private View mAddWidgetView;
+ private int mLastWidthMeasureSpec;
+ private int mLastHeightMeasureSpec;
// Bouncer
private int mBouncerZoomInOutDuration = 250;
@@ -238,13 +244,13 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
public void onUserActivityTimeoutChanged();
public void onAddView(View v);
public void onRemoveView(View v, boolean deletePermanently);
+ public void onRemoveViewAnimationCompleted();
}
public void addWidget(View widget) {
addWidget(widget, -1);
}
-
public void onRemoveView(View v, final boolean deletePermanently) {
final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId();
if (mCallbacks != null) {
@@ -258,6 +264,13 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
});
}
+ @Override
+ public void onRemoveViewAnimationCompleted() {
+ if (mCallbacks != null) {
+ mCallbacks.onRemoveViewAnimationCompleted();
+ }
+ }
+
public void onAddView(View v, final int index) {
final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId();
final int[] pagesRange = new int[mTempVisiblePagesRange.length];
@@ -458,12 +471,21 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
private void updatePageAlphaValues(int screenCenter) {
}
- public float getAlphaForPage(int screenCenter, int index) {
- return 1f;
+ public float getAlphaForPage(int screenCenter, int index, boolean showSidePages) {
+ if (showSidePages) {
+ return 1f;
+ } else {
+ return index == mCurrentPage ? 1.0f : 0f;
+ }
}
- public float getOutlineAlphaForPage(int screenCenter, int index) {
- return getAlphaForPage(screenCenter, index) * KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER;
+ public float getOutlineAlphaForPage(int screenCenter, int index, boolean showSidePages) {
+ if (showSidePages) {
+ return getAlphaForPage(screenCenter, index, showSidePages)
+ * KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER;
+ } else {
+ return 0f;
+ }
}
protected boolean isOverScrollChild(int index, float scrollProgress) {
@@ -562,12 +584,12 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
}
public void showInitialPageHints() {
+ mShowingInitialHints = true;
int count = getChildCount();
for (int i = 0; i < count; i++) {
KeyguardWidgetFrame child = getWidgetPageAt(i);
if (i != mCurrentPage) {
- child.fadeFrame(this, true, KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER,
- CHILDREN_OUTLINE_FADE_IN_DURATION);
+ child.setBackgroundAlpha(KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER);
child.setContentAlpha(0f);
} else {
child.setBackgroundAlpha(0f);
@@ -576,10 +598,6 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
}
}
- public void showSidePageHints() {
- animateOutlinesAndSidePages(true, -1);
- }
-
@Override
void setCurrentPage(int currentPage) {
super.setCurrentPage(currentPage);
@@ -592,12 +610,10 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
mHasMeasure = false;
}
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- }
-
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ mLastWidthMeasureSpec = widthMeasureSpec;
+ mLastHeightMeasureSpec = heightMeasureSpec;
+
int maxChallengeTop = -1;
View parent = (View) getParent();
boolean challengeShowing = false;
@@ -658,7 +674,7 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
for (int i = 0; i < count; i++) {
float finalContentAlpha;
if (show) {
- finalContentAlpha = getAlphaForPage(mScreenCenter, i);
+ finalContentAlpha = getAlphaForPage(mScreenCenter, i, true);
} else if (!show && i == curPage) {
finalContentAlpha = 1f;
} else {
@@ -670,7 +686,7 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
ObjectAnimator a = ObjectAnimator.ofPropertyValuesHolder(child, alpha);
anims.add(a);
- float finalOutlineAlpha = show ? getOutlineAlphaForPage(mScreenCenter, i) : 0f;
+ float finalOutlineAlpha = show ? getOutlineAlphaForPage(mScreenCenter, i, true) : 0f;
child.fadeFrame(this, show, finalOutlineAlpha, duration);
}
@@ -696,6 +712,7 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
frame.resetSize();
}
mWidgetToResetAfterFadeOut = -1;
+ mShowingInitialHints = false;
}
updateWidgetFramesImportantForAccessibility();
}
@@ -775,6 +792,9 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
mZoomInOutAnim.setInterpolator(new DecelerateInterpolator(1.5f));
mZoomInOutAnim.start();
}
+ if (currentPage instanceof KeyguardWidgetFrame) {
+ ((KeyguardWidgetFrame)currentPage).onBouncerShowing(false);
+ }
}
// Zoom out after the bouncer is initiated
@@ -800,6 +820,27 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
mZoomInOutAnim.setInterpolator(new DecelerateInterpolator(1.5f));
mZoomInOutAnim.start();
}
+ if (currentPage instanceof KeyguardWidgetFrame) {
+ ((KeyguardWidgetFrame)currentPage).onBouncerShowing(true);
+ }
+ }
+
+ void setAddWidgetEnabled(boolean enabled) {
+ if (mAddWidgetView != null && enabled) {
+ addView(mAddWidgetView, 0);
+ // We need to force measure the PagedView so that the calls to update the scroll
+ // position below work
+ measure(mLastWidthMeasureSpec, mLastHeightMeasureSpec);
+ // Bump up the current page to account for the addition of the new page
+ setCurrentPage(mCurrentPage + 1);
+ mAddWidgetView = null;
+ } else if (mAddWidgetView == null && !enabled) {
+ View addWidget = findViewById(com.android.internal.R.id.keyguard_add_widget);
+ if (addWidget != null) {
+ mAddWidgetView = addWidget;
+ removeView(addWidget);
+ }
+ }
}
boolean isAddPage(int pageIndex) {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
index 0b06306..33c2456 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
@@ -1588,6 +1588,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
//public abstract void onFlingToDelete(View v);
public abstract void onRemoveView(View v, boolean deletePermanently);
+ public abstract void onRemoveViewAnimationCompleted();
public abstract void onAddView(View v, int index);
private void resetTouchState() {
@@ -2383,6 +2384,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
public void run() {
mDeferringForDelete = false;
onEndReordering();
+ onRemoveViewAnimationCompleted();
}
};
zoomIn(onCompleteRunnable);
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 9c533da..85bc259 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -386,6 +386,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
private Locale mLastSystemLocale;
private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
private final IPackageManager mIPackageManager;
+ private boolean mInputBoundToKeyguard;
class SettingsObserver extends ContentObserver {
SettingsObserver(Handler handler) {
@@ -877,10 +878,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
final boolean hardKeyShown = haveHardKeyboard
&& conf.hardKeyboardHidden
!= Configuration.HARDKEYBOARDHIDDEN_YES;
- final boolean isScreenLocked = mKeyguardManager != null
- && mKeyguardManager.isKeyguardLocked()
- && mKeyguardManager.isKeyguardSecure();
- mImeWindowVis = (!isScreenLocked && (mInputShown || hardKeyShown)) ?
+ final boolean isScreenLocked =
+ mKeyguardManager != null && mKeyguardManager.isKeyguardLocked();
+ final boolean isScreenSecurelyLocked =
+ isScreenLocked && mKeyguardManager.isKeyguardSecure();
+ final boolean inputShown = mInputShown && (!isScreenLocked || mInputBoundToKeyguard);
+ mImeWindowVis = (!isScreenSecurelyLocked && (inputShown || hardKeyShown)) ?
(InputMethodService.IME_ACTIVE | InputMethodService.IME_VISIBLE) : 0;
updateImeWindowStatusLocked();
}
@@ -1124,6 +1127,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return mNoBinding;
}
+ if (mCurClient == null) {
+ mInputBoundToKeyguard = mKeyguardManager != null && mKeyguardManager.isKeyguardLocked();
+ if (DEBUG) {
+ Slog.v(TAG, "New bind. keyguard = " + mInputBoundToKeyguard);
+ }
+ }
+
if (mCurClient != cs) {
// If the client is changing, we need to switch over to the new
// one.
@@ -2486,10 +2496,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
map.put(id, p);
// Valid system default IMEs and IMEs that have English subtypes are enabled
- // by default, unless there's a hard keyboard and the system IME was explicitly
- // disabled
- if ((isValidSystemDefaultIme(p, mContext) || isSystemImeThatHasEnglishSubtype(p))
- && (!haveHardKeyboard || disabledSysImes.indexOf(id) < 0)) {
+ // by default
+ if ((isValidSystemDefaultIme(p, mContext) || isSystemImeThatHasEnglishSubtype(p))) {
setInputMethodEnabledLocked(id, true);
}
diff --git a/services/java/com/android/server/NetworkTimeUpdateService.java b/services/java/com/android/server/NetworkTimeUpdateService.java
index 790be55..3bfd190 100644
--- a/services/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/java/com/android/server/NetworkTimeUpdateService.java
@@ -57,15 +57,6 @@ public class NetworkTimeUpdateService {
private static final int EVENT_POLL_NETWORK_TIME = 2;
private static final int EVENT_NETWORK_CONNECTED = 3;
- /** Normal polling frequency */
- private static final long POLLING_INTERVAL_MS = 24L * 60 * 60 * 1000; // 24 hrs
- /** Try-again polling interval, in case the network request failed */
- private static final long POLLING_INTERVAL_SHORTER_MS = 60 * 1000L; // 60 seconds
- /** Number of times to try again */
- private static final int TRY_AGAIN_TIMES_MAX = 3;
- /** If the time difference is greater than this threshold, then update the time. */
- private static final int TIME_ERROR_THRESHOLD_MS = 5 * 1000;
-
private static final String ACTION_POLL =
"com.android.server.NetworkTimeUpdateService.action.POLL";
private static int POLL_REQUEST = 0;
@@ -86,6 +77,15 @@ public class NetworkTimeUpdateService {
private SettingsObserver mSettingsObserver;
// The last time that we successfully fetched the NTP time.
private long mLastNtpFetchTime = NOT_SET;
+
+ // Normal polling frequency
+ private final long mPollingIntervalMs;
+ // Try-again polling interval, in case the network request failed
+ private final long mPollingIntervalShorterMs;
+ // Number of times to try again
+ private final int mTryAgainTimesMax;
+ // If the time difference is greater than this threshold, then update the time.
+ private final int mTimeErrorThresholdMs;
// Keeps track of how many quick attempts were made to fetch NTP time.
// During bootup, the network may not have been up yet, or it's taking time for the
// connection to happen.
@@ -97,6 +97,15 @@ public class NetworkTimeUpdateService {
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
Intent pollIntent = new Intent(ACTION_POLL, null);
mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0);
+
+ mPollingIntervalMs = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_ntpPollingInterval);
+ mPollingIntervalShorterMs = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_ntpPollingIntervalShorter);
+ mTryAgainTimesMax = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_ntpRetry);
+ mTimeErrorThresholdMs = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_ntpThreshold);
}
/** Initialize the receivers and initiate the first NTP request */
@@ -143,35 +152,35 @@ public class NetworkTimeUpdateService {
if (!isAutomaticTimeRequested()) return;
final long refTime = SystemClock.elapsedRealtime();
- // If NITZ time was received less than POLLING_INTERVAL_MS time ago,
+ // If NITZ time was received less than mPollingIntervalMs time ago,
// no need to sync to NTP.
- if (mNitzTimeSetTime != NOT_SET && refTime - mNitzTimeSetTime < POLLING_INTERVAL_MS) {
- resetAlarm(POLLING_INTERVAL_MS);
+ if (mNitzTimeSetTime != NOT_SET && refTime - mNitzTimeSetTime < mPollingIntervalMs) {
+ resetAlarm(mPollingIntervalMs);
return;
}
final long currentTime = System.currentTimeMillis();
if (DBG) Log.d(TAG, "System time = " + currentTime);
// Get the NTP time
- if (mLastNtpFetchTime == NOT_SET || refTime >= mLastNtpFetchTime + POLLING_INTERVAL_MS
+ if (mLastNtpFetchTime == NOT_SET || refTime >= mLastNtpFetchTime + mPollingIntervalMs
|| event == EVENT_AUTO_TIME_CHANGED) {
if (DBG) Log.d(TAG, "Before Ntp fetch");
// force refresh NTP cache when outdated
- if (mTime.getCacheAge() >= POLLING_INTERVAL_MS) {
+ if (mTime.getCacheAge() >= mPollingIntervalMs) {
mTime.forceRefresh();
}
// only update when NTP time is fresh
- if (mTime.getCacheAge() < POLLING_INTERVAL_MS) {
+ if (mTime.getCacheAge() < mPollingIntervalMs) {
final long ntp = mTime.currentTimeMillis();
mTryAgainCounter = 0;
// If the clock is more than N seconds off or this is the first time it's been
// fetched since boot, set the current time.
- if (Math.abs(ntp - currentTime) > TIME_ERROR_THRESHOLD_MS
+ if (Math.abs(ntp - currentTime) > mTimeErrorThresholdMs
|| mLastNtpFetchTime == NOT_SET) {
// Set the system time
if (DBG && mLastNtpFetchTime == NOT_SET
- && Math.abs(ntp - currentTime) <= TIME_ERROR_THRESHOLD_MS) {
+ && Math.abs(ntp - currentTime) <= mTimeErrorThresholdMs) {
Log.d(TAG, "For initial setup, rtc = " + currentTime);
}
if (DBG) Log.d(TAG, "Ntp time to be set = " + ntp);
@@ -186,17 +195,17 @@ public class NetworkTimeUpdateService {
} else {
// Try again shortly
mTryAgainCounter++;
- if (mTryAgainCounter <= TRY_AGAIN_TIMES_MAX) {
- resetAlarm(POLLING_INTERVAL_SHORTER_MS);
+ if (mTryAgainTimesMax < 0 || mTryAgainCounter <= mTryAgainTimesMax) {
+ resetAlarm(mPollingIntervalShorterMs);
} else {
// Try much later
mTryAgainCounter = 0;
- resetAlarm(POLLING_INTERVAL_MS);
+ resetAlarm(mPollingIntervalMs);
}
return;
}
}
- resetAlarm(POLLING_INTERVAL_MS);
+ resetAlarm(mPollingIntervalMs);
}
/**
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index fa84f48..e2be577 100644
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -1128,13 +1128,13 @@ public class NotificationManagerService extends INotificationManager.Stub
final boolean hasCustomVibrate = notification.vibrate != null;
// new in 4.2: if there was supposed to be a sound and we're in vibrate mode,
- // and no other vibration is specified, we apply the default vibration anyway
+ // and no other vibration is specified, we fall back to vibration
final boolean convertSoundToVibration =
!hasCustomVibrate
&& hasValidSound
&& (audioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE);
- // The DEFAULT_VIBRATE flag trumps any custom vibration.
+ // The DEFAULT_VIBRATE flag trumps any custom vibration AND the fallback.
final boolean useDefaultVibrate =
(notification.defaults & Notification.DEFAULT_VIBRATE) != 0;
@@ -1147,8 +1147,8 @@ public class NotificationManagerService extends INotificationManager.Stub
// does not have the VIBRATE permission.
long identity = Binder.clearCallingIdentity();
try {
- mVibrator.vibrate(convertSoundToVibration ? mFallbackVibrationPattern
- : mDefaultVibrationPattern,
+ mVibrator.vibrate(useDefaultVibrate ? mDefaultVibrationPattern
+ : mFallbackVibrationPattern,
((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1);
} finally {
Binder.restoreCallingIdentity(identity);
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 671cbfe..65bfa7e 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -87,7 +87,9 @@ import com.android.internal.statusbar.IStatusBarService;
import org.xmlpull.v1.XmlPullParserException;
+import java.io.FileDescriptor;
import java.io.IOException;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -122,6 +124,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private static final String TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED =
"temporaryEnableAccessibilityStateUntilKeyguardRemoved";
+ private static final String FUNCTION_DUMP = "dump";
+
private static final char COMPONENT_NAME_SEPARATOR = ':';
private static final int OWN_PROCESS_ID = android.os.Process.myPid();
@@ -1258,6 +1262,46 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
}
+ @Override
+ public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
+ mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
+ synchronized (mLock) {
+ pw.println("ACCESSIBILITY MANAGER (dumpsys accessibility)");
+ pw.println();
+ pw.println("Ui automation service: bound=" + (mUiAutomationService != null));
+ pw.println();
+ if (mUiAutomationService != null) {
+ mUiAutomationService.dump(fd, pw, args);
+ pw.println();
+ }
+ final int userCount = mUserStates.size();
+ for (int i = 0; i < userCount; i++) {
+ UserState userState = mUserStates.valueAt(i);
+ pw.append("User state[attributes:{id=" + userState.mUserId);
+ pw.append(", currentUser=" + (userState.mUserId == mCurrentUserId));
+ pw.append(", accessibilityEnabled=" + userState.mIsAccessibilityEnabled);
+ pw.append(", touchExplorationEnabled=" + userState.mIsTouchExplorationEnabled);
+ pw.append(", displayMagnificationEnabled="
+ + userState.mIsDisplayMagnificationEnabled);
+ pw.append("}");
+ pw.println();
+ pw.append(" services:{");
+ final int serviceCount = userState.mServices.size();
+ for (int j = 0; j < serviceCount; j++) {
+ if (j > 0) {
+ pw.append(", ");
+ pw.println();
+ pw.append(" ");
+ }
+ Service service = userState.mServices.get(j);
+ service.dump(fd, pw, args);
+ }
+ pw.println("}]");
+ pw.println();
+ }
+ }
+ }
+
private class AccessibilityConnectionWrapper implements DeathRecipient {
private final int mWindowId;
private final int mUserId;
@@ -1894,6 +1938,23 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
}
+ @Override
+ public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
+ mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
+ synchronized (mLock) {
+ pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo()
+ .loadLabel(mContext.getPackageManager()));
+ pw.append(", feedbackType"
+ + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType));
+ pw.append(", canRetrieveScreenContent=" + mCanRetrieveScreenContent);
+ pw.append(", eventTypes="
+ + AccessibilityEvent.eventTypeToString(mEventTypes));
+ pw.append(", notificationTimeout=" + mNotificationTimeout);
+ pw.append("]");
+ }
+ }
+
+ @Override
public void onServiceDisconnected(ComponentName componentName) {
/* do nothing - #binderDied takes care */
}
@@ -2313,7 +2374,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
if (!hasPermission(permission)) {
throw new SecurityException("You do not have " + permission
- + " required to call " + function);
+ + " required to call " + function + " from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
}
}
diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java
index 8650192..2690442 100644
--- a/services/java/com/android/server/power/PowerManagerService.java
+++ b/services/java/com/android/server/power/PowerManagerService.java
@@ -618,8 +618,19 @@ public final class PowerManagerService extends IPowerManager.Stub
}
}
+ private static boolean isScreenLock(final WakeLock wakeLock) {
+ switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
+ case PowerManager.FULL_WAKE_LOCK:
+ case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
+ case PowerManager.SCREEN_DIM_WAKE_LOCK:
+ return true;
+ }
+ return false;
+ }
+
private void applyWakeLockFlagsOnAcquireLocked(WakeLock wakeLock) {
- if ((wakeLock.mFlags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
+ if ((wakeLock.mFlags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0 &&
+ isScreenLock(wakeLock)) {
wakeUpNoUpdateLocked(SystemClock.uptimeMillis());
}
}
diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/java/com/android/server/wm/AppWindowAnimator.java
index ca94d04..e044c6d 100644
--- a/services/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/java/com/android/server/wm/AppWindowAnimator.java
@@ -100,6 +100,10 @@ public class AppWindowAnimator {
animInitialized = false;
}
clearThumbnail();
+ if (mAppToken.deferClearAllDrawn) {
+ mAppToken.allDrawn = false;
+ mAppToken.deferClearAllDrawn = false;
+ }
}
public void clearThumbnail() {
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index 7efffe5..3ec6d26 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -64,6 +64,9 @@ class AppWindowToken extends WindowToken {
int numDrawnWindows;
boolean inPendingTransaction;
boolean allDrawn;
+ // Set to true when this app creates a surface while in the middle of an animation. In that
+ // case do not clear allDrawn until the animation completes.
+ boolean deferClearAllDrawn;
// Is this token going to be hidden in a little while? If so, it
// won't be taken into account for setting the screen orientation.
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 5adc082..f8a2b0c 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -4295,6 +4295,7 @@ public class WindowManagerService extends IWindowManager.Stub
// the new one.
if (ttoken.allDrawn) {
wtoken.allDrawn = true;
+ wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn;
}
if (ttoken.firstWindowDrawn) {
wtoken.firstWindowDrawn = true;
@@ -4425,6 +4426,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ @Override
public void setAppWillBeHidden(IBinder token) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
"setAppWillBeHidden()")) {
@@ -4548,6 +4550,7 @@ public class WindowManagerService extends IWindowManager.Stub
return delayed;
}
+ @Override
public void setAppVisibility(IBinder token, boolean visible) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
"setAppVisibility()")) {
@@ -4602,6 +4605,7 @@ public class WindowManagerService extends IWindowManager.Stub
// its windows to be ready.
if (wtoken.hidden) {
wtoken.allDrawn = false;
+ wtoken.deferClearAllDrawn = false;
wtoken.waitingToShow = true;
if (wtoken.clientHidden) {
@@ -4700,6 +4704,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ @Override
public void startAppFreezingScreen(IBinder token, int configChanges) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
"setAppFreezingScreen()")) {
@@ -4723,6 +4728,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ @Override
public void stopAppFreezingScreen(IBinder token, boolean force) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
"setAppFreezingScreen()")) {
@@ -5583,7 +5589,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (!mSystemBooted && !haveBootMsg) {
return;
}
-
+
// If we are turning on the screen after the boot is completed
// normally, don't do so until we have the application and
// wallpaper.
@@ -5733,7 +5739,7 @@ public class WindowManagerService extends IWindowManager.Stub
* Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
* In portrait mode, it grabs the upper region of the screen based on the vertical dimension
* of the target image.
- *
+ *
* @param displayId the Display to take a screenshot of.
* @param width the width of the target bitmap
* @param height the height of the target bitmap
@@ -5808,7 +5814,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (maxLayer < ws.mWinAnimator.mSurfaceLayer) {
maxLayer = ws.mWinAnimator.mSurfaceLayer;
}
-
+
// Don't include wallpaper in bounds calculation
if (!ws.mIsWallpaper) {
final Rect wf = ws.mFrame;
@@ -8708,6 +8714,7 @@ public class WindowManagerService extends IWindowManager.Stub
// this guy's animations regardless of whether it's
// gotten drawn.
wtoken.allDrawn = true;
+ wtoken.deferClearAllDrawn = false;
}
if (mNextAppTransitionThumbnail != null && topOpeningApp != null
@@ -8878,6 +8885,7 @@ public class WindowManagerService extends IWindowManager.Stub
winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
if (w.mAppToken != null) {
w.mAppToken.allDrawn = false;
+ w.mAppToken.deferClearAllDrawn = false;
}
}
if (!mResizingWindows.contains(w)) {
@@ -8953,27 +8961,29 @@ public class WindowManagerService extends IWindowManager.Stub
// so we want to leave all of them as undimmed (for
// performance reasons).
mInnerFields.mObscured = true;
- } else if (canBeSeen && (attrFlags & FLAG_DIM_BEHIND) != 0
- && !(w.mAppToken != null && w.mAppToken.hiddenRequested)
+ }
+ }
+
+ private void handleFlagDimBehind(WindowState w, int innerDw, int innerDh) {
+ final WindowManager.LayoutParams attrs = w.mAttrs;
+ if ((attrs.flags & FLAG_DIM_BEHIND) != 0
+ && w.isDisplayedLw()
&& !w.mExiting) {
- if (localLOGV) Slog.v(TAG, "Win " + w + " obscured=" + mInnerFields.mObscured);
- if (!mInnerFields.mDimming) {
- //Slog.i(TAG, "DIM BEHIND: " + w);
- mInnerFields.mDimming = true;
- final WindowStateAnimator winAnimator = w.mWinAnimator;
- if (!mAnimator.isDimmingLocked(winAnimator)) {
- final int width, height;
- if (attrs.type == TYPE_BOOT_PROGRESS) {
- final DisplayInfo displayInfo = w.mDisplayContent.getDisplayInfo();
- width = displayInfo.logicalWidth;
- height = displayInfo.logicalHeight;
- } else {
- width = innerDw;
- height = innerDh;
- }
- startDimmingLocked(
- winAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount, width, height);
+ mInnerFields.mDimming = true;
+ final WindowStateAnimator winAnimator = w.mWinAnimator;
+ if (!mAnimator.isDimmingLocked(winAnimator)) {
+ final int width, height;
+ if (attrs.type == TYPE_BOOT_PROGRESS) {
+ final DisplayInfo displayInfo = w.mDisplayContent.getDisplayInfo();
+ width = displayInfo.logicalWidth;
+ height = displayInfo.logicalHeight;
+ } else {
+ width = innerDw;
+ height = innerDh;
}
+ if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming.");
+ startDimmingLocked(
+ winAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount, width, height);
}
}
}
@@ -9152,6 +9162,10 @@ public class WindowManagerService extends IWindowManager.Stub
handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
}
+ if (!mInnerFields.mDimming) {
+ handleFlagDimBehind(w, innerDw, innerDh);
+ }
+
if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
&& w.isVisibleLw()) {
// This is the wallpaper target and its obscured state
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 7b30c89..4ecc191 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -626,7 +626,14 @@ class WindowStateAnimator {
"createSurface " + this + ": mDrawState=DRAW_PENDING");
mDrawState = DRAW_PENDING;
if (mWin.mAppToken != null) {
- mWin.mAppToken.allDrawn = false;
+ if (mWin.mAppToken.mAppAnimator.animation == null) {
+ mWin.mAppToken.allDrawn = false;
+ mWin.mAppToken.deferClearAllDrawn = false;
+ } else {
+ // Currently animating, persist current state of allDrawn until animation
+ // is complete.
+ mWin.mAppToken.deferClearAllDrawn = true;
+ }
}
mService.makeWindowFreezingScreenIfNeededLocked(mWin);
diff --git a/tests/AppLaunch/Android.mk b/tests/AppLaunch/Android.mk
new file mode 100644
index 0000000..c0560fd
--- /dev/null
+++ b/tests/AppLaunch/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := AppLaunch
+
+LOCAL_CERTIFICATE := platform
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH)) \ No newline at end of file
diff --git a/tests/AppLaunch/AndroidManifest.xml b/tests/AppLaunch/AndroidManifest.xml
new file mode 100644
index 0000000..ac6760b
--- /dev/null
+++ b/tests/AppLaunch/AndroidManifest.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.tests.applaunch"
+ android:sharedUserId="android.uid.system" >
+ <instrumentation android:label="Measure app start up time"
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.tests.applaunch" />
+
+ <application android:label="App Launch Test">
+ <uses-library android:name="android.test.runner" />
+ </application>
+</manifest> \ No newline at end of file
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
new file mode 100644
index 0000000..e9374e0
--- /dev/null
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -0,0 +1,216 @@
+/*
+ * 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.tests.applaunch;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.ProcessErrorStateInfo;
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.test.InstrumentationTestCase;
+import android.test.InstrumentationTestRunner;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This test is intended to measure the time it takes for the apps to start.
+ * Names of the applications are passed in command line, and the
+ * test starts each application, and reports the start up time in milliseconds.
+ * The instrumentation expects the following key to be passed on the command line:
+ * apps - A list of applications to start and their corresponding result keys
+ * in the following format:
+ * -e apps <app name>^<result key>|<app name>^<result key>
+ */
+public class AppLaunch extends InstrumentationTestCase {
+
+ private static final int JOIN_TIMEOUT = 10000;
+ private static final String TAG = "AppLaunch";
+ private static final String KEY_APPS = "apps";
+
+ private Map<String, Intent> mNameToIntent;
+ private Map<String, String> mNameToProcess;
+ private Map<String, String> mNameToResultKey;
+
+ private IActivityManager mAm;
+
+ public void testMeasureStartUpTime() throws RemoteException {
+ InstrumentationTestRunner instrumentation =
+ (InstrumentationTestRunner)getInstrumentation();
+ Bundle args = instrumentation.getBundle();
+ mAm = ActivityManagerNative.getDefault();
+
+ createMappings();
+ parseArgs(args);
+
+ Bundle results = new Bundle();
+ for (String app : mNameToResultKey.keySet()) {
+ try {
+ startApp(app, results);
+ closeApp();
+ } catch (NameNotFoundException e) {
+ Log.i(TAG, "Application " + app + " not found");
+ }
+
+ }
+ instrumentation.sendStatus(0, results);
+ }
+
+ private void parseArgs(Bundle args) {
+ mNameToResultKey = new HashMap<String, String>();
+ String appList = args.getString(KEY_APPS);
+
+ if (appList == null)
+ return;
+
+ String appNames[] = appList.split("\\|");
+ for (String pair : appNames) {
+ String[] parts = pair.split("\\^");
+ if (parts.length != 2) {
+ Log.e(TAG, "The apps key is incorectly formatted");
+ fail();
+ }
+
+ mNameToResultKey.put(parts[0], parts[1]);
+ }
+ }
+
+ private void createMappings() {
+ mNameToIntent = new HashMap<String, Intent>();
+ mNameToProcess = new HashMap<String, String>();
+
+ PackageManager pm = getInstrumentation().getContext()
+ .getPackageManager();
+ Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
+ intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
+ List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0);
+ if (ris == null || ris.isEmpty()) {
+ Log.i(TAG, "Could not find any apps");
+ } else {
+ for (ResolveInfo ri : ris) {
+ Intent startIntent = new Intent(intentToResolve);
+ startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ startIntent.setClassName(ri.activityInfo.packageName,
+ ri.activityInfo.name);
+ mNameToIntent.put(ri.loadLabel(pm).toString(), startIntent);
+ mNameToProcess.put(ri.loadLabel(pm).toString(),
+ ri.activityInfo.processName);
+ }
+ }
+ }
+
+ private void startApp(String appName, Bundle results)
+ throws NameNotFoundException, RemoteException {
+ Log.i(TAG, "Starting " + appName);
+
+ Intent startIntent = mNameToIntent.get(appName);
+ AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent);
+ Thread t = new Thread(runnable);
+ long startTime = System.currentTimeMillis();
+ t.start();
+ try {
+ t.join(JOIN_TIMEOUT);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ if(t.isAlive() || (runnable.getResult() != null &&
+ runnable.getResult().result != ActivityManager.START_SUCCESS)) {
+ Log.w(TAG, "Assuming app " + appName + " crashed.");
+ reportError(appName, mNameToProcess.get(appName), results);
+ return;
+ }
+ long startUpTime = System.currentTimeMillis() - startTime;
+ results.putString(mNameToResultKey.get(appName), String.valueOf(startUpTime));
+ sleep(5000);
+ }
+
+ private void closeApp() {
+ Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+ homeIntent.addCategory(Intent.CATEGORY_HOME);
+ homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ getInstrumentation().getContext().startActivity(homeIntent);
+ sleep(3000);
+ }
+
+ private void sleep(int time) {
+ try {
+ Thread.sleep(time);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+
+ private void reportError(String appName, String processName, Bundle results) {
+ ActivityManager am = (ActivityManager) getInstrumentation()
+ .getContext().getSystemService(Context.ACTIVITY_SERVICE);
+ List<ProcessErrorStateInfo> crashes = am.getProcessesInErrorState();
+ if (crashes != null) {
+ for (ProcessErrorStateInfo crash : crashes) {
+ if (!crash.processName.equals(processName))
+ continue;
+
+ Log.w(TAG, appName + " crashed: " + crash.shortMsg);
+ results.putString(mNameToResultKey.get(appName), crash.shortMsg);
+ return;
+ }
+ }
+
+ results.putString(mNameToResultKey.get(appName),
+ "Crashed for unknown reason");
+ Log.w(TAG, appName
+ + " not found in process list, most likely it is crashed");
+ }
+
+ private class AppLaunchRunnable implements Runnable {
+ private Intent mLaunchIntent;
+ private IActivityManager.WaitResult mResult;
+ public AppLaunchRunnable(Intent intent) {
+ mLaunchIntent = intent;
+ }
+
+ public IActivityManager.WaitResult getResult() {
+ return mResult;
+ }
+
+ public void run() {
+ try {
+ String mimeType = mLaunchIntent.getType();
+ if (mimeType == null && mLaunchIntent.getData() != null
+ && "content".equals(mLaunchIntent.getData().getScheme())) {
+ mimeType = mAm.getProviderMimeType(mLaunchIntent.getData(),
+ UserHandle.USER_CURRENT);
+ }
+
+ mResult = mAm.startActivityAndWait(null, mLaunchIntent, mimeType,
+ null, null, 0, mLaunchIntent.getFlags(), null, null, null,
+ UserHandle.USER_CURRENT);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error launching app", e);
+ }
+ }
+ }
+}
diff --git a/tests/MemoryUsage/Android.mk b/tests/MemoryUsage/Android.mk
index e7bfb4f..0ab793b 100644
--- a/tests/MemoryUsage/Android.mk
+++ b/tests/MemoryUsage/Android.mk
@@ -8,7 +8,8 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := MemoryUsage
-LOCAL_SDK_VERSION := 7
+LOCAL_CERTIFICATE := platform
+LOCAL_JAVA_LIBRARIES := android.test.runner
include $(BUILD_PACKAGE)
diff --git a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
index 5e27ba7..b550957 100644
--- a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
+++ b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
@@ -18,14 +18,17 @@ package com.android.tests.memoryusage;
import android.app.ActivityManager;
import android.app.ActivityManager.ProcessErrorStateInfo;
import android.app.ActivityManager.RunningAppProcessInfo;
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.Debug.MemoryInfo;
+import android.os.RemoteException;
+import android.os.UserHandle;
import android.test.InstrumentationTestCase;
import android.util.Log;
@@ -48,8 +51,9 @@ public class MemoryUsageTest extends InstrumentationTestCase {
private static final int SLEEP_TIME = 1000;
private static final int THRESHOLD = 1024;
- private static final int MAX_ITERATIONS = 10;
- private static final int MIN_ITERATIONS = 4;
+ private static final int MAX_ITERATIONS = 20;
+ private static final int MIN_ITERATIONS = 6;
+ private static final int JOIN_TIMEOUT = 10000;
private static final String TAG = "MemoryUsageInstrumentation";
private static final String KEY_APPS = "apps";
@@ -58,10 +62,13 @@ public class MemoryUsageTest extends InstrumentationTestCase {
private Map<String, String> mNameToProcess;
private Map<String, String> mNameToResultKey;
+ private IActivityManager mAm;
+
public void testMemory() {
MemoryUsageInstrumentation instrumentation =
- (MemoryUsageInstrumentation) getInstrumentation();
+ (MemoryUsageInstrumentation) getInstrumentation();
Bundle args = instrumentation.getBundle();
+ mAm = ActivityManagerNative.getDefault();
createMappings();
parseArgs(args);
@@ -136,7 +143,16 @@ public class MemoryUsageTest extends InstrumentationTestCase {
String process = mNameToProcess.get(appName);
Intent startIntent = mNameToIntent.get(appName);
- getInstrumentation().getContext().startActivity(startIntent);
+
+ AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent);
+ Thread t = new Thread(runnable);
+ t.start();
+ try {
+ t.join(JOIN_TIMEOUT);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+
return process;
}
@@ -234,7 +250,7 @@ public class MemoryUsageTest extends InstrumentationTestCase {
}
int[] pids = {
- proc.pid };
+ proc.pid };
MemoryInfo meminfo = am.getProcessMemoryInfo(pids)[0];
return meminfo.getTotalPss();
@@ -242,4 +258,29 @@ public class MemoryUsageTest extends InstrumentationTestCase {
}
return -1;
}
+
+ private class AppLaunchRunnable implements Runnable {
+ private Intent mLaunchIntent;
+
+ public AppLaunchRunnable(Intent intent) {
+ mLaunchIntent = intent;
+ }
+
+ public void run() {
+ try {
+ String mimeType = mLaunchIntent.getType();
+ if (mimeType == null && mLaunchIntent.getData() != null
+ && "content".equals(mLaunchIntent.getData().getScheme())) {
+ mimeType = mAm.getProviderMimeType(mLaunchIntent.getData(),
+ UserHandle.USER_CURRENT);
+ }
+
+ mAm.startActivityAndWait(null, mLaunchIntent, mimeType,
+ null, null, 0, mLaunchIntent.getFlags(), null, null, null,
+ UserHandle.USER_CURRENT_OR_SELF);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error launching app", e);
+ }
+ }
+ }
}