Merge "Catch badly formed URLs in WebView accessibility injector." into jb-mr1-dev
diff --git a/api/17.txt b/api/17.txt
index ee9a973..84c2a93 100644
--- a/api/17.txt
+++ b/api/17.txt
@@ -28617,7 +28617,6 @@
method public void setHeight(int);
method public void setHorizontalOffset(int);
method public void setInputMethodMode(int);
- method public void setLayoutDirection(int);
method public void setListSelector(android.graphics.drawable.Drawable);
method public void setModal(boolean);
method public void setOnDismissListener(android.widget.PopupWindow.OnDismissListener);
diff --git a/api/current.txt b/api/current.txt
index ee9a973..5462aee 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7094,7 +7094,7 @@
method public int getIndexCount();
method public int getInt(int, int);
method public int getInteger(int, int);
- method public deprecated int getLayoutDimension(int, java.lang.String);
+ method public int getLayoutDimension(int, java.lang.String);
method public int getLayoutDimension(int, int);
method public java.lang.String getNonResourceString(int);
method public java.lang.String getPositionDescription();
@@ -8263,6 +8263,7 @@
method public int getScaledWidth(int);
method public final int getWidth();
method public final boolean hasAlpha();
+ method public final boolean hasMipMap();
method public final boolean isMutable();
method public final boolean isPremultiplied();
method public final boolean isRecycled();
@@ -8271,6 +8272,7 @@
method public boolean sameAs(android.graphics.Bitmap);
method public void setDensity(int);
method public void setHasAlpha(boolean);
+ method public final void setHasMipMap(boolean);
method public void setPixel(int, int, int);
method public void setPixels(int[], int, int, int, int, int, int);
method public void writeToParcel(android.os.Parcel, int);
@@ -16149,7 +16151,7 @@
public class Looper {
method public void dump(android.util.Printer, java.lang.String);
- method public static android.os.Looper getMainLooper();
+ method public static synchronized android.os.Looper getMainLooper();
method public java.lang.Thread getThread();
method public static void loop();
method public static android.os.Looper myLooper();
@@ -28617,7 +28619,6 @@
method public void setHeight(int);
method public void setHorizontalOffset(int);
method public void setInputMethodMode(int);
- method public void setLayoutDirection(int);
method public void setListSelector(android.graphics.drawable.Drawable);
method public void setModal(boolean);
method public void setOnDismissListener(android.widget.PopupWindow.OnDismissListener);
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index a276225..387f33d 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -36,6 +36,7 @@
char pkgdir[PKG_PATH_MAX];
char libsymlink[PKG_PATH_MAX];
char applibdir[PKG_PATH_MAX];
+ struct stat libStat;
if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
ALOGE("invalid uid/gid: %d %d\n", uid, gid);
@@ -67,6 +68,25 @@
return -1;
}
+ if (lstat(libsymlink, &libStat) < 0) {
+ if (errno != ENOENT) {
+ ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
+ return -1;
+ }
+ } else {
+ if (S_ISDIR(libStat.st_mode)) {
+ if (delete_dir_contents(libsymlink, 1, 0) < 0) {
+ ALOGE("couldn't delete lib directory during install for: %s", libsymlink);
+ return -1;
+ }
+ } else if (S_ISLNK(libStat.st_mode)) {
+ if (unlink(libsymlink) < 0) {
+ ALOGE("couldn't unlink lib directory during install for: %s", libsymlink);
+ return -1;
+ }
+ }
+ }
+
if (symlink(applibdir, libsymlink) < 0) {
ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, applibdir,
strerror(errno));
@@ -140,7 +160,7 @@
if (stat(pkgdir, &s) < 0) return -1;
if (s.st_uid != 0 || s.st_gid != 0) {
- ALOGE("fixing uid of non-root pkg: %s %d %d\n", pkgdir, s.st_uid, s.st_gid);
+ ALOGE("fixing uid of non-root pkg: %s %lu %lu\n", pkgdir, s.st_uid, s.st_gid);
return -1;
}
@@ -172,11 +192,23 @@
int make_user_data(const char *pkgname, uid_t uid, uid_t persona)
{
char pkgdir[PKG_PATH_MAX];
+ char applibdir[PKG_PATH_MAX];
+ char libsymlink[PKG_PATH_MAX];
+ struct stat libStat;
// Create the data dir for the package
if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) {
return -1;
}
+ if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, persona)) {
+ ALOGE("cannot create package lib symlink origin path\n");
+ return -1;
+ }
+ if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) {
+ ALOGE("cannot create package lib symlink dest path\n");
+ return -1;
+ }
+
if (mkdir(pkgdir, 0751) < 0) {
ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
return -errno;
@@ -186,8 +218,41 @@
unlink(pkgdir);
return -errno;
}
+
+ if (lstat(libsymlink, &libStat) < 0) {
+ if (errno != ENOENT) {
+ ALOGE("couldn't stat lib dir for non-primary: %s\n", strerror(errno));
+ unlink(pkgdir);
+ return -1;
+ }
+ } else {
+ if (S_ISDIR(libStat.st_mode)) {
+ if (delete_dir_contents(libsymlink, 1, 0) < 0) {
+ ALOGE("couldn't delete lib directory during install for non-primary: %s",
+ libsymlink);
+ unlink(pkgdir);
+ return -1;
+ }
+ } else if (S_ISLNK(libStat.st_mode)) {
+ if (unlink(libsymlink) < 0) {
+ ALOGE("couldn't unlink lib directory during install for non-primary: %s",
+ libsymlink);
+ unlink(pkgdir);
+ return -1;
+ }
+ }
+ }
+
+ if (symlink(applibdir, libsymlink) < 0) {
+ ALOGE("couldn't symlink directory for non-primary '%s' -> '%s': %s\n", libsymlink,
+ applibdir, strerror(errno));
+ unlink(pkgdir);
+ return -1;
+ }
+
if (chown(pkgdir, uid, uid) < 0) {
ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
+ unlink(libsymlink);
unlink(pkgdir);
return -errno;
}
@@ -195,6 +260,7 @@
#ifdef HAVE_SELINUX
if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) {
ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
+ unlink(libsymlink);
unlink(pkgdir);
return -errno;
}
@@ -254,7 +320,7 @@
/* Get the file stat */
if (stat(pkg_path, &s) < 0) continue;
/* Get the uid of the package */
- ALOGI("Adding datadir for uid = %d\n", s.st_uid);
+ ALOGI("Adding datadir for uid = %lu\n", s.st_uid);
uid = (uid_t) s.st_uid % PER_USER_RANGE;
/* Create the directory for the target */
make_user_data(name, uid + target_persona * PER_USER_RANGE,
@@ -991,75 +1057,71 @@
return 0;
}
-int linklib(const char* dataDir, const char* asecLibDir)
+int linklib(const char* pkgname, const char* asecLibDir, int userId)
{
- char libdir[PKG_PATH_MAX];
+ char pkgdir[PKG_PATH_MAX];
+ char libsymlink[PKG_PATH_MAX];
struct stat s, libStat;
int rc = 0;
- const size_t libdirLen = strlen(dataDir) + strlen(PKG_LIB_POSTFIX);
- if (libdirLen >= PKG_PATH_MAX) {
- ALOGE("library dir len too large");
+ if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userId)) {
+ ALOGE("cannot create package path\n");
+ return -1;
+ }
+ if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userId)) {
+ ALOGE("cannot create package lib symlink origin path\n");
return -1;
}
- if (snprintf(libdir, sizeof(libdir), "%s%s", dataDir, PKG_LIB_POSTFIX) != (ssize_t)libdirLen) {
- ALOGE("library dir not written successfully: %s\n", strerror(errno));
+ if (stat(pkgdir, &s) < 0) return -1;
+
+ if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) {
+ ALOGE("failed to chown '%s': %s\n", pkgdir, strerror(errno));
return -1;
}
- if (stat(dataDir, &s) < 0) return -1;
-
- if (chown(dataDir, AID_INSTALL, AID_INSTALL) < 0) {
- ALOGE("failed to chown '%s': %s\n", dataDir, strerror(errno));
- return -1;
- }
-
- if (chmod(dataDir, 0700) < 0) {
- ALOGE("linklib() 1: failed to chmod '%s': %s\n", dataDir, strerror(errno));
+ if (chmod(pkgdir, 0700) < 0) {
+ ALOGE("linklib() 1: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
rc = -1;
goto out;
}
- if (lstat(libdir, &libStat) < 0) {
- ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
- rc = -1;
- goto out;
- }
-
- if (S_ISDIR(libStat.st_mode)) {
- if (delete_dir_contents(libdir, 1, 0) < 0) {
+ if (lstat(libsymlink, &libStat) < 0) {
+ if (errno != ENOENT) {
+ ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
rc = -1;
goto out;
}
- } else if (S_ISLNK(libStat.st_mode)) {
- if (unlink(libdir) < 0) {
- rc = -1;
- goto out;
+ } else {
+ if (S_ISDIR(libStat.st_mode)) {
+ if (delete_dir_contents(libsymlink, 1, 0) < 0) {
+ rc = -1;
+ goto out;
+ }
+ } else if (S_ISLNK(libStat.st_mode)) {
+ if (unlink(libsymlink) < 0) {
+ ALOGE("couldn't unlink lib dir: %s\n", strerror(errno));
+ rc = -1;
+ goto out;
+ }
}
}
- if (symlink(asecLibDir, libdir) < 0) {
- ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libdir, asecLibDir, strerror(errno));
- rc = -errno;
- goto out;
- }
-
- if (lchown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) {
- ALOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno));
- unlink(libdir);
+ if (symlink(asecLibDir, libsymlink) < 0) {
+ ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, asecLibDir,
+ strerror(errno));
rc = -errno;
goto out;
}
out:
- if (chmod(dataDir, s.st_mode) < 0) {
- ALOGE("linklib() 2: failed to chmod '%s': %s\n", dataDir, strerror(errno));
+ if (chmod(pkgdir, s.st_mode) < 0) {
+ ALOGE("linklib() 2: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
rc = -errno;
}
- if (chown(dataDir, s.st_uid, s.st_gid) < 0) {
- ALOGE("failed to chown '%s' : %s\n", dataDir, strerror(errno));
+ if (chown(pkgdir, s.st_uid, s.st_gid) < 0) {
+ ALOGE("failed to chown '%s' : %s\n", pkgdir, strerror(errno));
return -errno;
}
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index 19298a3..21d674a 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -123,7 +123,7 @@
static int do_linklib(char **arg, char reply[REPLY_MAX])
{
- return linklib(arg[0], arg[1]);
+ return linklib(arg[0], arg[1], atoi(arg[2]));
}
struct cmdinfo {
@@ -146,7 +146,7 @@
{ "getsize", 5, do_get_size },
{ "rmuserdata", 2, do_rm_user_data },
{ "movefiles", 0, do_movefiles },
- { "linklib", 2, do_linklib },
+ { "linklib", 3, do_linklib },
{ "mkuserdata", 3, do_mk_user_data },
{ "rmuser", 1, do_rm_user },
{ "cloneuserdata", 3, do_clone_user_data },
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 2540dbe..0500c23 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -188,6 +188,7 @@
char *build_string3(char *s1, char *s2, char *s3);
int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid);
+int ensure_media_user_dirs(userid_t userid);
/* commands.c */
@@ -209,4 +210,4 @@
int free_cache(int64_t free_size);
int dexopt(const char *apk_path, uid_t uid, int is_public);
int movefiles();
-int linklib(const char* target, const char* source);
+int linklib(const char* target, const char* source, int userId);
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 5cde65c..03e0c0f 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -247,7 +247,6 @@
}
public void systemReady() {
- initUser(UserHandle.USER_OWNER);
}
private UserManager getUserManager() {
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 7492629..67d3930 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2809,6 +2809,15 @@
return success;
}
+ public void clearPendingBackup() throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(CLEAR_PENDING_BACKUP_TRANSACTION, data, reply, 0);
+ reply.recycle();
+ data.recycle();
+ }
+
public void backupAgentCreated(String packageName, IBinder agent) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 5f65f08..456d757 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -29,6 +29,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.InstrumentationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ProviderInfo;
@@ -2396,12 +2397,31 @@
private void handleCreateBackupAgent(CreateBackupAgentData data) {
if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data);
+ // Sanity check the requested target package's uid against ours
+ try {
+ PackageInfo requestedPackage = getPackageManager().getPackageInfo(
+ data.appInfo.packageName, 0, UserHandle.myUserId());
+ if (requestedPackage.applicationInfo.uid != Process.myUid()) {
+ Slog.w(TAG, "Asked to instantiate non-matching package "
+ + data.appInfo.packageName);
+ return;
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Can't reach package manager", e);
+ return;
+ }
+
// no longer idle; we have backup work to do
unscheduleGcIdler();
// instantiate the BackupAgent class named in the manifest
LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
String packageName = packageInfo.mPackageName;
+ if (packageName == null) {
+ Slog.d(TAG, "Asked to create backup agent for nonexistent package");
+ return;
+ }
+
if (mBackupAgents.get(packageName) != null) {
Slog.d(TAG, "BackupAgent " + " for " + packageName
+ " already exists");
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 3e1e358..95b6bed 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -77,6 +77,7 @@
import android.nfc.NfcManager;
import android.os.Binder;
import android.os.Bundle;
+import android.os.Debug;
import android.os.DropBoxManager;
import android.os.Environment;
import android.os.FileUtils;
@@ -97,6 +98,7 @@
import android.content.ClipboardManager;
import android.util.AndroidRuntimeException;
import android.util.Log;
+import android.util.Slog;
import android.view.CompatibilityInfoHolder;
import android.view.ContextThemeWrapper;
import android.view.Display;
@@ -925,6 +927,7 @@
@Override
public void startActivity(Intent intent) {
+ warnIfCallingFromSystemProcess();
startActivity(intent, null);
}
@@ -936,6 +939,7 @@
@Override
public void startActivity(Intent intent, Bundle options) {
+ warnIfCallingFromSystemProcess();
if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
throw new AndroidRuntimeException(
"Calling startActivity() from outside of an Activity "
@@ -962,6 +966,7 @@
@Override
public void startActivities(Intent[] intents) {
+ warnIfCallingFromSystemProcess();
startActivities(intents, null);
}
@@ -981,6 +986,7 @@
@Override
public void startActivities(Intent[] intents, Bundle options) {
+ warnIfCallingFromSystemProcess();
if ((intents[0].getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
throw new AndroidRuntimeException(
"Calling startActivities() from outside of an Activity "
@@ -1023,6 +1029,7 @@
@Override
public void sendBroadcast(Intent intent) {
+ warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.setAllowFds(false);
@@ -1036,6 +1043,7 @@
@Override
public void sendBroadcast(Intent intent, String receiverPermission) {
+ warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.setAllowFds(false);
@@ -1050,6 +1058,7 @@
@Override
public void sendOrderedBroadcast(Intent intent,
String receiverPermission) {
+ warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.setAllowFds(false);
@@ -1066,6 +1075,7 @@
String receiverPermission, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData,
Bundle initialExtras) {
+ warnIfCallingFromSystemProcess();
IIntentReceiver rd = null;
if (resultReceiver != null) {
if (mPackageInfo != null) {
@@ -1154,6 +1164,7 @@
@Override
public void sendStickyBroadcast(Intent intent) {
+ warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.setAllowFds(false);
@@ -1170,6 +1181,7 @@
BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData,
Bundle initialExtras) {
+ warnIfCallingFromSystemProcess();
IIntentReceiver rd = null;
if (resultReceiver != null) {
if (mPackageInfo != null) {
@@ -1337,11 +1349,13 @@
@Override
public ComponentName startService(Intent service) {
+ warnIfCallingFromSystemProcess();
return startServiceAsUser(service, mUser);
}
@Override
public boolean stopService(Intent service) {
+ warnIfCallingFromSystemProcess();
return stopServiceAsUser(service, mUser);
}
@@ -1389,6 +1403,7 @@
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
+ warnIfCallingFromSystemProcess();
return bindService(service, conn, flags, UserHandle.getUserId(Process.myUid()));
}
@@ -1697,6 +1712,13 @@
message);
}
+ private void warnIfCallingFromSystemProcess() {
+ if (Process.myUid() == Process.SYSTEM_UID) {
+ Slog.w(TAG, "Calling a method in the system process without a qualified user: "
+ + Debug.getCallers(3));
+ }
+ }
+
@Override
public Context createPackageContext(String packageName, int flags)
throws NameNotFoundException {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 97250e9..8fc1c86 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -152,6 +152,7 @@
public boolean bindBackupAgent(ApplicationInfo appInfo, int backupRestoreMode)
throws RemoteException;
+ public void clearPendingBackup() throws RemoteException;
public void backupAgentCreated(String packageName, IBinder agent) throws RemoteException;
public void unbindBackupAgent(ApplicationInfo appInfo) throws RemoteException;
public void killApplicationProcess(String processName, int uid) throws RemoteException;
@@ -619,4 +620,5 @@
int GET_RUNNING_USER_IDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+156;
int REQUEST_BUG_REPORT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+157;
int INPUT_DISPATCHING_TIMED_OUT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+158;
+ int CLEAR_PENDING_BACKUP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+159;
}
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index 201d7b2..86fd7b9 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -312,7 +312,8 @@
}
public Editor putStringSet(String key, Set<String> values) {
synchronized (this) {
- mModified.put(key, values);
+ mModified.put(key,
+ (values == null) ? null : new HashSet<String>(values));
return this;
}
}
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 3d656c7..829b80c 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -45,6 +45,7 @@
public static final int DISABLE_RECENT = View.STATUS_BAR_DISABLE_RECENT;
public static final int DISABLE_BACK = View.STATUS_BAR_DISABLE_BACK;
public static final int DISABLE_CLOCK = View.STATUS_BAR_DISABLE_CLOCK;
+ public static final int DISABLE_SEARCH = View.STATUS_BAR_DISABLE_SEARCH;
@Deprecated
public static final int DISABLE_NAVIGATION =
@@ -54,7 +55,8 @@
public static final int DISABLE_MASK = DISABLE_EXPAND | DISABLE_NOTIFICATION_ICONS
| DISABLE_NOTIFICATION_ALERTS | DISABLE_NOTIFICATION_TICKER
- | DISABLE_SYSTEM_INFO | DISABLE_RECENT | DISABLE_HOME | DISABLE_BACK | DISABLE_CLOCK;
+ | DISABLE_SYSTEM_INFO | DISABLE_RECENT | DISABLE_HOME | DISABLE_BACK | DISABLE_CLOCK
+ | DISABLE_SEARCH;
public static final int NAVIGATION_HINT_BACK_NOP = 1 << 0;
public static final int NAVIGATION_HINT_HOME_NOP = 1 << 1;
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 97d299a..cf0603e 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2430,7 +2430,8 @@
/**
* Broadcast sent to the system when a user is removed. Carries an extra EXTRA_USER_HANDLE that has
* the userHandle of the user. It is sent to all running users except the
- * one that has been removed. You must hold
+ * one that has been removed. The user will not be completely removed until all receivers have
+ * handled the broadcast. You must hold
* {@link android.Manifest.permission#MANAGE_USERS} to receive this broadcast.
* @hide
*/
diff --git a/core/java/android/content/SharedPreferences.java b/core/java/android/content/SharedPreferences.java
index bdc38d6..da5480e 100644
--- a/core/java/android/content/SharedPreferences.java
+++ b/core/java/android/content/SharedPreferences.java
@@ -25,7 +25,8 @@
* there is a single instance of this class that all clients share.
* Modifications to the preferences must go through an {@link Editor} object
* to ensure the preference values remain in a consistent state and control
- * when they are committed to storage.
+ * when they are committed to storage. Objects that are returned from the
+ * various <code>get</code> methods must be treated as immutable by the application.
*
* <p><em>Note: currently this class does not support use across multiple
* processes. This will be added later.</em>
@@ -226,6 +227,10 @@
/**
* Retrieve all values from the preferences.
*
+ * <p>Note that you <em>must not</em> modify the collection returned
+ * by this method, or alter any of its contents. The consistency of your
+ * stored data is not guaranteed if you do.
+ *
* @return Returns a map containing a list of pairs key/value representing
* the preferences.
*
@@ -250,6 +255,10 @@
/**
* Retrieve a set of String values from the preferences.
*
+ * <p>Note that you <em>must not</em> modify the set instance returned
+ * by this call. The consistency of the stored data is not guaranteed
+ * if you do, nor is your ability to modify the instance at all.
+ *
* @param key The name of the preference to retrieve.
* @param defValues Values to return if this preference does not exist.
*
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 58df167..977b461 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -55,6 +55,7 @@
import android.util.EventLog;
import android.util.Log;
import android.util.Pair;
+import android.util.Slog;
import com.android.internal.R;
import com.android.internal.util.IndentingPrintWriter;
@@ -264,7 +265,9 @@
}
private void doDatabaseCleanup() {
- for (UserInfo user : mUserManager.getUsers()) {
+ for (UserInfo user : mUserManager.getUsers(true)) {
+ // Skip any partially created/removed users
+ if (user.partial) continue;
Account[] accountsForUser = AccountManagerService.getSingleton().getAccounts(user.id);
mSyncStorageEngine.doDatabaseCleanup(accountsForUser, user.id);
}
@@ -311,13 +314,10 @@
if (userId == UserHandle.USER_NULL) return;
if (Intent.ACTION_USER_REMOVED.equals(action)) {
- Log.i(TAG, "User removed: u" + userId);
onUserRemoved(userId);
} else if (Intent.ACTION_USER_STARTING.equals(action)) {
- Log.i(TAG, "User starting: u" + userId);
onUserStarting(userId);
} else if (Intent.ACTION_USER_STOPPING.equals(action)) {
- Log.i(TAG, "User stopping: u" + userId);
onUserStopping(userId);
}
}
@@ -338,6 +338,10 @@
}
}
+ /**
+ * Should only be created after {@link ContentService#systemReady()} so that
+ * {@link PackageManager} is ready to query.
+ */
public SyncManager(Context context, boolean factoryTest) {
// Initialize the SyncStorageEngine first, before registering observers
// and creating threads and so on; it may fail if the disk is full.
@@ -441,9 +445,6 @@
UserHandle.ALL,
new IntentFilter(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION),
null, null);
-
- // do this synchronously to ensure we have the accounts before this call returns
- onUserStarting(UserHandle.USER_OWNER);
}
// Pick a random second in a day to seed all periodic syncs
@@ -2529,7 +2530,7 @@
syncStateIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
syncStateIntent.putExtra("active", mNeedSyncActiveNotification);
syncStateIntent.putExtra("failing", false);
- mContext.sendBroadcast(syncStateIntent);
+ mContext.sendBroadcastAsUser(syncStateIntent, UserHandle.OWNER);
}
private void installHandleTooManyDeletesNotification(Account account, String authority,
diff --git a/core/java/android/content/SyncQueue.java b/core/java/android/content/SyncQueue.java
index 14bfc5b..c9a325e 100644
--- a/core/java/android/content/SyncQueue.java
+++ b/core/java/android/content/SyncQueue.java
@@ -51,8 +51,6 @@
public SyncQueue(SyncStorageEngine syncStorageEngine, final SyncAdaptersCache syncAdapters) {
mSyncStorageEngine = syncStorageEngine;
mSyncAdapters = syncAdapters;
-
- addPendingOperations(UserHandle.USER_OWNER);
}
public void addPendingOperations(int userId) {
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index a0283d3..32cc7fd 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -554,6 +554,7 @@
manageSpaceActivityName = orig.manageSpaceActivityName;
descriptionRes = orig.descriptionRes;
uiOptions = orig.uiOptions;
+ backupAgentName = orig.backupAgentName;
}
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 7f3b6b9..2968fbb 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -469,20 +469,13 @@
* {@link android.view.ViewGroup}'s layout_width and layout_height
* attributes. This is only here for performance reasons; applications
* should use {@link #getDimensionPixelSize}.
- *
+ *
* @param index Index of the attribute to retrieve.
* @param name Textual name of attribute for error reporting.
*
* @return Attribute dimension value multiplied by the appropriate
* metric and truncated to integer pixels.
- *
- * @throws RuntimeException
- * if this TypedArray does not contain an entry for <code>index</code>
- *
- * @deprecated Use {@link #getLayoutDimension(int, int)} instead.
- *
*/
- @Deprecated
public int getLayoutDimension(int index, String name) {
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index 69e1de9..ce5f163 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -110,7 +110,7 @@
* <h2>The 4 steps</h2>
* <p>When an asynchronous task is executed, the task goes through 4 steps:</p>
* <ol>
- * <li>{@link #onPreExecute()}, invoked on the UI thread immediately after the task
+ * <li>{@link #onPreExecute()}, invoked on the UI thread before the task
* is executed. This step is normally used to setup the task, for instance by
* showing a progress bar in the user interface.</li>
* <li>{@link #doInBackground}, invoked on the background thread
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 4820c5e..6c9290b 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -51,12 +51,17 @@
* an exhibition/lean-back experience.</p>
*
* <p>The Dream lifecycle is as follows:</p>
- * <ul>
- * <li>onAttachedToWindow</li>
- * <li>onDreamingStarted</li>
- * <li>onDreamingStopped</li>
- * <li>onDetachedFromWindow</li>
- * </ul>
+ * <ol>
+ * <li>{@link #onAttachedToWindow}
+ * <p>Use this for initial setup, such as calling {@link #setContentView setContentView()}.</li>
+ * <li>{@link #onDreamingStarted}
+ * <p>Your dream has started, so you should begin animations or other behaviors here.</li>
+ * <li>{@link #onDreamingStopped}
+ * <p>Use this to stop the things you started in {@link #onDreamingStarted}.</li>
+ * <li>{@link #onDetachedFromWindow}
+ * <p>Use this to dismantle resources your dream set up. For example, detach from handlers
+ * and listeners.</li>
+ * </ol>
*
* <p>In addition, onCreate and onDestroy (from the Service interface) will also be called, but
* initialization and teardown should be done by overriding the hooks above.</p>
@@ -80,14 +85,40 @@
* android:resource="@xml/my_dream" />
* </service>
* </pre>
- * <p>If specified, additional information for the dream is defined using the
- * <code><{@link android.R.styleable#Dream dream}></code> element. For example:</p>
- * <pre>
- * (in res/xml/my_dream.xml)
*
+ * <p>If specified with the {@code <meta-data>} element,
+ * additional information for the dream is defined using the
+ * {@link android.R.styleable#Dream <dream>} element in a separate XML file.
+ * Currently, the only addtional
+ * information you can provide is for a settings activity that allows the user to configure
+ * the dream behavior. For example:</p>
+ * <p class="code-caption">res/xml/my_dream.xml</p>
+ * <pre>
* <dream xmlns:android="http://schemas.android.com/apk/res/android"
* android:settingsActivity="com.example.app/.MyDreamSettingsActivity" />
* </pre>
+ * <p>This makes a Settings button available alongside your dream's listing in the
+ * system settings, which when pressed opens the specified activity.</p>
+ *
+ *
+ * <p>To specify your dream layout, call {@link #setContentView}, typically during the
+ * {@link #onAttachedToWindow} callback. For example:</p>
+ * <pre>
+ * public class MyDream extends DreamService {
+ *
+ * @Override
+ * public void onAttachedToWindow() {
+ * super.onAttachedToWindow();
+ *
+ * // Exit dream upon user touch
+ * setInteractive(false);
+ * // Hide system UI
+ * setFullscreen(true);
+ * // Set the dream layout
+ * setContentView(R.layout.dream);
+ * }
+ * }
+ * </pre>
*/
public class DreamService extends Service implements Window.Callback {
private final String TAG = DreamService.class.getSimpleName() + "[" + getClass().getSimpleName() + "]";
@@ -323,11 +354,12 @@
/**
* Sets a view to be the content view for this Dream.
- * Behaves similarly to {@link android.app.Activity#setContentView(android.view.View)},
+ * Behaves similarly to {@link android.app.Activity#setContentView(android.view.View)} in an activity,
* including using {@link ViewGroup.LayoutParams#MATCH_PARENT} as the layout height and width of the view.
*
- * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
- * @param view The desired content to display.
+ * <p>Note: This requires a window, so you should usually call it during
+ * {@link #onAttachedToWindow()} and never earlier (you <strong>cannot</strong> call it
+ * during {@link #onCreate}).</p>
*
* @see #setContentView(int)
* @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
@@ -339,9 +371,12 @@
/**
* Sets a view to be the content view for this Dream.
* Behaves similarly to
- * {@link android.app.Activity#setContentView(android.view.View, android.view.ViewGroup.LayoutParams)}.
+ * {@link android.app.Activity#setContentView(android.view.View, android.view.ViewGroup.LayoutParams)}
+ * in an activity.
*
- * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
+ * <p>Note: This requires a window, so you should usually call it during
+ * {@link #onAttachedToWindow()} and never earlier (you <strong>cannot</strong> call it
+ * during {@link #onCreate}).</p>
*
* @param view The desired content to display.
* @param params Layout parameters for the view.
diff --git a/core/java/android/service/dreams/Sandman.java b/core/java/android/service/dreams/Sandman.java
index 70142ce..5f5b079 100644
--- a/core/java/android/service/dreams/Sandman.java
+++ b/core/java/android/service/dreams/Sandman.java
@@ -36,9 +36,6 @@
public final class Sandman {
private static final String TAG = "Sandman";
- private static final int DEFAULT_SCREENSAVER_ENABLED = 1;
- private static final int DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK = 1;
-
// The component name of a special dock app that merely launches a dream.
// We don't want to launch this app when docked because it causes an unnecessary
// activity transition. We just want to start the dream.
@@ -109,14 +106,18 @@
}
private static boolean isScreenSaverEnabled(Context context) {
+ int def = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_dreamsEnabledByDefault) ? 1 : 0;
return Settings.Secure.getIntForUser(context.getContentResolver(),
- Settings.Secure.SCREENSAVER_ENABLED, DEFAULT_SCREENSAVER_ENABLED,
+ Settings.Secure.SCREENSAVER_ENABLED, def,
UserHandle.USER_CURRENT) != 0;
}
private static boolean isScreenSaverActivatedOnDock(Context context) {
+ int def = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault) ? 1 : 0;
return Settings.Secure.getIntForUser(context.getContentResolver(),
- Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
- DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK, UserHandle.USER_CURRENT) != 0;
+ Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, def,
+ UserHandle.USER_CURRENT) != 0;
}
}
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 0d2835a..1fecf81 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -939,27 +939,22 @@
continue;
}
- if (c == null) {
- x += handleText(wp, i, mlimit, i, inext, runIsRtl, c, x, top,
- y, bottom, fmi, needWidth || mlimit < measureLimit);
- } else {
- for (int j = i, jnext; j < mlimit; j = jnext) {
- jnext = mCharacterStyleSpanSet.getNextTransition(mStart + j, mStart + mlimit) -
- mStart;
+ for (int j = i, jnext; j < mlimit; j = jnext) {
+ jnext = mCharacterStyleSpanSet.getNextTransition(mStart + j, mStart + mlimit) -
+ mStart;
- wp.set(mPaint);
- for (int k = 0; k < mCharacterStyleSpanSet.numberOfSpans; k++) {
- // Intentionally using >= and <= as explained above
- if ((mCharacterStyleSpanSet.spanStarts[k] >= mStart + jnext) ||
- (mCharacterStyleSpanSet.spanEnds[k] <= mStart + j)) continue;
+ wp.set(mPaint);
+ for (int k = 0; k < mCharacterStyleSpanSet.numberOfSpans; k++) {
+ // Intentionally using >= and <= as explained above
+ if ((mCharacterStyleSpanSet.spanStarts[k] >= mStart + jnext) ||
+ (mCharacterStyleSpanSet.spanEnds[k] <= mStart + j)) continue;
- CharacterStyle span = mCharacterStyleSpanSet.spans[k];
- span.updateDrawState(wp);
- }
-
- x += handleText(wp, j, jnext, i, inext, runIsRtl, c, x,
- top, y, bottom, fmi, needWidth || jnext < measureLimit);
+ CharacterStyle span = mCharacterStyleSpanSet.spans[k];
+ span.updateDrawState(wp);
}
+
+ x += handleText(wp, j, jnext, i, inext, runIsRtl, c, x,
+ top, y, bottom, fmi, needWidth || jnext < measureLimit);
}
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index ec1695e..59f941d 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -1200,7 +1200,12 @@
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
- status = onPreDraw(dirty);
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "prepareFrame");
+ try {
+ status = onPreDraw(dirty);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
saveCount = canvas.save();
callbacks.onHardwarePreDraw(canvas);
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index f692e05..26a5b26 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -20,7 +20,6 @@
import android.os.Handler;
import android.os.Message;
import android.widget.FrameLayout;
-import com.android.internal.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -44,20 +43,20 @@
*
* <pre>LayoutInflater inflater = (LayoutInflater)context.getSystemService
* (Context.LAYOUT_INFLATER_SERVICE);</pre>
- *
+ *
* <p>
* To create a new LayoutInflater with an additional {@link Factory} for your
* own views, you can use {@link #cloneInContext} to clone an existing
* ViewFactory, and then call {@link #setFactory} on it to include your
* Factory.
- *
+ *
* <p>
* For performance reasons, view inflation relies heavily on pre-processing of
* XML files that is done at build time. Therefore, it is not currently possible
* to use LayoutInflater with an XmlPullParser over a plain XML file at runtime;
* it only works with an XmlPullParser returned from a compiled resource
* (R.<em>something</em> file.)
- *
+ *
* @see Context#getSystemService
*/
public abstract class LayoutInflater {
@@ -83,7 +82,7 @@
private static final HashMap<String, Constructor<? extends View>> sConstructorMap =
new HashMap<String, Constructor<? extends View>>();
-
+
private HashMap<String, Boolean> mFilterMap;
private static final String TAG_MERGE = "merge";
@@ -94,36 +93,36 @@
/**
* Hook to allow clients of the LayoutInflater to restrict the set of Views that are allowed
* to be inflated.
- *
+ *
*/
public interface Filter {
/**
* Hook to allow clients of the LayoutInflater to restrict the set of Views
* that are allowed to be inflated.
- *
+ *
* @param clazz The class object for the View that is about to be inflated
- *
+ *
* @return True if this class is allowed to be inflated, or false otherwise
*/
@SuppressWarnings("unchecked")
boolean onLoadClass(Class clazz);
}
-
+
public interface Factory {
/**
* Hook you can supply that is called when inflating from a LayoutInflater.
* You can use this to customize the tag names available in your XML
* layout files.
- *
+ *
* <p>
* Note that it is good practice to prefix these custom names with your
* package (i.e., com.coolcompany.apps) to avoid conflicts with system
* names.
- *
+ *
* @param name Tag name to be inflated.
* @param context The context the view is being created in.
* @param attrs Inflation attributes as specified in XML file.
- *
+ *
* @return View Newly created view. Return null for the default
* behavior.
*/
@@ -151,14 +150,14 @@
private static class FactoryMerger implements Factory2 {
private final Factory mF1, mF2;
private final Factory2 mF12, mF22;
-
+
FactoryMerger(Factory f1, Factory2 f12, Factory f2, Factory2 f22) {
mF1 = f1;
mF2 = f2;
mF12 = f12;
mF22 = f22;
}
-
+
public View onCreateView(String name, Context context, AttributeSet attrs) {
View v = mF1.onCreateView(name, context, attrs);
if (v != null) return v;
@@ -173,13 +172,13 @@
: mF2.onCreateView(name, context, attrs);
}
}
-
+
/**
* Create a new LayoutInflater instance associated with a particular Context.
* Applications will almost always want to use
* {@link Context#getSystemService Context.getSystemService()} to retrieve
* the standard {@link Context#LAYOUT_INFLATER_SERVICE Context.INFLATER_SERVICE}.
- *
+ *
* @param context The Context in which this LayoutInflater will create its
* Views; most importantly, this supplies the theme from which the default
* values for their attributes are retrieved.
@@ -192,7 +191,7 @@
* Create a new LayoutInflater instance that is a copy of an existing
* LayoutInflater, optionally with its Context changed. For use in
* implementing {@link #cloneInContext}.
- *
+ *
* @param original The original LayoutInflater to copy.
* @param newContext The new Context to use.
*/
@@ -203,7 +202,7 @@
mPrivateFactory = original.mPrivateFactory;
mFilter = original.mFilter;
}
-
+
/**
* Obtains the LayoutInflater from the given context.
*/
@@ -221,15 +220,15 @@
* pointing to a different Context than the original. This is used by
* {@link ContextThemeWrapper} to create a new LayoutInflater to go along
* with the new Context theme.
- *
+ *
* @param newContext The new Context to associate with the new LayoutInflater.
* May be the same as the original Context if desired.
- *
+ *
* @return Returns a brand spanking new LayoutInflater object associated with
* the given Context.
*/
public abstract LayoutInflater cloneInContext(Context newContext);
-
+
/**
* Return the context we are running in, for access to resources, class
* loader, etc.
@@ -265,7 +264,7 @@
* called on each element name as the xml is parsed. If the factory returns
* a View, that is added to the hierarchy. If it returns null, the next
* factory default {@link #onCreateView} method is called.
- *
+ *
* <p>If you have an existing
* LayoutInflater and want to add your own factory to it, use
* {@link #cloneInContext} to clone the existing instance and then you
@@ -321,13 +320,13 @@
public Filter getFilter() {
return mFilter;
}
-
+
/**
* Sets the {@link Filter} to by this LayoutInflater. If a view is attempted to be inflated
* which is not allowed by the {@link Filter}, the {@link #inflate(int, ViewGroup)} call will
* throw an {@link InflateException}. This filter will replace any previous filter set on this
* LayoutInflater.
- *
+ *
* @param filter The Filter which restricts the set of Views that are allowed to be inflated.
* This filter will replace any previous filter set on this LayoutInflater.
*/
@@ -341,7 +340,7 @@
/**
* Inflate a new view hierarchy from the specified xml resource. Throws
* {@link InflateException} if there is an error.
- *
+ *
* @param resource ID for an XML layout resource to load (e.g.,
* <code>R.layout.main_page</code>)
* @param root Optional view to be the parent of the generated hierarchy.
@@ -361,7 +360,7 @@
* reasons, view inflation relies heavily on pre-processing of XML files
* that is done at build time. Therefore, it is not currently possible to
* use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
- *
+ *
* @param parser XML dom node containing the description of the view
* hierarchy.
* @param root Optional view to be the parent of the generated hierarchy.
@@ -376,7 +375,7 @@
/**
* Inflate a new view hierarchy from the specified xml resource. Throws
* {@link InflateException} if there is an error.
- *
+ *
* @param resource ID for an XML layout resource to load (e.g.,
* <code>R.layout.main_page</code>)
* @param root Optional view to be the parent of the generated hierarchy (if
@@ -408,7 +407,7 @@
* reasons, view inflation relies heavily on pre-processing of XML files
* that is done at build time. Therefore, it is not currently possible to
* use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
- *
+ *
* @param parser XML dom node containing the description of the view
* hierarchy.
* @param root Optional view to be the parent of the generated hierarchy (if
@@ -443,7 +442,7 @@
}
final String name = parser.getName();
-
+
if (DEBUG) {
System.out.println("**************************");
System.out.println("Creating root view: "
@@ -529,17 +528,17 @@
* Low-level function for instantiating a view by name. This attempts to
* instantiate a view class of the given <var>name</var> found in this
* LayoutInflater's ClassLoader.
- *
+ *
* <p>
* There are two things that can happen in an error case: either the
* exception describing the error will be thrown, or a null will be
* returned. You must deal with both possibilities -- the former will happen
* the first time createView() is called for a class of a particular name,
* the latter every time there-after for that class name.
- *
+ *
* @param name The full name of the class to be instantiated.
* @param attrs The XML attributes supplied for this instance.
- *
+ *
* @return View The newly instantiated view, or null.
*/
public final View createView(String name, String prefix, AttributeSet attrs)
@@ -552,7 +551,7 @@
// Class not found in the cache, see if it's real, and try to add it
clazz = mContext.getClassLoader().loadClass(
prefix != null ? (prefix + name) : name).asSubclass(View.class);
-
+
if (mFilter != null && clazz != null) {
boolean allowed = mFilter.onLoadClass(clazz);
if (!allowed) {
@@ -570,7 +569,7 @@
// New class -- remember whether it is allowed
clazz = mContext.getClassLoader().loadClass(
prefix != null ? (prefix + name) : name).asSubclass(View.class);
-
+
boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
mFilterMap.put(name, allowed);
if (!allowed) {
@@ -633,10 +632,10 @@
* given the xml element name. Override it to handle custom view objects. If
* you override this in your subclass be sure to call through to
* super.onCreateView(name) for names you do not recognize.
- *
+ *
* @param name The fully qualified class name of the View to be create.
* @param attrs An AttributeSet of attributes to apply to the View.
- *
+ *
* @return View The View created.
*/
protected View onCreateView(String name, AttributeSet attrs)
@@ -680,7 +679,7 @@
if (view == null && mPrivateFactory != null) {
view = mPrivateFactory.onCreateView(parent, name, mContext, attrs);
}
-
+
if (view == null) {
if (-1 == name.indexOf('.')) {
view = onCreateView(parent, name, attrs);
@@ -727,7 +726,7 @@
}
final String name = parser.getName();
-
+
if (TAG_REQUEST_FOCUS.equals(name)) {
parseRequestFocus(parser, parent);
} else if (TAG_INCLUDE.equals(name)) {
@@ -742,7 +741,7 @@
final ViewGroup viewGroup = (ViewGroup) parent;
final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
rInflate(parser, view, attrs, true);
- viewGroup.addView(view, params);
+ viewGroup.addView(view, params);
} else {
final View view = createViewFromTag(parent, name, attrs);
final ViewGroup viewGroup = (ViewGroup) parent;
@@ -811,14 +810,21 @@
// We try to load the layout params set in the <include /> tag. If
// they don't exist, we will rely on the layout params set in the
// included XML file.
- TypedArray ta = getContext().obtainStyledAttributes(attrs,
- R.styleable.ViewGroup_Layout);
- boolean definesBothWidthAndHeight =
- ta.hasValue(R.styleable.ViewGroup_Layout_layout_width) &&
- ta.hasValue(R.styleable.ViewGroup_Layout_layout_height);
- AttributeSet attributes = definesBothWidthAndHeight ? attrs : childAttrs;
- view.setLayoutParams(group.generateLayoutParams(attributes));
- ta.recycle();
+ // During a layoutparams generation, a runtime exception is thrown
+ // if either layout_width or layout_height is missing. We catch
+ // this exception and set localParams accordingly: true means we
+ // successfully loaded layout params from the <include /> tag,
+ // false means we need to rely on the included layout params.
+ ViewGroup.LayoutParams params = null;
+ try {
+ params = group.generateLayoutParams(attrs);
+ } catch (RuntimeException e) {
+ params = group.generateLayoutParams(childAttrs);
+ } finally {
+ if (params != null) {
+ view.setLayoutParams(params);
+ }
+ }
// Inflate all children.
rInflate(childParser, view, childAttrs, true);
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 7ef6939..183b012 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -258,7 +258,7 @@
private native void nativeSetLayerStack(int layerStack);
private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
- private static native IBinder nativeCreateDisplay(String name);
+ private static native IBinder nativeCreateDisplay(String name, boolean secure);
private static native void nativeSetDisplaySurface(
IBinder displayToken, Surface surface);
private static native void nativeSetDisplayLayerStack(
@@ -597,11 +597,11 @@
}
/** @hide */
- public static IBinder createDisplay(String name) {
+ public static IBinder createDisplay(String name, boolean secure) {
if (name == null) {
throw new IllegalArgumentException("name must not be null");
}
- return nativeCreateDisplay(name);
+ return nativeCreateDisplay(name, secure);
}
/** @hide */
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b4ba871..f5e259e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2452,6 +2452,17 @@
/**
* @hide
+ *
+ * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
+ * out of the public fields to keep the undefined bits out of the developer's way.
+ *
+ * Flag to disable the global search gesture. Don't use this
+ * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
+ */
+ public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
+
+ /**
+ * @hide
*/
public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
@@ -8232,6 +8243,7 @@
case MotionEvent.ACTION_CANCEL:
setPressed(false);
removeTapCallback();
+ removeLongPressCallback();
break;
case MotionEvent.ACTION_MOVE:
@@ -10002,8 +10014,10 @@
/**
* Resolve the layout parameters depending on the resolved layout direction
+ *
+ * @hide
*/
- private void resolveLayoutParams() {
+ public void resolveLayoutParams() {
if (mLayoutParams != null) {
mLayoutParams.resolveLayoutDirection(getLayoutDirection());
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 9ce7df9..c252c77 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3383,7 +3383,7 @@
}
if (child.isLayoutDirectionInherited()) {
- child.resetResolvedLayoutDirection();
+ child.resetRtlProperties();
child.resolveRtlPropertiesIfNeeded();
}
@@ -5362,6 +5362,19 @@
* @hide
*/
@Override
+ public void resolveLayoutParams() {
+ super.resolveLayoutParams();
+ int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ child.resolveLayoutParams();
+ }
+ }
+
+ /**
+ * @hide
+ */
+ @Override
public void resetRtlProperties() {
super.resetRtlProperties();
int count = getChildCount();
@@ -5611,19 +5624,15 @@
}
/**
- * Extracts the <code>width</code> and <code>height</code> layout parameters
- * from the supplied TypedArray, <code>a</code>, and assigns them
- * to the appropriate fields. If, <code>a</code>, does not contain an
- * entry for either attribute, the value, {@link ViewGroup.LayoutParams#WRAP_CONTENT},
- * is used as a default.
+ * Extracts the layout parameters from the supplied attributes.
*
* @param a the style attributes to extract the parameters from
* @param widthAttr the identifier of the width attribute
* @param heightAttr the identifier of the height attribute
*/
protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
- width = a.getLayoutDimension(widthAttr, WRAP_CONTENT);
- height = a.getLayoutDimension(heightAttr, WRAP_CONTENT);
+ width = a.getLayoutDimension(widthAttr, "layout_width");
+ height = a.getLayoutDimension(heightAttr, "layout_height");
}
/**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 91df4b5..8a82a54 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -317,6 +317,8 @@
private final int mDensity;
private final int mNoncompatDensity;
+ private int mViewLayoutDirectionInitial;
+
/**
* Consistency verifier for debugging purposes.
*/
@@ -465,6 +467,7 @@
synchronized (this) {
if (mView == null) {
mView = view;
+ mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
mFallbackEventHandler.setView(view);
mWindowAttributes.copyFrom(attrs);
attrs = mWindowAttributes;
@@ -887,11 +890,13 @@
// Intersect with the bounds of the window to skip
// updates that lie outside of the visible region
final float appScale = mAttachInfo.mApplicationScale;
- localDirty.intersect(0, 0,
- (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));
-
- if (!mWillDrawSoon) {
- scheduleTraversals();
+ if (localDirty.intersect(0, 0,
+ (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f))) {
+ if (!mWillDrawSoon) {
+ scheduleTraversals();
+ }
+ } else {
+ localDirty.setEmpty();
}
return null;
@@ -1184,6 +1189,10 @@
viewVisibilityChanged = false;
mLastConfiguration.setTo(host.getResources().getConfiguration());
mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
+ // Set the layout direction if it has not been set before (inherit is the default)
+ if (mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
+ host.setLayoutDirection(mLastConfiguration.getLayoutDirection());
+ }
host.dispatchAttachedToWindow(attachInfo, 0);
mFitSystemWindowsInsets.set(mAttachInfo.mContentInsets);
host.fitSystemWindows(mFitSystemWindowsInsets);
@@ -2676,7 +2685,13 @@
// the one in them which may be newer.
config = mView.getResources().getConfiguration();
if (force || mLastConfiguration.diff(config) != 0) {
+ final int lastLayoutDirection = mLastConfiguration.getLayoutDirection();
+ final int currentLayoutDirection = config.getLayoutDirection();
mLastConfiguration.setTo(config);
+ if (lastLayoutDirection != currentLayoutDirection &&
+ mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
+ mView.setLayoutDirection(currentLayoutDirection);
+ }
mView.dispatchConfigurationChanged(config);
}
}
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 7855763c..5cdc1ed 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -99,6 +99,7 @@
public static final int ADD_STARTING_NOT_NEEDED = -6;
public static final int ADD_MULTIPLE_SINGLETON = -7;
public static final int ADD_PERMISSION_DENIED = -8;
+ public static final int ADD_INVALID_DISPLAY = -9;
private static WindowManagerGlobal sDefaultWindowManager;
private static IWindowManager sWindowManagerService;
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 75d1471..f0eb94f 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -1093,7 +1093,6 @@
mPopup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NEEDED);
mPopup.setListItemExpandMax(EXPAND_MAX);
}
- mPopup.setLayoutDirection(getLayoutDirection());
mPopup.show();
mPopup.getListView().setOverScrollMode(View.OVER_SCROLL_ALWAYS);
}
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 45f30df..e158776 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -608,12 +608,6 @@
*/
public int gravity = -1;
- @Override
- protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
- width = a.getLayoutDimension(widthAttr, MATCH_PARENT);
- height = a.getLayoutDimension(heightAttr, MATCH_PARENT);
- }
-
/**
* {@inheritDoc}
*/
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 1c81d11..3d6b69e 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -1021,8 +1021,6 @@
mDropDownList.setOnItemSelectedListener(mItemSelectedListener);
}
- mDropDownList.setLayoutDirection(mLayoutDirection);
-
dropDownView = mDropDownList;
View hintView = mPromptView;
@@ -1132,21 +1130,6 @@
}
/**
- * Set the layout direction for this popup. Should be a resolved direction as the
- * popup as no capacity to do the resolution on his own.
- *
- * @param layoutDirection One of {@link View#LAYOUT_DIRECTION_LTR},
- * {@link View#LAYOUT_DIRECTION_RTL},
- *
- */
- public void setLayoutDirection(int layoutDirection) {
- mLayoutDirection = layoutDirection;
- if (mDropDownList != null) {
- mDropDownList.setLayoutDirection(mLayoutDirection);
- }
- }
-
- /**
* <p>Wrapper class for a ListView. This wrapper can hijack the focus to
* make sure the list uses the appropriate drawables and states when
* displayed on screen within a drop down. The focus is never actually
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index af3365e..b71649a 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -142,6 +142,8 @@
};
private int mAnchorXoff, mAnchorYoff;
+ private boolean mPopupViewInitialLayoutDirectionInherited;
+
/**
* <p>Create a new empty, non focusable popup window of dimension (0,0).</p>
*
@@ -968,6 +970,8 @@
} else {
mPopupView = mContentView;
}
+ mPopupViewInitialLayoutDirectionInherited =
+ (mPopupView.getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT);
mPopupWidth = p.width;
mPopupHeight = p.height;
}
@@ -985,9 +989,19 @@
p.packageName = mContext.getPackageName();
}
mPopupView.setFitsSystemWindows(mLayoutInsetDecor);
+ setLayoutDirectionFromAnchor();
mWindowManager.addView(mPopupView, p);
}
+ private void setLayoutDirectionFromAnchor() {
+ if (mAnchor != null) {
+ View anchor = mAnchor.get();
+ if (anchor != null && mPopupViewInitialLayoutDirectionInherited) {
+ mPopupView.setLayoutDirection(anchor.getLayoutDirection());
+ }
+ }
+ }
+
/**
* <p>Generate the layout parameters for the popup window.</p>
*
@@ -1304,8 +1318,9 @@
p.flags = newFlags;
update = true;
}
-
+
if (update) {
+ setLayoutDirectionFromAnchor();
mWindowManager.updateViewLayout(mPopupView, p);
}
}
@@ -1406,6 +1421,7 @@
}
if (update) {
+ setLayoutDirectionFromAnchor();
mWindowManager.updateViewLayout(mPopupView, p);
}
}
@@ -1482,7 +1498,7 @@
} else {
updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff));
}
-
+
update(p.x, p.y, width, height, x != p.x || y != p.y);
}
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index 42d63b2..78d05b0 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -297,6 +297,33 @@
public LayoutParams(MarginLayoutParams source) {
super(source);
}
+
+ /**
+ * <p>Fixes the child's width to
+ * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} and the child's
+ * height to {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}
+ * when not specified in the XML file.</p>
+ *
+ * @param a the styled attributes set
+ * @param widthAttr the width attribute to fetch
+ * @param heightAttr the height attribute to fetch
+ */
+ @Override
+ protected void setBaseAttributes(TypedArray a,
+ int widthAttr, int heightAttr) {
+
+ if (a.hasValue(widthAttr)) {
+ width = a.getLayoutDimension(widthAttr, "layout_width");
+ } else {
+ width = WRAP_CONTENT;
+ }
+
+ if (a.hasValue(heightAttr)) {
+ height = a.getLayoutDimension(heightAttr, "layout_height");
+ } else {
+ height = WRAP_CONTENT;
+ }
+ }
}
/**
diff --git a/core/java/android/widget/TableLayout.java b/core/java/android/widget/TableLayout.java
index 113299a..399b4fa 100644
--- a/core/java/android/widget/TableLayout.java
+++ b/core/java/android/widget/TableLayout.java
@@ -741,9 +741,14 @@
* @param heightAttr the height attribute to fetch
*/
@Override
- protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
+ protected void setBaseAttributes(TypedArray a,
+ int widthAttr, int heightAttr) {
this.width = MATCH_PARENT;
- this.height = a.getLayoutDimension(heightAttr, WRAP_CONTENT);
+ if (a.hasValue(heightAttr)) {
+ this.height = a.getLayoutDimension(heightAttr, "layout_height");
+ } else {
+ this.height = WRAP_CONTENT;
+ }
}
}
diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java
index 3f8f9dae..68ffd73 100644
--- a/core/java/android/widget/TableRow.java
+++ b/core/java/android/widget/TableRow.java
@@ -505,8 +505,19 @@
@Override
protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
- width = a.getLayoutDimension(widthAttr, MATCH_PARENT);
- height = a.getLayoutDimension(heightAttr, WRAP_CONTENT);
+ // We don't want to force users to specify a layout_width
+ if (a.hasValue(widthAttr)) {
+ width = a.getLayoutDimension(widthAttr, "layout_width");
+ } else {
+ width = MATCH_PARENT;
+ }
+
+ // We don't want to force users to specify a layout_height
+ if (a.hasValue(heightAttr)) {
+ height = a.getLayoutDimension(heightAttr, "layout_height");
+ } else {
+ height = WRAP_CONTENT;
+ }
}
}
diff --git a/core/java/com/android/internal/app/IMediaContainerService.aidl b/core/java/com/android/internal/app/IMediaContainerService.aidl
index c82834f7..03d3b22 100755
--- a/core/java/com/android/internal/app/IMediaContainerService.aidl
+++ b/core/java/com/android/internal/app/IMediaContainerService.aidl
@@ -36,4 +36,5 @@
/** Return file system stats: [0] is total bytes, [1] is available bytes */
long[] getFileSystemStats(in String path);
void clearDirectory(in String directory);
+ long calculateInstalledSize(in String packagePath, boolean isForwardLocked);
}
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index 7287327..c9b7cb3 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -70,6 +70,47 @@
this.key = key;
}
+ public VpnProfile(Parcel in) {
+ key = in.readString();
+ name = in.readString();
+ type = in.readInt();
+ server = in.readString();
+ username = in.readString();
+ password = in.readString();
+ dnsServers = in.readString();
+ searchDomains = in.readString();
+ routes = in.readString();
+ mppe = in.readInt() != 0;
+ l2tpSecret = in.readString();
+ ipsecIdentifier = in.readString();
+ ipsecSecret = in.readString();
+ ipsecUserCert = in.readString();
+ ipsecCaCert = in.readString();
+ ipsecServerCert = in.readString();
+ saveLogin = in.readInt() != 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(key);
+ out.writeString(name);
+ out.writeInt(type);
+ out.writeString(server);
+ out.writeString(username);
+ out.writeString(password);
+ out.writeString(dnsServers);
+ out.writeString(searchDomains);
+ out.writeString(routes);
+ out.writeInt(mppe ? 1 : 0);
+ out.writeString(l2tpSecret);
+ out.writeString(ipsecIdentifier);
+ out.writeString(ipsecSecret);
+ out.writeString(ipsecUserCert);
+ out.writeString(ipsecCaCert);
+ out.writeString(ipsecServerCert);
+ out.writeInt(saveLogin ? 1 : 0);
+ }
+
public static VpnProfile decode(String key, byte[] value) {
try {
if (key == null) {
@@ -155,17 +196,10 @@
}
}
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(key);
- out.writeByteArray(encode());
- }
-
public static final Creator<VpnProfile> CREATOR = new Creator<VpnProfile>() {
@Override
public VpnProfile createFromParcel(Parcel in) {
- final String key = in.readString();
- return decode(key, in.createByteArray());
+ return new VpnProfile(in);
}
@Override
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index fd7a6a7..63683b4 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -7,7 +7,7 @@
#include "SkUnPreMultiply.h"
#include <binder/Parcel.h>
-#include "android_os_Parcel.h"
+#include "android_os_Parcel.h"
#include "android_util_Binder.h"
#include "android_nio_utils.h"
#include "CreateJavaOutputStreamAdaptor.h"
@@ -261,14 +261,14 @@
delete bitmap;
}
-static void Bitmap_recycle(JNIEnv* env, jobject, SkBitmap* bitmap) {
+static jboolean Bitmap_recycle(JNIEnv* env, jobject, SkBitmap* bitmap) {
#ifdef USE_OPENGL_RENDERER
if (android::uirenderer::Caches::hasInstance()) {
- android::uirenderer::Caches::getInstance().resourceCache.recycle(bitmap);
- return;
+ return android::uirenderer::Caches::getInstance().resourceCache.recycle(bitmap);
}
#endif // USE_OPENGL_RENDERER
bitmap->setPixels(NULL, NULL);
+ return true;
}
// These must match the int values in Bitmap.java
@@ -353,6 +353,15 @@
bitmap->setIsOpaque(!hasAlpha);
}
+static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, SkBitmap* bitmap) {
+ return bitmap->hasHardwareMipMap();
+}
+
+static void Bitmap_setHasMipMap(JNIEnv* env, jobject, SkBitmap* bitmap,
+ jboolean hasMipMap) {
+ bitmap->setHasHardwareMipMap(hasMipMap);
+}
+
///////////////////////////////////////////////////////////////////////////////
static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
@@ -656,7 +665,7 @@
{ "nativeCopy", "(IIZ)Landroid/graphics/Bitmap;",
(void*)Bitmap_copy },
{ "nativeDestructor", "(I)V", (void*)Bitmap_destructor },
- { "nativeRecycle", "(I)V", (void*)Bitmap_recycle },
+ { "nativeRecycle", "(I)Z", (void*)Bitmap_recycle },
{ "nativeCompress", "(IIILjava/io/OutputStream;[B)Z",
(void*)Bitmap_compress },
{ "nativeErase", "(II)V", (void*)Bitmap_erase },
@@ -666,6 +675,8 @@
{ "nativeConfig", "(I)I", (void*)Bitmap_config },
{ "nativeHasAlpha", "(I)Z", (void*)Bitmap_hasAlpha },
{ "nativeSetHasAlpha", "(IZ)V", (void*)Bitmap_setHasAlpha },
+ { "nativeHasMipMap", "(I)Z", (void*)Bitmap_hasMipMap },
+ { "nativeSetHasMipMap", "(IZ)V", (void*)Bitmap_setHasMipMap },
{ "nativeCreateFromParcel",
"(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
(void*)Bitmap_createFromParcel },
diff --git a/core/jni/android/graphics/YuvToJpegEncoder.cpp b/core/jni/android/graphics/YuvToJpegEncoder.cpp
index 8333e00..f386905 100644
--- a/core/jni/android/graphics/YuvToJpegEncoder.cpp
+++ b/core/jni/android/graphics/YuvToJpegEncoder.cpp
@@ -90,8 +90,9 @@
// process 16 lines of Y and 8 lines of U/V each time.
while (cinfo->next_scanline < cinfo->image_height) {
//deitnerleave u and v
- deinterleave(vuPlanar, uRows, vRows, cinfo->next_scanline, width);
+ deinterleave(vuPlanar, uRows, vRows, cinfo->next_scanline, width, height);
+ // Jpeg library ignores the rows whose indices are greater than height.
for (int i = 0; i < 16; i++) {
// y row
y[i] = yPlanar + (cinfo->next_scanline + i) * fStrides[0];
@@ -112,8 +113,10 @@
}
void Yuv420SpToJpegEncoder::deinterleave(uint8_t* vuPlanar, uint8_t* uRows,
- uint8_t* vRows, int rowIndex, int width) {
- for (int row = 0; row < 8; ++row) {
+ uint8_t* vRows, int rowIndex, int width, int height) {
+ int numRows = (height - rowIndex) / 2;
+ if (numRows > 8) numRows = 8;
+ for (int row = 0; row < numRows; ++row) {
int offset = ((rowIndex >> 1) + row) * fStrides[1];
uint8_t* vu = vuPlanar + offset;
for (int i = 0; i < (width >> 1); ++i) {
@@ -164,6 +167,7 @@
while (cinfo->next_scanline < cinfo->image_height) {
deinterleave(yuvOffset, yRows, uRows, vRows, cinfo->next_scanline, width, height);
+ // Jpeg library ignores the rows whose indices are greater than height.
for (int i = 0; i < 16; i++) {
// y row
y[i] = yRows + i * width;
@@ -185,7 +189,9 @@
void Yuv422IToJpegEncoder::deinterleave(uint8_t* yuv, uint8_t* yRows, uint8_t* uRows,
uint8_t* vRows, int rowIndex, int width, int height) {
- for (int row = 0; row < 16; ++row) {
+ int numRows = height - rowIndex;
+ if (numRows > 16) numRows = 16;
+ for (int row = 0; row < numRows; ++row) {
uint8_t* yuvSeg = yuv + (rowIndex + row) * fStrides[0];
for (int i = 0; i < (width >> 1); ++i) {
int indexY = row * width + (i << 1);
diff --git a/core/jni/android/graphics/YuvToJpegEncoder.h b/core/jni/android/graphics/YuvToJpegEncoder.h
index 97106ce..0d418ed 100644
--- a/core/jni/android/graphics/YuvToJpegEncoder.h
+++ b/core/jni/android/graphics/YuvToJpegEncoder.h
@@ -55,7 +55,7 @@
void deinterleaveYuv(uint8_t* yuv, int width, int height,
uint8_t*& yPlanar, uint8_t*& uPlanar, uint8_t*& vPlanar);
void deinterleave(uint8_t* vuPlanar, uint8_t* uRows, uint8_t* vRows,
- int rowIndex, int width);
+ int rowIndex, int width, int height);
void compress(jpeg_compress_struct* cinfo, uint8_t* yuv, int* offsets);
};
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 1b71b43..5d306d2 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -829,7 +829,6 @@
static void android_view_GLES20Canvas_setTextureLayerTransform(JNIEnv* env, jobject clazz,
Layer* layer, SkMatrix* matrix) {
-
layer->getTransform().load(*matrix);
}
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 531445f..8a2c88c 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -653,9 +653,11 @@
return javaObjectForIBinder(env, token);
}
-static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj) {
+static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj,
+ jboolean secure) {
ScopedUtfChars name(env, nameObj);
- sp<IBinder> token(SurfaceComposerClient::createDisplay(String8(name.c_str())));
+ sp<IBinder> token(SurfaceComposerClient::createDisplay(
+ String8(name.c_str()), bool(secure)));
return javaObjectForIBinder(env, token);
}
@@ -845,7 +847,7 @@
(void*)nativeSetLayerStack },
{"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;",
(void*)nativeGetBuiltInDisplay },
- {"nativeCreateDisplay", "(Ljava/lang/String;)Landroid/os/IBinder;",
+ {"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;",
(void*)nativeCreateDisplay },
{"nativeSetDisplaySurface", "(Landroid/os/IBinder;Landroid/view/Surface;)V",
(void*)nativeSetDisplaySurface },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index aa67ec2..92aa06a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2032,7 +2032,7 @@
<permission android:name="android.permission.SERIAL_PORT"
android:label="@string/permlab_serialPort"
android:description="@string/permdesc_serialPort"
- android:protectionLevel="normal" />
+ android:protectionLevel="signature|system" />
<!-- Allows the holder to access content providers from outside an ApplicationThread.
This permission is enforced by the ActivityManagerService on the corresponding APIs,
diff --git a/core/res/res/drawable-hdpi/ic_notify_wifidisplay.png b/core/res/res/drawable-hdpi/ic_notify_wifidisplay.png
new file mode 100644
index 0000000..35f27df
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_notify_wifidisplay.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_notify_wifidisplay.png b/core/res/res/drawable-mdpi/ic_notify_wifidisplay.png
new file mode 100644
index 0000000..f9c8678
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_notify_wifidisplay.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_notify_wifidisplay.png b/core/res/res/drawable-xhdpi/ic_notify_wifidisplay.png
new file mode 100644
index 0000000..4cc0ee8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_notify_wifidisplay.png
Binary files differ
diff --git a/core/res/res/layout-port/keyguard_host_view.xml b/core/res/res/layout-port/keyguard_host_view.xml
index 20726d0..981fe6d 100644
--- a/core/res/res/layout-port/keyguard_host_view.xml
+++ b/core/res/res/layout-port/keyguard_host_view.xml
@@ -33,7 +33,8 @@
<com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper
android:id="@+id/view_flipper"
- android:layout_height="0dp"
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
android:clipChildren="false"
android:clipToPadding="false"
android:layout_weight="1"
diff --git a/core/res/res/layout-port/keyguard_status_area.xml b/core/res/res/layout-port/keyguard_status_area.xml
index e0a49dc..c1f6aab 100644
--- a/core/res/res/layout-port/keyguard_status_area.xml
+++ b/core/res/res/layout-port/keyguard_status_area.xml
@@ -45,6 +45,8 @@
<TextView
android:id="@+id/alarm_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
android:singleLine="true"
android:ellipsize="marquee"
@@ -93,4 +95,4 @@
android:textSize="@dimen/kg_status_line_font_size"
/>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/core/res/res/layout-sw600dp-port/keyguard_status_area.xml b/core/res/res/layout-sw600dp-port/keyguard_status_area.xml
index f21254a..405ac14 100644
--- a/core/res/res/layout-sw600dp-port/keyguard_status_area.xml
+++ b/core/res/res/layout-sw600dp-port/keyguard_status_area.xml
@@ -78,4 +78,4 @@
android:textAppearance="?android:attr/textAppearance"
android:textSize="@dimen/kg_status_line_font_size"
/>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/core/res/res/layout/default_navigation.xml b/core/res/res/layout/default_navigation.xml
index b13103c..b216ded 100644
--- a/core/res/res/layout/default_navigation.xml
+++ b/core/res/res/layout/default_navigation.xml
@@ -18,6 +18,8 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/keyguard_click_area"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:gravity="center">
<!-- message area for security screen -->
diff --git a/core/res/res/layout/keyguard_password_view.xml b/core/res/res/layout/keyguard_password_view.xml
index ab8aa85..81916f7 100644
--- a/core/res/res/layout/keyguard_password_view.xml
+++ b/core/res/res/layout/keyguard_password_view.xml
@@ -53,6 +53,7 @@
since the backspace/IME switcher looks better inside -->
<LinearLayout
android:layout_gravity="center_vertical|fill_horizontal"
+ android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="horizontal"
android:background="#70000000"
diff --git a/core/res/res/layout/keyguard_sim_pin_view.xml b/core/res/res/layout/keyguard_sim_pin_view.xml
index 163dc15..ae59d1d 100644
--- a/core/res/res/layout/keyguard_sim_pin_view.xml
+++ b/core/res/res/layout/keyguard_sim_pin_view.xml
@@ -91,6 +91,7 @@
<!-- Numeric keyboard -->
<com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
android:layout_width="match_parent"
+ android:layout_height="wrap_content"
android:layout_marginStart="4dip"
android:layout_marginEnd="4dip"
android:paddingTop="4dip"
diff --git a/core/res/res/layout/keyguard_sim_puk_view.xml b/core/res/res/layout/keyguard_sim_puk_view.xml
index 6e45b0b..414806f 100644
--- a/core/res/res/layout/keyguard_sim_puk_view.xml
+++ b/core/res/res/layout/keyguard_sim_puk_view.xml
@@ -93,6 +93,7 @@
<!-- Numeric keyboard -->
<com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
android:layout_width="match_parent"
+ android:layout_height="wrap_content"
android:layout_marginStart="4dip"
android:layout_marginEnd="4dip"
android:paddingTop="4dip"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index c93008d..34e82a7 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI-skerm"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Oorlegger #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Noodoproep"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Het jy die patroon vergeet?"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Verkeerde patroon"</string>
@@ -1418,7 +1424,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer verkeerdelik geteken. Na nog <xliff:g id="NUMBER_1">%d</xliff:g> onsuksesvolle pogings, sal jy gevra word om jou tablet te ontsluit deur middel van \'n e-posrekening."\n\n" Probeer weer oor <xliff:g id="NUMBER_2">%d</xliff:g> sekondes."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer verkeerdelik geteken. Na nog <xliff:g id="NUMBER_1">%d</xliff:g> onsuksesvolle pogings, sal jy gevra word om jou foon te ontsluit deur middel van \'n e-posrekening."\n\n" Probeer weer oor <xliff:g id="NUMBER_2">%d</xliff:g> sekondes."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Moet volume bo veilige vlak verhoog word?"\n"Deur vir lang tydperke op hoë volume te luister, kan jou gehoor beskadig."</string>
- <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Hou twee vingers in om toeganklikheid te aktiveer."</string>
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Hou aan met twee vingers inhou om toeganklikheid te aktiveer."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Toeganklikheid geaktiveer."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Toeganklikheid gekanselleer."</string>
<string name="user_switched" msgid="3768006783166984410">"Huidige gebruiker <xliff:g id="NAME">%1$s</xliff:g> ."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 495c0e2..eea1fac 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI ማያ ገጽ"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"ተደራቢ #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>፦ <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>፣ <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"ገመድ አልባ ማሳያ ተገናኝቷል"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"ይህ ማያ ገጽ በሌላ መሣሪያ ላይ እያሳየ ነው"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"ግንኙነት አቋርጥ"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"የአደጋ ጊዜ ጥሪ"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"ስርዓተ ጥለቱን እርሳ"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"የተሳሳተ ስርዓተ ጥለት"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index dfa88344..30adcad 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"شاشة HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"المركب #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>، <xliff:g id="DPI">%4$d</xliff:g> نقطة لكل بوصة"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"تم الاتصال بعرض شاشة اللاسلكي"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"يتم عرض هذه الشاشة على جهاز آخر"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"قطع الاتصال"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"الاتصال بالطوارئ"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"نسيت النقش"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"نقش خاطئ"</string>
@@ -1418,8 +1421,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"لقد رسمت نقش إلغاء التأمين بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%d</xliff:g> من المحاولات غير الناجحة الأخرى، ستطالَب بإلغاء تأمين الجهاز اللوحي باستخدام معلومات حساب بريد إلكتروني."\n\n" أعد المحاولة خلال <xliff:g id="NUMBER_2">%d</xliff:g> ثانية."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"لقد رسمت نقش إلغاء التأمين بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%d</xliff:g> من المحاولات غير الناجحة الأخرى، ستُطالب بإلغاء تأمين الهاتف باستخدام حساب بريد إلكتروني لإلغاء تأمين الهاتف."\n\n" أعد المحاولة خلال <xliff:g id="NUMBER_2">%d</xliff:g> ثانية."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"هل تريد رفع مستوى الصوت فوق المستوى الآمن؟"\n"قد يضر سماع صوت عالٍ لفترات طويلة بسمعك."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"اضغط بإصبعين لأسفل مع الاستمرار لتمكين تسهيل الدخول."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"تم تمكين إمكانية الدخول."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"تم إلغاء تسهيل الدخول."</string>
<string name="user_switched" msgid="3768006783166984410">"المستخدم الحالي <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 4403f97..bed4196 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -765,8 +765,7 @@
<string name="lockscreen_charged" msgid="4938930459620989972">"Зараджаны."</string>
<string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
<string name="lockscreen_low_battery" msgid="1482873981919249740">"Падлучыце зарадную прыладу."</string>
- <!-- no translation found for lockscreen_missing_sim_message_short (5099439277819215399) -->
- <skip />
+ <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Няма SIM-карты"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Няма SIM-карты ў планшэце."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"У тэлефоне няма SIM-карты."</string>
<string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Усталюйце SIM-карту."</string>
@@ -1382,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Экран HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Оверлей # <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> кр. на цалю"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"Падключаны бесправадны дысплей"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"Гэты экран паказваецца на іншай прыладзе"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Адключыць"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Экстранны выклік"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Забылі ключ"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Няправільна ключ"</string>
@@ -1419,8 +1421,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Вы няправільна ўвялі графічны ключ разблакiроўкi пэўную колькасць разоў: <xliff:g id="NUMBER_0">%d</xliff:g>. Пасля яшчэ некалькiх няўдалых спроб (<xliff:g id="NUMBER_1">%d</xliff:g>) вам будзе прапанавана разблакiраваць тэлефон, увайшоўшы ў Google."\n\n" Паўтарыце спробу праз <xliff:g id="NUMBER_2">%d</xliff:g> с."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Вы няправільна ўвялі графічны ключ разблакiроўкi пэўную колькасць разоў: <xliff:g id="NUMBER_0">%d</xliff:g>. Пасля яшчэ некалькiх няўдалых спроб (<xliff:g id="NUMBER_1">%d</xliff:g>) вам будзе прапанавана разблакiраваць тэлефон, увайшоўшы ў Google."\n\n" Паўтарыце спробу праз <xliff:g id="NUMBER_2">%d</xliff:g> с."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Павялiчыць гук больш за рэкамендаваны ўзровень?"\n"Доўгае слуханне музыкi на вялiкай гучнасцi можа пашкодзiць ваш слых."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Утрымлiвайце два пальцы, каб уключыць доступ."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Даступнасць уключана."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Даступнасць адменена."</string>
<string name="user_switched" msgid="3768006783166984410">"Бягучы карыстальнік <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index b46e30a..ed28d37 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Екран „HDMI“"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Наслагване №<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"„<xliff:g id="NAME">%1$s</xliff:g>“: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Спешно обаждане"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Забравена фигура"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Грешна фигура"</string>
@@ -1418,8 +1424,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%d</xliff:g> неуспешни опита ще бъдете помолени да отключите таблета посредством имейл адрес."\n\n" Опитайте отново след <xliff:g id="NUMBER_2">%d</xliff:g> секунди."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%d</xliff:g> неуспешни опита ще бъдете помолени да отключите телефона посредством имейл адрес."\n\n" Опитайте отново след <xliff:g id="NUMBER_2">%d</xliff:g> секунди."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Да се увеличи ли силата на звука над безопасното ниво?"\n"Продължителното слушане при висока сила на звука може да увреди слуха ви."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Продължете да натискате с два пръста, за да активирате функцията за достъпност."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Достъпността е активирана."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Функцията за достъпност е анулирана."</string>
<string name="user_switched" msgid="3768006783166984410">"Текущ потребител <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 6fa8b50..c6f1e1a 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Pantalla HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Superposa #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Trucada d\'emergència"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Patró oblidat"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Patró incorrecte"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 7381366..3c1b52f 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Obrazovka HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Překryvná vrstva č. <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Tísňové volání"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Zapomenuté gesto"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Nesprávné gesto"</string>
@@ -1418,8 +1424,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Již <xliff:g id="NUMBER_0">%d</xliff:g>krát jste nesprávně nakreslili své heslo odemknutí. Po <xliff:g id="NUMBER_1">%d</xliff:g>dalších neúspěšných pokusech budete požádáni o odemčení tabletu pomocí e-mailového účtu."\n\n" Zkuste to znovu za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Již <xliff:g id="NUMBER_0">%d</xliff:g>krát jste nesprávně nakreslili své heslo odemknutí. Po <xliff:g id="NUMBER_1">%d</xliff:g> dalších neúspěšných pokusech budete požádáni o odemčení telefonu pomocí e-mailového účtu."\n\n" Zkuste to znovu za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Chcete hlasitost zvýšit nad bezpečnou úroveň?"\n"Dlouhodobý poslech hlasitého zvuku může poškodit sluch."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Usnadnění zapnete dlouhým stisknutím dvěma prsty."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Usnadnění přístupu je aktivováno."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Usnadnění zrušeno."</string>
<string name="user_switched" msgid="3768006783166984410">"Aktuální uživatel je <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index db09717..0801988 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI-skærm"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlejring nr. <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Nødopkald"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Glemt mønster"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Forkert mønster"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index c938ca5..c1a9741e 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI-Bildschirm"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlay-Nr. <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"WLAN-Anzeige ist aktiv."</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"Dieser Bildschirm wird auf einem anderen Gerät angezeigt."</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Verbindung trennen"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Notruf"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Muster vergessen"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Falsches Muster"</string>
@@ -1418,8 +1421,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Sie haben Ihr Entsperrungsmuster <xliff:g id="NUMBER_0">%d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%d</xliff:g> weiteren erfolglosen Versuchen werden Sie aufgefordert, Ihr Tablet mithilfe eines E-Mail-Kontos zu entsperren."\n\n" Versuchen Sie es in <xliff:g id="NUMBER_2">%d</xliff:g> Sekunden erneut."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Sie haben Ihr Entsperrungsmuster <xliff:g id="NUMBER_0">%d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%d</xliff:g> weiteren erfolglosen Versuchen werden Sie aufgefordert, Ihr Telefon mithilfe eines E-Mail-Kontos zu entsperren."\n\n" Versuchen Sie es in <xliff:g id="NUMBER_2">%d</xliff:g> Sekunden erneut."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Lautstärke höher als Schwellenwert stellen?"\n"Wenn Sie über längere Zeiträume hinweg Musik in hoher Lautstärke hören, kann dies Ihr Gehör schädigen."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Drücken Sie mit zwei Fingern, um die Bedienungshilfen zu aktivieren."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Bedienungshilfen aktiviert"</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Bedienungshilfen abgebrochen"</string>
<string name="user_switched" msgid="3768006783166984410">"Aktueller Nutzer <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index e55a272f..52f0070 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Οθόνη HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Επικάλυψη #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"Έχει συνδεθεί ασύρματη οθόνη"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"Αυτή η οθόνη εμφανίζεται σε μια άλλη συσκευή"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Αποσύνδεση"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Κλήσεις επείγουσας ανάγκης"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Ξεχάσατε το μοτίβο"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Εσφαλμένο μοτίβο"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index a96995a..fdd35a1 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI Screen"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlay #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"Wireless display is connected"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"This screen is showing on another device"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Disconnect"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Emergency call"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Forgot Pattern"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Wrong Pattern"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index d0a1cd9..a333187 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Pantalla HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Superposición #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> ppp"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Llamada de emergencia"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"¿Olvidaste el patrón?"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Patrón incorrecto"</string>
@@ -1418,8 +1424,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Dibujaste incorrectamente tu patrón de desbloqueo <xliff:g id="NUMBER_0">%d</xliff:g> veces. Luego de <xliff:g id="NUMBER_1">%d</xliff:g> intentos incorrectos más, se te solicitará que desbloquees tu tableta mediante el uso de una cuenta de correo."\n\n" Vuelve a intentarlo en <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Dibujaste incorrectamente tu patrón de desbloqueo <xliff:g id="NUMBER_0">%d</xliff:g> veces. Luego de <xliff:g id="NUMBER_1">%d</xliff:g> intentos incorrectos más, se te solicitará que desbloquees tu dispositivo mediante el uso de una cuenta de correo."\n\n" Vuelve a intentarlo en <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"¿Aumentar el volumen por encima del nivel seguro?"\n"Si escuchas con el volumen alto durante períodos prolongados, puedes dañar tu audición."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Mantén presionado con dos dedos para activar la accesibilidad."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Se activó la accesibilidad."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Se canceló la accesibilidad."</string>
<string name="user_switched" msgid="3768006783166984410">"Usuario actual: <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index d41ce82..53f0eff 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Pantalla HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Superposición #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"Pantalla inalámbrica conectada"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"Esta pantalla se muestra en otro dispositivo."</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Desconectar"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Llamada de emergencia"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"¿Has olvidado el patrón?"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"El patrón es incorrecto."</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index cf237dc..d554e21 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI-ekraan"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Ülekate nr .<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Hädaabikõne"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Unustasin mustri"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Vale muster"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index ae0ca2b..10434f8 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"صفحه HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"همپوشانی #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"نمایشگر بیسیم متصل است"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"این صفحه در حال نمایش در دستگاه دیگری است"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"قطع اتصال"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"تماس اضطراری"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"الگو را فراموش کردهاید"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"الگوی اشتباه"</string>
@@ -1418,8 +1421,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیدهاید. بعد از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق، از شما خواسته میشود که با استفاده از یک حساب ایمیل قفل رایانه لوحی خود را باز کنید."\n\n" لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیدهاید. پس از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق، از شما خواسته میشود که با استفاده از یک حساب ایمیل قفل تلفن خود را باز کنید."\n\n" لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"صدا به بالاتر از سطح ایمن افزایش یابد؟"\n"گوش دادن به صدای بلند برای زمانهای طولانی میتواند به شنوایی شما آسیب برساند."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"برای فعال کردن قابلیت دسترسی، با دو انگشت خود همچنان به طرف پایین فشار دهید."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"قابلیت دسترسی فعال شد."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"قابلیت دسترسی لغو شد."</string>
<string name="user_switched" msgid="3768006783166984410">"کاربر کنونی <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index ae2a4cb..a0ec3ad 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI-ruutu"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Peittokuva # <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"Langaton näyttö on yhdistetty"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"Tämä ruutu näkyy toisella laitteella"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Katkaise yhteys"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Hätäpuhelu"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Unohtunut kuvio"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Väärä kuvio"</string>
@@ -1418,8 +1421,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Piirsit lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%d</xliff:g> kertaa, sinua pyydetään poistamaan tablet-laitteesi lukitus sähköpostitilin avulla."\n\n" Yritä uudelleen <xliff:g id="NUMBER_2">%d</xliff:g> sekunnin kuluttua."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Piirsit lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%d</xliff:g> kertaa, sinua pyydetään poistamaan puhelimesi lukitus sähköpostitilin avulla."\n\n" Yritä uudelleen <xliff:g id="NUMBER_2">%d</xliff:g> sekunnin kuluttua."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Nostetaanko äänenvoimakkuus turvallista tasoa voimakkaammaksi?"\n"Jos kuuntelet suurella äänenvoimakkuudella pitkiä aikoja, kuulosi voi vahingoittua."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Ota esteettömyystila käyttöön koskettamalla pitkään kahdella sormella."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Esteettömyystila käytössä."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Esteettömyystila peruutettu."</string>
<string name="user_switched" msgid="3768006783166984410">"Nykyinen käyttäjä: <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index aa4f91e..f19c4a6 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Écran HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Superposition n° <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g> : <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Appel d\'urgence"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"J\'ai oublié le schéma"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Schéma incorrect."</string>
@@ -1418,8 +1424,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%d</xliff:g> fois, vous devrez déverrouiller votre tablette à l\'aide d\'un compte de messagerie électronique."\n\n" Veuillez réessayer dans <xliff:g id="NUMBER_2">%d</xliff:g> secondes."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%d</xliff:g> fois, vous devrez déverrouiller votre téléphone à l\'aide d\'un compte de messagerie électronique."\n\n" Veuillez réessayer dans <xliff:g id="NUMBER_2">%d</xliff:g> secondes."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Augmenter le volume au-dessus du niveau de sécurité ?"\n"L\'écoute à un volume élevé pendant des périodes prolongées peut endommager votre audition."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Pour activer l\'accessibilité, appuyez de manière prolongée avec deux doigts."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"L\'accessibilité a bien été activée."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Accessibilité annulée."</string>
<string name="user_switched" msgid="3768006783166984410">"Utilisateur actuel : <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index d0f1dc5..5b7516d 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1262,7 +1262,7 @@
<string name="media_shared" product="nosdcard" msgid="5830814349250834225">"USB संग्रहण का उपयोग वर्तमान में एक कंप्यूटर द्वारा किया जा रहा है."</string>
<string name="media_shared" product="default" msgid="5706130568133540435">"SD कार्ड का उपयोग वर्तमान में एक कंप्यूटर द्वारा किया जा रहा है."</string>
<string name="media_unknown_state" msgid="729192782197290385">"बाह्य मीडिया अज्ञात स्थिति में है."</string>
- <string name="share" msgid="1778686618230011964">"शेयर करें"</string>
+ <string name="share" msgid="1778686618230011964">"साझा करें"</string>
<string name="find" msgid="4808270900322985960">"ढूंढें"</string>
<string name="websearch" msgid="4337157977400211589">"वेब खोज"</string>
<string name="find_next" msgid="5742124618942193978">"अगला ढूंढें"</string>
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI स्क्रीन"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"ओवरले #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"आपातकालीन कॉल"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"प्रतिमान भूल गए"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"गलत प्रतिमान"</string>
@@ -1418,8 +1424,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"आपने अपने अनलॉक प्रतिमान को <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से आरेखित किया है. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने टेबलेट को किसी ईमेल खाते के उपयोग से अनलॉक करने के लिए कहा जाएगा."\n\n" <xliff:g id="NUMBER_2">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"आपने अपने अनलॉक प्रतिमान को <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से आरेखित किया है. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने फ़ोन को किसी ईमेल खाते का उपयोग करके अनलॉक करने के लिए कहा जाएगा."\n\n" <xliff:g id="NUMBER_2">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"वॉल्यूम को सुरक्षित स्तर से अधिक करें?"\n"अधिक देर तक उच्च वॉल्यूम पर सुनने से आपकी सुनने की क्षमता को नुकसान हो सकता है."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"पहुंच-योग्यता को सक्षम करने के लिए दो अंगुलियों से नीचे दबाए रखें."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"पहुंच-योग्यता सक्षम कर दी है."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"पहुंच-योग्यता रद्द की गई."</string>
<string name="user_switched" msgid="3768006783166984410">"वर्तमान उपयोगकर्ता <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index f223fa6..78d7d28 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI zaslon"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Preklapanje br. <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"Bežični je prikaz povezan"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"Ovaj se zaslon prikazuje na nekom drugom uređaju"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Isključi"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Hitan poziv"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Zaboravili ste obrazac"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Pogrešan obrazac"</string>
@@ -1418,8 +1421,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Netočno ste iscrtali obrazac za otključavanje <xliff:g id="NUMBER_0">%d</xliff:g> puta. Nakon još ovoliko neuspješnih pokušaja: <xliff:g id="NUMBER_1">%d</xliff:g> morat ćete otključati tabletno računalo pomoću računa e-pošte."\n\n" Pokušajte ponovo za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Netočno ste iscrtali obrazac za otključavanje <xliff:g id="NUMBER_0">%d</xliff:g> puta. Nakon još ovoliko neuspješnih pokušaja: <xliff:g id="NUMBER_1">%d</xliff:g> morat ćete otključati telefon pomoću računa e-pošte."\n\n" Pokušajte ponovo za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Pojačati iznad sigurne razine?"\n"Dulje slušanje preglasne glazbe može vam oštetiti sluh."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Nastavite držati s dva prsta kako biste omogućili pristupačnost."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Dostupnost je omogućena."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Pristupačnost otkazana."</string>
<string name="user_switched" msgid="3768006783166984410">"Trenutačni korisnik <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 3815c38..e899b60 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI-képernyő"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"<xliff:g id="ID">%1$d</xliff:g>. fedvény"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> képpont"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Segélyhívás"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Elfelejtett minta"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Helytelen minta"</string>
@@ -1418,8 +1424,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"<xliff:g id="NUMBER_0">%d</xliff:g> alkalommal helytelenül rajzolta le a feloldási mintát. További <xliff:g id="NUMBER_1">%d</xliff:g> sikertelen kísérlet után egy e-mail fiók használatával kell feloldania a táblagépét."\n\n" Kérjük, próbálja újra <xliff:g id="NUMBER_2">%d</xliff:g> másodperc múlva."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"<xliff:g id="NUMBER_0">%d</xliff:g> alkalommal helytelenül rajzolta le a feloldási mintát. További <xliff:g id="NUMBER_1">%d</xliff:g> sikertelen kísérlet után egy e-mail fiók használatával kell feloldania a telefonját."\n\n" Kérjük, próbálja újra <xliff:g id="NUMBER_2">%d</xliff:g> másodperc múlva."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"A biztonságos szint fölé emeli a hangerőt?"\n"Ha hosszú ideig hangosan hallgatja a zenét, az károsíthatja a hallását."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Továbbra is tartsa lenyomva két ujját a hozzáférés engedélyezéséhez."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Hozzáférés engedélyezve"</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Hozzáférés megszakítva."</string>
<string name="user_switched" msgid="3768006783166984410">"<xliff:g id="NAME">%1$s</xliff:g> az aktuális felhasználó."</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 17b4944..e258670 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Layar HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Hamparan #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"Layar nirkabel tersambung"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"Layar ini ditampilkan di perangkat lain"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Putuskan sambungan"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Panggilan darurat"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Lupa Pola?"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Pola Salah"</string>
@@ -1418,8 +1421,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Anda telah <xliff:g id="NUMBER_0">%d</xliff:g> kali salah menggambar pola pembuka kunci. Setelah <xliff:g id="NUMBER_1">%d</xliff:g> lagi upaya gagal, Anda akan diminta membuka kunci tablet menggunakan akun email."\n\n"Coba lagi dalam <xliff:g id="NUMBER_2">%d</xliff:g> detik."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Anda telah <xliff:g id="NUMBER_0">%d</xliff:g> kali salah menggambar pola pembuka kunci. Setelah <xliff:g id="NUMBER_1">%d</xliff:g> lagi upaya gagal, Anda akan diminta membuka kunci ponsel menggunakan akun email."\n\n"Coba lagi dalam <xliff:g id="NUMBER_2">%d</xliff:g> detik."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Naikkan volume di atas tingkat aman?"\n"Mendengarkan volume tinggi dalam jangka waktu yang lama dapat merusak pendengaran Anda."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Tahan terus dua jari untuk mengaktifkan aksesibilitas."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Aksesibilitas diaktifkan."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Aksesibilitas dibatalkan."</string>
<string name="user_switched" msgid="3768006783166984410">"Pengguna saat ini <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 5357009..b29d0b6 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Schermo HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlay n. <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"Il display wireless è connesso"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"Questa schermata è mostrata su un altro dispositivo"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Disconnetti"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Chiamata di emergenza"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Sequenza dimenticata"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Sequenza sbagliata"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index bd1ffb7..18de68f 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"מסך HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"שכבת על #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"מסך אלחוטי מחובר"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"מסך זה מוצג במכשיר אחר"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"נתק"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"שיחת חירום"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"שכחת את הקו"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"קו ביטול נעילה שגוי"</string>
@@ -1418,8 +1421,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות כושלים נוספים, תתבקש לבטל את נעילת הטאבלט באמצעות חשבון דוא\"ל."\n\n"נסה שוב בעוד <xliff:g id="NUMBER_2">%d</xliff:g> שניות."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות כושלים נוספים, תתבקש לבטל את נעילת הטלפון באמצעות חשבון דוא\"ל."\n\n"נסה שוב בעוד <xliff:g id="NUMBER_2">%d</xliff:g> שניות."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"האם להעלות את עוצמת הקול מעל לרמה הבטוחה?"\n"האזנה בעוצמת קול גבוהה למשך זמן ארוך עלולה לפגוע בשמיעה."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"המשך לגעת בשתי אצבעות כדי להפעיל נגישות."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"נגישות הופעלה."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"נגישות בוטלה."</string>
<string name="user_switched" msgid="3768006783166984410">"המשתמש הנוכחי <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 97a1675..23d077c 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI画面"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"オーバーレイ第<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>、<xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"緊急通報"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"パターンを忘れた場合"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"パターンが正しくありません"</string>
@@ -1418,8 +1424,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、タブレットのロック解除にメールアカウントが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒以内にもう一度お試しください。"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、携帯端末のロック解除にメールアカウントが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒以内にもう一度お試しください。"</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"安全レベルを超えるまで音量を上げますか?"\n"大音量で長時間聞き続けると、聴力を損なう恐れがあります。"</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"ユーザー補助機能を有効にするには2本の指で押し続けてください。"</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"ユーザー補助が有効になりました。"</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"ユーザー補助をキャンセルしました。"</string>
<string name="user_switched" msgid="3768006783166984410">"現在のユーザーは<xliff:g id="NAME">%1$s</xliff:g>です。"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index e10fd3f..ccffc49 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI 화면"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"<xliff:g id="ID">%1$d</xliff:g>번째 오버레이"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"무선 디스플레이가 연결되었습니다."</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"이 화면은 다른 기기에서 표시되고 있습니다."</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"연결 해제"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"긴급 통화"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"패턴을 잊음"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"잘못된 패턴"</string>
@@ -1418,8 +1421,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"잠금해제 패턴을 <xliff:g id="NUMBER_0">%d</xliff:g>회 잘못 그렸습니다. <xliff:g id="NUMBER_1">%d</xliff:g>회 더 실패하면 이메일 계정을 사용하여 태블릿을 잠금해제해야 합니다."\n\n" <xliff:g id="NUMBER_2">%d</xliff:g>초 후에 다시 시도해 주세요."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"잠금해제 패턴을 <xliff:g id="NUMBER_0">%d</xliff:g>회 잘못 그렸습니다. <xliff:g id="NUMBER_1">%d</xliff:g>회 더 실패하면 이메일 계정을 사용하여 휴대전화를 잠금해제해야 합니다."\n\n" <xliff:g id="NUMBER_2">%d</xliff:g>초 후에 다시 시도해 주세요."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"안전한 수준 이상으로 볼륨을 높이시겠습니까?"\n"높은 볼륨으로 장시간 청취하면 청력에 손상이 올 수 있습니다."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"두 손가락으로 길게 누르면 접근성을 사용하도록 설정됩니다."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"접근성을 사용 설정했습니다."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"접근성이 취소되었습니다."</string>
<string name="user_switched" msgid="3768006783166984410">"현재 사용자는 <xliff:g id="NAME">%1$s</xliff:g>님입니다."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 1240d6c..f6217a3 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI ekranas"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Perdanga nr. <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"„<xliff:g id="NAME">%1$s</xliff:g>“: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> tašk. colyje"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Skambutis pagalbos numeriu"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Pamiršau atrakinimo piešinį"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Netinkamas atrakinimo piešinys"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 25c036b..fe141de 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI ekrāns"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Pārklājums Nr. <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Ārkārtas izsaukums"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Aizmirsu kombināciju"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Nepareiza kombinācija"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 79eefef..636a168 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Skrin HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Tindih #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"Paparan wayarles disambungkan"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"Skrin ini ditunjukkan pada peranti lain"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Putus sambungan"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Panggilan kecemasan"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Lupa Corak"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Corak Salah"</string>
@@ -1418,8 +1421,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Anda telah tersilap melukis corak buka kunci sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%d</xliff:g> lagi percubaan yang tidak berjaya, anda akan diminta membuka kunci tablet anda menggunakan log masuk Google anda."\n\n" Cuba lagi dalam <xliff:g id="NUMBER_2">%d</xliff:g> saat."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Anda telah tersilap lukis corak buka kunci sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%d</xliff:g> lagi percubaan yang tidak berjaya, anda akan diminta membuka kunci telefon anda menggunakan log masuk Google anda."\n\n" Cuba lagi dalam <xliff:g id="NUMBER_2">%d</xliff:g> saat."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Tingkatkan kelantangan di atas tahap selamat?"\n"Mendengar pada kelantangan tinggi untuk tempoh yang panjang boleh merosakkan pendengaran anda."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Teruskan menahan dengan dua jari untuk mendayakan kebolehcapaian."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Kebolehcapaian didayakan."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Kebolehcapaian dibatalkan."</string>
<string name="user_switched" msgid="3768006783166984410">"Pengguna semasa <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 78cc0e9..aa6b0c4 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI-skjerm"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlegg #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Nødnummer"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Har du glemt mønsteret?"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Feil mønster"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index df8ec78..d896f1a 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI-scherm"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlay <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"Draadloze display is aangesloten"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"Dit scherm wordt op een ander apparaat weergegeven"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Verbinding verbreken"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Noodoproep"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Patroon vergeten"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Onjuist patroon"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 7381794b..0472a10b 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -765,8 +765,7 @@
<string name="lockscreen_charged" msgid="4938930459620989972">"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>
- <!-- no translation found for lockscreen_missing_sim_message_short (5099439277819215399) -->
- <skip />
+ <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Brak karty SIM"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Brak karty SIM w tablecie."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Brak karty SIM w telefonie."</string>
<string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Włóż kartę SIM."</string>
@@ -1382,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Ekran HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Nakładka nr <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"Podłączony jest wyświetlacz bezprzewodowy"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"Ten ekran jest wyświetlany na innym urządzeniu"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Rozłącz"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Połączenie alarmowe"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Nie pamiętam wzoru"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Nieprawidłowy wzór"</string>
@@ -1419,8 +1421,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Po raz <xliff:g id="NUMBER_0">%d</xliff:g> nieprawidłowo narysowałeś wzór odblokowania. Po kolejnych <xliff:g id="NUMBER_1">%d</xliff:g> nieudanych próbach konieczne będzie odblokowanie tabletu przy użyciu danych logowania na konto Google."\n\n" Spróbuj ponownie za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Po raz <xliff:g id="NUMBER_0">%d</xliff:g> nieprawidłowo narysowałeś wzór odblokowania. Po kolejnych <xliff:g id="NUMBER_1">%d</xliff:g> nieudanych próbach konieczne będzie odblokowanie telefonu przy użyciu danych logowania na konto Google."\n\n" Spróbuj ponownie za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Chcesz ustawić głośność powyżej bezpiecznego poziomu?"\n"Słuchanie przy dużym poziomie głośności przez dłuższy czas może doprowadzić do uszkodzenia słuchu."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Aby włączyć ułatwienia dostępu, przytrzymaj dwa palce."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Włączono ułatwienia dostępu."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Ułatwienia dostępu zostały anulowane."</string>
<string name="user_switched" msgid="3768006783166984410">"Bieżący użytkownik: <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 1a22702..7b90687 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Ecrã HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Sobreposição #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> ppp"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Chamada de emergência"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Esqueceu-se da Sequência"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Sequência Incorreta"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 55f727a2..44c1c46 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Tela HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Sobreposição nº <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"O Display sem fio está conectado"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"Tela exibida em outro dispositivo."</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Desconectar"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Chamada de emergência"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Esqueci o padrão"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Padrão incorreto"</string>
@@ -1418,8 +1421,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear seu tablet."\n\n" Tente novamente em <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear."\n\n" Tente novamente em <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Aumentar o volume acima do nível seguro?"\n"A audição em volume elevado por períodos longos pode prejudicar sua audição."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Mantenha pressionado com dois dedos para ativar a acessibilidade."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Acessibilidade ativada."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Acessibilidade cancelada."</string>
<string name="user_switched" msgid="3768006783166984410">"Usuário atual <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 3f8bbf4..3a01bac 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -2216,6 +2216,12 @@
<skip />
<!-- no translation found for display_manager_overlay_display_title (652124517672257172) -->
<skip />
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<!-- no translation found for kg_emergency_call_label (684946192523830531) -->
<skip />
<!-- no translation found for kg_forgot_pattern_button_text (8852021467868220608) -->
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 81aaaa0..5b8fca7 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Ecran HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Suprapunerea <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Apel de urgenţă"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Model uitat"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Model greşit"</string>
@@ -1418,8 +1424,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%d</xliff:g> încercări nereuşite, vi se va solicita să deblocaţi tableta cu ajutorul unui cont de e-mail."\n\n" Încercaţi din nou peste <xliff:g id="NUMBER_2">%d</xliff:g> (de) secunde."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%d</xliff:g> încercări nereuşite, vi se va solicita să deblocaţi telefonul cu ajutorul unui cont de e-mail."\n\n" Încercaţi din nou peste <xliff:g id="NUMBER_2">%d</xliff:g> (de) secunde."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Ridicaţi volumul mai sus de nivelul sigur?"\n"Ascultarea la volum ridicat pe perioade lungi de timp vă poate afecta auzul."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Menţineţi două degete pe ecran pentru a activa accesibilitatea."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"S-a activat accesibilitatea."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Accesibilitatea a fost anulată"</string>
<string name="user_switched" msgid="3768006783166984410">"Utilizator curent: <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 0b3d009..f32aa97 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Экран HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Наложение № <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> х <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> тчк/дюйм"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Экстренный вызов"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Забыли графический ключ?"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Неправильный графический ключ"</string>
@@ -1418,8 +1424,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Вы <xliff:g id="NUMBER_0">%d</xliff:g> раз неверно указали графический ключ. После <xliff:g id="NUMBER_1">%d</xliff:g> неверных попыток для разблокировки планшетного ПК потребуется войти в аккаунт Google."\n\n"Повтор через <xliff:g id="NUMBER_2">%d</xliff:g> сек."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Вы <xliff:g id="NUMBER_0">%d</xliff:g> раз неверно указали графический ключ. После <xliff:g id="NUMBER_1">%d</xliff:g> неверных попыток для разблокировки телефона потребуется войти в аккаунт Google."\n\n"Повтор через <xliff:g id="NUMBER_2">%d</xliff:g> сек."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Увеличить громкость до небезопасного уровня?"\n"Долговременное прослушивание на такой громкости может повредить слух."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Чтобы включить специальные возможности, удерживайте пальцы на экране."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Специальные возможности включены."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Специальные возможности не будут включены."</string>
<string name="user_switched" msgid="3768006783166984410">"Выбран аккаунт пользователя <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index e6a3b38..946a0ce 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Obrazovka HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Prekrytie č. <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Tiesňové volanie"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Nepamätám si vzor"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Nesprávny vzor"</string>
@@ -1418,8 +1424,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"<xliff:g id="NUMBER_0">%d</xliff:g>-krát ste nesprávne nakreslili svoj bezpečnostný vzor. Po ďalších <xliff:g id="NUMBER_1">%d</xliff:g> neúspešných pokusoch sa zobrazí výzva na odomknutie tabletu pomocou e-mailového účtu."\n\n" Skúste to znova o <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"<xliff:g id="NUMBER_0">%d</xliff:g>-krát ste nesprávne nakreslili svoj bezpečnostný vzor. Po <xliff:g id="NUMBER_1">%d</xliff:g> ďalších neúspešných pokusoch sa zobrazí výzva na odomknutie telefónu pomocou e-mailového účtu."\n\n" Skúste to znova o <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Chcete zvýšiť hlasitosť nad bezpečnú úroveň?"\n"Dlhodobé počúvanie pri vysokej hlasitosti môže viesť k poškodeniu vášho sluchu."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Zjednodušenie ovládania povolíte dlhým stlačením dvoma prstami."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Zjednodušenie ovládania je povolené."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Zjednodušenie ovládania bolo zrušené."</string>
<string name="user_switched" msgid="3768006783166984410">"Aktuálny používateľ je <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index cdd8d112..b94be23 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Zaslon HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Prekrivanje #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> pik na palec"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Klic v sili"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Pozabljen vzorec"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Napačen vzorec"</string>
@@ -1418,8 +1424,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%d</xliff:g>-krat napačno vnesli. Po nadaljnjih <xliff:g id="NUMBER_1">%d</xliff:g> neuspešnih poskusih boste pozvani, da tablični računalnik odklenete z e-poštnim računom."\n\n"Poskusite znova čez <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%d</xliff:g>-krat napačno vnesli. Po nadaljnjih <xliff:g id="NUMBER_1">%d</xliff:g> neuspešnih poskusih boste pozvani, da odklenete telefon z Googlovimi podatki za prijavo."\n\n"Poskusite znova čez <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Želite povečati glasnost nad varno raven?"\n"Dolgotrajna izpostavljenost glasnim tonom lahko poškoduje sluh."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Če želite omogočiti pripomočke za ljudi s posebnimi potrebami, na zaslonu pridržite z dvema prstoma."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Pripomočki za ljudi s posebnimi potrebami so omogočeni."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Omogočanje pripomočkov za ljudi s posebnimi potrebami preklicano."</string>
<string name="user_switched" msgid="3768006783166984410">"Trenutni uporabnik <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index bfeb021..b08bce7 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI екран"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Постављени елемент бр. <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>×<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"Бежични екран је повезан"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"Овај екран се приказује на другом уређају"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Прекини везу"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Хитни позив"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Заборављени шаблон"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Погрешан шаблон"</string>
@@ -1418,8 +1421,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Нацртали сте шаблон за откључавање неисправно <xliff:g id="NUMBER_0">%d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате таблет помоћу налога е-поште."\n\n"Покушајте поново за <xliff:g id="NUMBER_2">%d</xliff:g> секунде(и)."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Нацртали сте шаблон за откључавање неисправно <xliff:g id="NUMBER_0">%d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате телефон помоћу налога е-поште."\n\n"Покушајте поново за <xliff:g id="NUMBER_2">%d</xliff:g> секунде(и)."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Желите да појачате звук изнад безбедног нивоа?"\n"Ако дуже време слушате гласну музику, може доћи до оштећења слуха."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Држите са два прста да бисте омогућили приступачност."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Приступачност је омогућена."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Приступачност је отказана."</string>
<string name="user_switched" msgid="3768006783166984410">"Актуелни корисник <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 428e3d6..c2c41c5 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI-skärm"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Överlagring #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Nödsamtal"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Har du glömt ditt grafiska lösenord?"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Fel grafiskt lösenord"</string>
@@ -1418,8 +1424,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%d</xliff:g> försök ombeds du låsa upp surfplattan med ett e-postkonto."\n\n" Försök igen om <xliff:g id="NUMBER_2">%d</xliff:g> sekunder."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%d</xliff:g> försök ombeds du låsa upp mobilen med hjälp av ett e-postkonto."\n\n" Försök igen om <xliff:g id="NUMBER_2">%d</xliff:g> sekunder."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Vill du höja volymen över den säkra nivån?"\n"Om du lyssnar på hög volym under långa perioder kan din hörsel skadas."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Fortsätt trycka med två fingrar om du vill aktivera tillgänglighetsläget."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Tillgänglighetsläget har aktiverats."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Byte till tillgänglighetsläge avbrutet."</string>
<string name="user_switched" msgid="3768006783166984410">"Nuvarande användare: <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index b712146..f4a4d64 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Skrini ya HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Uwekeleaji #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"Onyesho pasiwaya limeunganishwa"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"Skrini hii inaonyesha kwenye kifaa kingine"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Tenganisha"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Simu ya dharura"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Umesahau Ruwaza"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Ruwaza Isiyo sahihi"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index a619a36..38cf2f6 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"หน้าจอ HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"การวางซ้อน #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"เชื่อมต่อการแสดงผลแบบไร้สายอยู่"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"หน้าจอนี้กำลังแสดงบนอุปกรณ์อื่น"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"หยุดเชื่อมต่อ"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"หมายเลขฉุกเฉิน"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"ลืมรูปแบบใช่หรือไม่"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"รูปแบบไม่ถูกต้อง"</string>
@@ -1418,8 +1421,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกแท็บเล็ตโดยใช้บัญชีอีเมล"\n\n" โปรดลองอีกครั้งใน <xliff:g id="NUMBER_2">%d</xliff:g> วินาที"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกโทรศัพท์โดยใช้ับัญชีอีเมล"\n\n" โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_2">%d</xliff:g> วินาที"</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"เพิ่มระดับเสียงจนเกินระดับที่ปลอดภัยหรือไม่"\n"การฟังเสียงดังเป็นเวลานานอาจทำให้การได้ยินของคุณบกพร่องได้"</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"ใช้สองนิ้วแตะค้างไว้เพื่อเปิดใช้งานการเข้าถึง"</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"เปิดใช้งานการเข้าถึงแล้ว"</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"ยกเลิกการเข้าถึงแล้ว"</string>
<string name="user_switched" msgid="3768006783166984410">"ผู้ใช้ปัจจุบัน <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index cfe58c7..205dfa6 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI Screen"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlay #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"Nakakonekta ang wireless na display"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"Lumalabas ang screen na ito sa isa pang device"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Alisin sa pagkakakonekta"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Emergency na tawag"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Nakalimutan ang Pattern"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Maling Pattern"</string>
@@ -1418,8 +1421,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Naguhit mo nang hindi tama ang iyong pattern sa pag-unlock nang <xliff:g id="NUMBER_0">%d</xliff:g> (na) beses. Pagkatapos ng <xliff:g id="NUMBER_1">%d</xliff:g> pang hindi matagumpay na pagtatangka, hihilingin sa iyong i-unlock ang tablet mo gamit ang isang email account."\n\n" Subukang muli sa loob ng <xliff:g id="NUMBER_2">%d</xliff:g> (na) segundo."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Naguhit mo nang hindi tama ang iyong pattern sa pag-unlock nang <xliff:g id="NUMBER_0">%d</xliff:g> (na) beses. Pagkatapos ng <xliff:g id="NUMBER_1">%d</xliff:g> pang hindi matagumpay na pagtatangka, hihilingin sa iyong i-unlock ang telepono mo gamit ang isang email account."\n\n" Subukang muli sa loob ng <xliff:g id="NUMBER_2">%d</xliff:g> (na) segundo."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Lakasan ang volume nang lagpas sa ligtas na antas?"\n"Maaaring mapinsala ng pakikinig sa malakas na volume sa loob ng mahahabang panahon ang iyong pandinig."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Panatilihing nakapindot nang matagal ang iyong dalawang daliri upang paganahin ang pagiging naa-access."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Pinagana ang accessibility."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Nakansela ang pagiging naa-access."</string>
<string name="user_switched" msgid="3768006783166984410">"Kasalukuyang user <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 2c9407b..4a661b74 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI Ekran"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Yer Paylaşımı No. <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Acil durum çağrısı"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Deseni Unuttunuz mu?"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Yanlış Desen"</string>
@@ -1418,8 +1424,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%d</xliff:g> kez yanlış çizdiniz. <xliff:g id="NUMBER_1">%d</xliff:g> başarısız denemeden sonra, tabletinizi bir e-posta hesabı kullanarak açmanız istenir."\n\n" <xliff:g id="NUMBER_2">%d</xliff:g> saniye içinde tekrar deneyin."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%d</xliff:g> kez yanlış çizdiniz. <xliff:g id="NUMBER_1">%d</xliff:g> başarısız denemeden sonra telefonunuzu bir e-posta hesabı kullanarak açmanız istenir."\n\n" <xliff:g id="NUMBER_2">%d</xliff:g> saniye içinde tekrar deneyin."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Ses düzeyi güvenli seviyenin üzerine çıkarılsın mı?"\n"Yüksek sesle uzun süre dinlemek işitme yetinize zarar verebilir."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Erişilebilirliği etkinleştirmek için iki parmağınızı basılı tutmaya devam edin."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Erişilebilirlik etkinleştirildi."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Erişilebilirlik iptal edildi."</string>
<string name="user_switched" msgid="3768006783166984410">"Geçerli kullanıcı: <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 3072cb9..acfa7bb 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Екран HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Накладання №<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>х<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"Бездротовий екран під’єднано"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"Цей екран відображається на іншому пристрої"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Від’єднати"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Екстрений виклик"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Не пам’ятаю ключ"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Неправильний ключ"</string>
@@ -1418,8 +1421,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%d</xliff:g>. У вас є ще стільки спроб: <xliff:g id="NUMBER_1">%d</xliff:g>. У разі невдачі з’явиться запит розблокувати планшетний ПК за допомогою облікового запису електронної пошти."\n\n" Повторіть спробу через <xliff:g id="NUMBER_2">%d</xliff:g> сек."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%d</xliff:g>. У вас є ще стільки спроб: <xliff:g id="NUMBER_1">%d</xliff:g>. У разі невдачі з’явиться запит розблокувати телефон за допомогою облікового запису електронної пошти."\n\n" Повторіть спробу через <xliff:g id="NUMBER_2">%d</xliff:g> сек."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Збільшити гучність понад безпечний рівень?"\n"Надто гучне прослуховування впродовж тривалого періоду може пошкодити слух."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Утримуйте двома пальцями, щоб увімкнути доступність."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Доступність увімкнено."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Доступність скасовано."</string>
<string name="user_switched" msgid="3768006783166984410">"Поточний користувач: <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 3dbe71b..f3a4ca6 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Màn hình HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Lớp phủ #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"Cuộc gọi khẩn cấp"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Đã quên hình"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Hình sai"</string>
@@ -1418,8 +1424,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Bạn đã <xliff:g id="NUMBER_0">%d</xliff:g> lần vẽ không chính xác hình mở khóa của mình. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần thử không thành công nữa, bạn sẽ được yêu cầu mở khóa máy tính bảng bằng tài khoản email."\n\n" Vui lòng thử lại sau <xliff:g id="NUMBER_2">%d</xliff:g> giây."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Bạn đã <xliff:g id="NUMBER_0">%d</xliff:g> lần vẽ không chính xác hình mở khóa của mình. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần thử không thành công nữa, bạn sẽ được yêu cầu mở khóa điện thoại bằng tài khoản email."\n\n" Vui lòng thử lại sau <xliff:g id="NUMBER_2">%d</xliff:g> giây."</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Tăng âm lượng trên mức an toàn?"\n"Nghe ở âm lượng cao trong thời gian dài có thể gây hại cho thính giác của bạn."</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Tiếp tục giữ hai ngón tay để bật trợ năng."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"Trợ năng đã được bật."</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Đã hủy trợ năng."</string>
<string name="user_switched" msgid="3768006783166984410">"Người dùng hiện tại <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index ea55480..e60bee4 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -777,7 +777,7 @@
<string name="lockscreen_transport_pause_description" msgid="7659088786780128001">"“暂停”按钮"</string>
<string name="lockscreen_transport_play_description" msgid="5888422938351019426">"“播放”按钮"</string>
<string name="lockscreen_transport_stop_description" msgid="4562318378766987601">"“停止”按钮"</string>
- <string name="emergency_calls_only" msgid="6733978304386365407">"只能使用紧急呼救"</string>
+ <string name="emergency_calls_only" msgid="6733978304386365407">"只能拨打紧急呼救电话"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"网络已锁定"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM 卡已用 PUK 码锁定"</string>
<string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"请参阅《用户指南》或与客服人员联系。"</string>
@@ -1381,6 +1381,12 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI 屏幕"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"叠加视图 #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>:<xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>,<xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+ <skip />
+ <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+ <skip />
<string name="kg_emergency_call_label" msgid="684946192523830531">"紧急呼救"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"忘记了图案"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"图案错误"</string>
@@ -1418,8 +1424,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地绘制了解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐户解锁平板电脑。"\n\n"请在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒后重试。"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地绘制了解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐户解锁手机。"\n\n"请在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒后重试。"</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"将音量调高到安全级别以上?"\n"长时间聆听高音量可能会损伤听力。"</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"持续按住双指即可启用辅助功能。"</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"辅助功能已启用。"</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"已取消辅助功能。"</string>
<string name="user_switched" msgid="3768006783166984410">"当前用户是<xliff:g id="NAME">%1$s</xliff:g>。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 3301945..635b167 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI 螢幕"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"第 <xliff:g id="ID">%1$d</xliff:g> 個重疊效果"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>:<xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>,<xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"已連接無線顯示器"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"其他裝置正在顯示這個畫面"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"中斷連線"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"緊急電話"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"忘記圖形"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"圖形錯誤"</string>
@@ -1418,8 +1421,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"您的解鎖圖形已畫錯 <xliff:g id="NUMBER_0">%d</xliff:g> 次,如果再嘗試 <xliff:g id="NUMBER_1">%d</xliff:g> 次仍未成功,系統就會要求您透過電子郵件帳戶解除平板電腦的鎖定狀態。"\n\n"請在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒後再試一次。"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"您的解鎖圖形已畫錯 <xliff:g id="NUMBER_0">%d</xliff:g> 次,如果再嘗試 <xliff:g id="NUMBER_1">%d</xliff:g> 次仍未成功,系統就會要求您透過電子郵件帳戶解除手機的鎖定狀態。"\n\n"請在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒後再試一次。"</string>
<string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"要將音量調高到安全等級以上嗎?"\n"長時間聆聽偏高音量可能會損害您的聽力。"</string>
- <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
- <skip />
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"持續用兩指按住即可啟用協助工具。"</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"協助工具已啟用。"</string>
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"協助工具已取消。"</string>
<string name="user_switched" msgid="3768006783166984410">"目前的使用者是 <xliff:g id="NAME">%1$s</xliff:g>。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 75142fb..cb2f6eb 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1381,6 +1381,9 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Isikrini se-HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Isendlalelo #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+ <string name="wifi_display_notification_title" msgid="2223050649240326557">"Ukubukeka okungenantambo kuxhunyiwe"</string>
+ <string name="wifi_display_notification_message" msgid="4498802012464170685">"Lesi sikrini siyabonakala kwenye idivayisi"</string>
+ <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Nqamula"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Ucingo lwezimo eziphuthumayo"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Ukhohlwe iphethini?"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Iphatheni engalungile"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4698002..0890a18 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -636,19 +636,12 @@
of new location providers at run-time. The new package does not
have to be explicitly listed here, however it must have a signature
that matches the signature of at least one package on this list.
- Platforms should overlay additional packages in
- config_overlay_locationProviderPackageNames, instead of overlaying
- this config, if they only want to append packages and not replace
- the entire array.
-->
<string-array name="config_locationProviderPackageNames" translatable="false">
+ <!-- The standard AOSP fused location provider -->
<item>com.android.location.fused</item>
</string-array>
- <!-- Pacakge name(s) supplied by overlay, and appended to
- config_locationProviderPackageNames. -->
- <string-array name="config_overlay_locationProviderPackageNames" translatable="false" />
-
<!-- Boolean indicating if current platform supports bluetooth SCO for off call
use cases -->
<bool name="config_bluetooth_sco_off_call">true</bool>
@@ -902,8 +895,16 @@
<!-- Name of the wimax state tracker clas -->
<string name="config_wimaxStateTrackerClassname" translatable="false"></string>
- <!-- enable screen saver feature -->
- <bool name="config_enableDreams">true</bool>
+ <!-- Is the dreams feature supported? -->
+ <bool name="config_dreamsSupported">true</bool>
+ <!-- If supported, are dreams enabled? (by default) -->
+ <bool name="config_dreamsEnabledByDefault">true</bool>
+ <!-- If supported and enabled, are dreams activated when docked? (by default) -->
+ <bool name="config_dreamsActivatedOnDockByDefault">true</bool>
+ <!-- If supported and enabled, are dreams activated when asleep and charging? (by default) -->
+ <bool name="config_dreamsActivatedOnSleepByDefault">false</bool>
+ <!-- ComponentName of the default dream (Settings.Secure.SCREENSAVER_COMPONENT) -->
+ <string name="config_dreamsDefaultComponent">com.google.android.deskclock/com.android.deskclock.Screensaver</string>
<!-- Base "touch slop" value used by ViewConfiguration as a
movement threshold where scrolling should begin. -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 72de22c..f8dbd84 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3821,6 +3821,13 @@
<!-- Title text to show within the overlay. [CHAR LIMIT=50] -->
<string name="display_manager_overlay_display_title"><xliff:g id="name">%1$s</xliff:g>: <xliff:g id="width">%2$d</xliff:g>x<xliff:g id="height">%3$d</xliff:g>, <xliff:g id="dpi">%4$d</xliff:g> dpi</string>
+ <!-- Title of the notification to indicate an active wifi display connection. [CHAR LIMIT=50] -->
+ <string name="wifi_display_notification_title">Wireless display is connected</string>
+ <!-- Message of the notification to indicate an active wifi display connection. [CHAR LIMIT=80] -->
+ <string name="wifi_display_notification_message">This screen is showing on another device</string>
+ <!-- Label of a button to disconnect an active wifi display connection. [CHAR LIMIT=25] -->
+ <string name="wifi_display_notification_disconnect">Disconnect</string>
+
<!-- Keyguard strings -->
<!-- Label shown on emergency call button in keyguard -->
<string name="kg_emergency_call_label">Emergency call</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e76b67b..8ef91df 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1475,7 +1475,6 @@
<java-symbol type="array" name="radioAttributes" />
<java-symbol type="array" name="config_oemUsbModeOverride" />
<java-symbol type="array" name="config_locationProviderPackageNames" />
- <java-symbol type="array" name="config_overlay_locationProviderPackageNames" />
<java-symbol type="bool" name="config_animateScreenLights" />
<java-symbol type="bool" name="config_automatic_brightness_available" />
<java-symbol type="bool" name="config_sf_limitedAlpha" />
@@ -1486,6 +1485,7 @@
<java-symbol type="bool" name="show_ongoing_ime_switcher" />
<java-symbol type="color" name="config_defaultNotificationColor" />
<java-symbol type="drawable" name="ic_notification_ime_default" />
+ <java-symbol type="drawable" name="ic_notify_wifidisplay" />
<java-symbol type="drawable" name="stat_notify_car_mode" />
<java-symbol type="drawable" name="stat_notify_disabled" />
<java-symbol type="drawable" name="stat_notify_disk_full" />
@@ -1621,10 +1621,17 @@
<java-symbol type="string" name="vpn_lockdown_error" />
<java-symbol type="string" name="vpn_lockdown_reset" />
<java-symbol type="string" name="wallpaper_binding_label" />
+ <java-symbol type="string" name="wifi_display_notification_title" />
+ <java-symbol type="string" name="wifi_display_notification_message" />
+ <java-symbol type="string" name="wifi_display_notification_disconnect" />
<java-symbol type="style" name="Theme.Dialog.AppError" />
<java-symbol type="style" name="Theme.Toast" />
<java-symbol type="xml" name="storage_list" />
- <java-symbol type="bool" name="config_enableDreams" />
+ <java-symbol type="bool" name="config_dreamsSupported" />
+ <java-symbol type="bool" name="config_dreamsEnabledByDefault" />
+ <java-symbol type="bool" name="config_dreamsActivatedOnDockByDefault" />
+ <java-symbol type="bool" name="config_dreamsActivatedOnSleepByDefault" />
+ <java-symbol type="string" name="config_dreamsDefaultComponent" />
<java-symbol type="string" name="enable_explore_by_touch_warning_title" />
<java-symbol type="string" name="enable_explore_by_touch_warning_message" />
diff --git a/core/tests/ConnectivityManagerTest/AndroidManifest.xml b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
index 05f8b39..1bbc7df 100644
--- a/core/tests/ConnectivityManagerTest/AndroidManifest.xml
+++ b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
@@ -72,5 +72,6 @@
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DEVICE_POWER" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
</manifest>
diff --git a/core/tests/coretests/apks/install_bad_dex/AndroidManifest.xml b/core/tests/coretests/apks/install_bad_dex/AndroidManifest.xml
index fe4dd8e..76f0fe5 100644
--- a/core/tests/coretests/apks/install_bad_dex/AndroidManifest.xml
+++ b/core/tests/coretests/apks/install_bad_dex/AndroidManifest.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.frameworks.coretests.install_loc">
+ package="com.android.frameworks.coretests.install_bad_dex">
<application android:hasCode="true">
<activity
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 56070ee..04f8009 100755
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -981,19 +981,22 @@
try {
DeleteObserver observer = new DeleteObserver(pkgName);
- getPm().deletePackage(pkgName, observer, flags);
+ getPm().deletePackage(pkgName, observer, flags | PackageManager.DELETE_ALL_USERS);
observer.waitForCompletion(MAX_WAIT_TIME);
assertUninstalled(info);
// Verify we received the broadcast
- long waitTime = 0;
- while ((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME)) {
- receiver.wait(WAIT_TIME_INCR);
- waitTime += WAIT_TIME_INCR;
- }
- if (!receiver.isDone()) {
- throw new Exception("Timed out waiting for PACKAGE_REMOVED notification");
+ // TODO replace this with a CountDownLatch
+ synchronized (receiver) {
+ long waitTime = 0;
+ while ((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME)) {
+ receiver.wait(WAIT_TIME_INCR);
+ waitTime += WAIT_TIME_INCR;
+ }
+ if (!receiver.isDone()) {
+ throw new Exception("Timed out waiting for PACKAGE_REMOVED notification");
+ }
}
return receiver.received;
} finally {
@@ -1331,7 +1334,7 @@
}
DeleteObserver observer = new DeleteObserver(packageName);
- getPm().deletePackage(packageName, observer, 0);
+ getPm().deletePackage(packageName, observer, PackageManager.DELETE_ALL_USERS);
observer.waitForCompletion(MAX_WAIT_TIME);
try {
@@ -1357,7 +1360,7 @@
if (info != null) {
DeleteObserver observer = new DeleteObserver(pkgName);
- getPm().deletePackage(pkgName, observer, 0);
+ getPm().deletePackage(pkgName, observer, PackageManager.DELETE_ALL_USERS);
observer.waitForCompletion(MAX_WAIT_TIME);
assertUninstalled(info);
}
@@ -3126,7 +3129,7 @@
int rawResId = apk2;
Uri packageURI = getInstallablePackage(rawResId, outFile);
PackageParser.Package pkg = parsePackage(packageURI);
- getPm().deletePackage(pkg.packageName, null, 0);
+ getPm().deletePackage(pkg.packageName, null, PackageManager.DELETE_ALL_USERS);
// Check signatures now
int match = mContext.getPackageManager().checkSignatures(
ip1.pkg.packageName, pkg.packageName);
@@ -3265,7 +3268,7 @@
PackageManager pm = mContext.getPackageManager();
// Delete app2
PackageParser.Package pkg = getParsedPackage(apk2Name, apk2);
- getPm().deletePackage(pkg.packageName, null, 0);
+ getPm().deletePackage(pkg.packageName, null, PackageManager.DELETE_ALL_USERS);
// Check signatures now
int match = mContext.getPackageManager().checkSignatures(
ip1.pkg.packageName, pkg.packageName);
diff --git a/data/fonts/DroidNaskh-Bold.ttf b/data/fonts/DroidNaskh-Bold.ttf
index 692b796..14d8768 100644
--- a/data/fonts/DroidNaskh-Bold.ttf
+++ b/data/fonts/DroidNaskh-Bold.ttf
Binary files differ
diff --git a/data/fonts/DroidNaskh-Regular.ttf b/data/fonts/DroidNaskh-Regular.ttf
index da9a45f..03662f2 100644
--- a/data/fonts/DroidNaskh-Regular.ttf
+++ b/data/fonts/DroidNaskh-Regular.ttf
Binary files differ
diff --git a/data/sounds/effects/ogg/VideoRecord.ogg b/data/sounds/effects/ogg/VideoRecord.ogg
index d2dee03..0d7bf12 100644
--- a/data/sounds/effects/ogg/VideoRecord.ogg
+++ b/data/sounds/effects/ogg/VideoRecord.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/VideoRecord_48k.ogg b/data/sounds/effects/ogg/VideoRecord_48k.ogg
new file mode 100644
index 0000000..3eefaed
--- /dev/null
+++ b/data/sounds/effects/ogg/VideoRecord_48k.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/VideoStop.ogg b/data/sounds/effects/ogg/VideoStop.ogg
index f16ed13..a20d524 100644
--- a/data/sounds/effects/ogg/VideoStop.ogg
+++ b/data/sounds/effects/ogg/VideoStop.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/VideoStop_48k.ogg b/data/sounds/effects/ogg/VideoStop_48k.ogg
new file mode 100644
index 0000000..7fd9f47
--- /dev/null
+++ b/data/sounds/effects/ogg/VideoStop_48k.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/camera_click.ogg b/data/sounds/effects/ogg/camera_click.ogg
index 44b6683..130b534 100644
--- a/data/sounds/effects/ogg/camera_click.ogg
+++ b/data/sounds/effects/ogg/camera_click.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/camera_click_48k.ogg b/data/sounds/effects/ogg/camera_click_48k.ogg
new file mode 100644
index 0000000..b836e10
--- /dev/null
+++ b/data/sounds/effects/ogg/camera_click_48k.ogg
Binary files differ
diff --git a/docs/html/distribute/googleplay/promote/linking.jd b/docs/html/distribute/googleplay/promote/linking.jd
index 2d3bd05..46607f5 100644
--- a/docs/html/distribute/googleplay/promote/linking.jd
+++ b/docs/html/distribute/googleplay/promote/linking.jd
@@ -5,7 +5,7 @@
<div class="sidebox">
<a href="badges.html">
<img alt="Get it on Google Play"
- src="{@docRoot}en_app_rgb_wo_45.png" />
+ src="{@docRoot}images/brand/en_app_rgb_wo_45.png" />
</a>
<p>For a link that includes the Google Play brand icon, check out the <a href="badges.html">Badges</a> page. </p>
</div>
diff --git a/docs/html/distribute/googleplay/strategies/app-quality.jd b/docs/html/distribute/googleplay/strategies/app-quality.jd
index ecc51dc..eb2cd2b 100644
--- a/docs/html/distribute/googleplay/strategies/app-quality.jd
+++ b/docs/html/distribute/googleplay/strategies/app-quality.jd
@@ -37,7 +37,7 @@
<p>
The most obvious way to listen to users is by reading and addressing comments on your app in Google Play. Although the comments aren't always productive or constructive, some will provide valuable insight on aspects of your app that you may not have consciously considered before. It's important to remember that users have the opportunity to change their ratings and comments about an app as much as they'd like.</p>
<p>
-One way to reach users and help them address their concerns is to set up your own support and discussion destination(s). There are some great support tools out there that can put you in touch with your users directly such as <a href="http://groups.google.com">Google Groups</a>, <a href="http://discussions.zoho.com/">Zoho Discussions</a>, <a href="http://getsatisfaction.com">getsatisfaction.com</a> and <a href="http://uservoice.com">uservoice.com</a>. Once you get set up with such a tool, make sure to fill in the support link in your Google Play product details page — users do click through to these.</p>
+One way to reach users and help them address their concerns is to set up your own support and discussion destination(s). There are some great support tools out there that can put you in touch with your users directly, from forums such as <a href="http://groups.google.com">Google Groups</a> to comprehensive customer support products and destinations. Once you get set up with such a tool, make sure to fill in the support link in your Google Play product details page — users do click through to these.</p>
<p>
Another way to better listen to your users is by having a public beta or trusted tester program. It's crucial to have some amount of real user testing before releasing something in Google Play. Fortunately, you can distribute your apps to users outside of Google Play via a website; this website can require a login or be publicly accessible — it's entirely up to you. Take advantage of this opportunity by offering your next planned update to some early adopters, before submitting to Google Play. You'll be surprised by how many little, yet impactful, improvements can come out of crowd-sourced, real-user testing.</p>
@@ -51,7 +51,7 @@
<p>
Also, with the Google error-reporting features built into most Android devices, users now have a way to report application crashes to developers. The error reports show up in aggregate in the Google Play Developer Console. Make sure to read these reports often and act on them appropriately.</p>
<p>
-Last, keep an external bug and feature request tracker and let users know how to find it. This will enable them to engage with the app at a closer level, by following features and bugs that affect them. User frustration with app problems can be effectively managed with diligent issue tracking and communication. Some of the community support tools listed above offer issue tracking features, and if your project is open source, most popular repository hosting sites such as <a href="http://code.google.com/hosting">Google Code</a> and <a href="https://github.com/">GitHub</a> will offer this as well.</p>
+Last, keep an external bug and feature request tracker and let users know how to find it. This will enable them to engage with the app at a closer level, by following features and bugs that affect them. User frustration with app problems can be effectively managed with diligent issue tracking and communication. Some of the community support tools listed above offer issue tracking features, and if your project is open source, most popular repository hosting sites will offer this as well.</p>
<h2 id="responsiveness">Improve UI Responsiveness</h2>
<p>
@@ -96,9 +96,9 @@
<h2 id="appearance">Professional Appearance and Aesthetics</h2>
<p>
-There's no substitute for a real user interface designer — ideally one who's well-versed in mobile and Android, and ideally handy with both interaction and visual design. One popular venue to post openings for designers is <a href="http://jobs.smashingmagazine.com">jobs.smashingmagazine.com</a>, and leveraging social connections on Twitter and LinkedIn can surface great talent.</p>
+There's no substitute for a real user interface designer — ideally one who's well-versed in mobile and Android, and ideally handy with both interaction and visual design. One popular venue to post openings for designers is <a href="http://jobs.smashingmagazine.com">jobs.smashingmagazine.com</a>, and leveraging social networks can also surface great talent.</p>
<p>
-If you don't have the luxury of working with a UI designer, there are some ways in which you can improve your app's appearance yourself. First, get familiar with Adobe Photoshop, Adobe Fireworks, or some other raster image editing tool. Mastering the art of the pixel in these apps takes time, but honing this skill can help build polish across your interface designs. Also, master the resources framework by studying <a href="http://android.git.kernel.org/?p=platform/frameworks/base.git;a=tree;f=core/res/res;h=a3562fe1af94134486a8a899f02a9c2f7986c8dd;hb=master">the framework UI</a> assets and layouts and reading through the new <a href="{@docRoot}guide/topics/resources/index.html">resources documentation</a>. Techniques such as 9-patches and resource directory qualifiers are somewhat unique to Android, and are crucial in building flexible yet aesthetic UIs.</p>
+If you don't have the luxury of working with a UI designer, there are some ways in which you can improve your app's appearance yourself. First, get familiar with Adobe Photoshop, Adobe Fireworks, or some other raster image editing tool. Mastering the art of the pixel in these apps takes time, but honing this skill can help build polish across your interface designs. Also, master the resources framework by studying the framework UI assets and layouts and reading through the <a href="{@docRoot}guide/topics/resources/index.html">resources documentation</a>. Techniques such as 9-patches and resource directory qualifiers are somewhat unique to Android, and are crucial in building flexible yet aesthetic UIs.</p>
<p>
Before you get too far in designing your app and writing the code, make sure to visit the Android Design site and learn about the vision, the building blocks, and the tools of designing beautiful and inspiring user interfaces.</p>
@@ -114,8 +114,8 @@
<p>For some app categories, basic features like home screen widgets are par for the course. Not including them is a sure-fire way to tarnish an otherwise positive user experience. Some apps can achieve even tighter OS integration with Android's contacts, accounts, and sync APIs. </p>
<p>
-Third-party integrations can provide even more user delight and give the user a feeling of device cohesiveness. It's also a really nice way of adding functionality to your app without writing any extra code (by leveraging other apps' functionalities). For example, if you're creating a camera app, you can allow users to edit their photos in <a href=" http://mobile.photoshop.com/android/">Photoshop Express</a> before saving them to their collection, if they have that third-party application installed. More information on this subject is available in the class, <a href="{@docRoot}training/basics/intents/index.html">Interacting with Other Apps</a>.</p>
+Third-party integrations can provide even more user delight and give the user a feeling of device cohesiveness. It's also a really nice way of adding functionality to your app without writing any extra code (by leveraging other apps' functionalities). For example, if you're creating a camera app, you can allow users to edit their photos in another app before saving them to their collection, if they have that third-party application installed. More information on this subject is available in the Android Training class <a href="{@docRoot}training/basics/intents/index.html">Interacting with Other Apps</a>.</p>
<h2 id="details">Pay Attention to Details</h2>
<p>
-One particular detail to pay close attention to is your app's icon quality and consistency. Make sure your app icons (especially your launcher icon) are crisp and pixel-perfect at all resolutions, and follow the <a href="{@docRoot}guide/practices/ui_guidelines/icon_design.html">icon guidelines</a> as much as possible. If you're having trouble or don't have the resources to design the icons yourself, consider using the new <a href="http://android-ui-utils.googlecode.com/hg/asset-studio/dist/index.html">Android Asset Studio</a> tool to generate a set.</p>
+One particular detail to pay close attention to is your app's icon quality and consistency. Make sure your app icons (especially your launcher icon) are crisp and pixel-perfect at all resolutions, and follow the <a href="{@docRoot}guide/practices/ui_guidelines/icon_design.html">icon guidelines</a> as much as possible. If you're having trouble or don't have the resources to design the icons yourself, consider using the <a href="http://android-ui-utils.googlecode.com/hg/asset-studio/dist/index.html">Android Asset Studio</a> tool to generate a set.</p>
diff --git a/docs/html/guide/topics/ui/dialogs.jd b/docs/html/guide/topics/ui/dialogs.jd
index 62c054a..3cfed13 100644
--- a/docs/html/guide/topics/ui/dialogs.jd
+++ b/docs/html/guide/topics/ui/dialogs.jd
@@ -119,7 +119,7 @@
a {@link android.support.v4.app.DialogFragment}:</p>
<pre>
-public class FireMissilesDialog extends DialogFragment {
+public class FireMissilesDialogFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the Builder class for convenient dialog construction
@@ -469,7 +469,7 @@
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
- NoticeDialog.this.getDialog().cancel();
+ LoginDialogFragment.this.getDialog().cancel();
}
});
return builder.create();
@@ -497,15 +497,15 @@
<p>When the user touches one of the dialog's action buttons or selects an item from its list,
your {@link android.support.v4.app.DialogFragment} might perform the necessary
action itself, but often you'll want to deliver the event to the activity or fragment that
-opened the dialog. To do this, define an interface with a method for each type of click event,
-then implement that interface in the host component that will
+opened the dialog. To do this, define an interface with a method for each type of click event.
+Then implement that interface in the host component that will
receive the action events from the dialog.</p>
<p>For example, here's a {@link android.support.v4.app.DialogFragment} that defines an
interface through which it delivers the events back to the host activity:</p>
<pre>
-public class NoticeDialog extends DialogFragment {
+public class NoticeDialogFragment extends DialogFragment {
/* The activity that creates an instance of this dialog fragment must
* implement this interface in order to receive event callbacks.
@@ -516,48 +516,44 @@
}
// Use this instance of the interface to deliver action events
- static NoticeDialogListener mListener;
-
- /* Call this to instantiate a new NoticeDialog.
- * @param activity The activity hosting the dialog, which must implement the
- * NoticeDialogListener to receive event callbacks.
- * @returns A new instance of NoticeDialog.
- * @throws ClassCastException if the host activity does not
- * implement NoticeDialogListener
- */
- public static NoticeDialog newInstance(Activity activity) {
+ NoticeDialogListener mListener;
+
+ // Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
// Verify that the host activity implements the callback interface
try {
- // Instantiate the NoticeDialogListener so we can send events with it
+ // Instantiate the NoticeDialogListener so we can send events to the host
mListener = (NoticeDialogListener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
throw new ClassCastException(activity.toString()
+ " must implement NoticeDialogListener");
}
- NoticeDialog frag = new NoticeDialog();
- return frag;
}
-
...
}
</pre>
-<p>The activity hosting the dialog creates and shows an instance of the dialog
-by calling {@code NoticeDialog.newInstance()} and receives the dialog's
+<p>The activity hosting the dialog creates an instance of the dialog
+with the dialog fragment's constructor and receives the dialog's
events through an implementation of the {@code NoticeDialogListener} interface:</p>
<pre>
public class MainActivity extends FragmentActivity
- implements NoticeDialog.NoticeDialogListener{
+ implements NoticeDialogFragment.NoticeDialogListener{
...
public void showNoticeDialog() {
// Create an instance of the dialog fragment and show it
- DialogFragment dialog = NoticeDialog.newInstance(this);
- dialog.show(getSupportFragmentManager(), "NoticeDialog");
+ DialogFragment dialog = new NoticeDialogFragment();
+ dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
}
+ // The dialog fragment receives a reference to this Activity through the
+ // Fragment.onAttach() callback, which it uses to call the following methods
+ // defined by the NoticeDialogFragment.NoticeDialogListener interface
@Override
public void onDialogPositiveClick(DialogFragment dialog) {
// User touched the dialog's positive button
@@ -573,11 +569,12 @@
</pre>
<p>Because the host activity implements the {@code NoticeDialogListener}—which is
-enforced by the {@code newInstance()} method shown above—the dialog fragment can use the
+enforced by the {@link android.support.v4.app.Fragment#onAttach onAttach()}
+callback method shown above—the dialog fragment can use the
interface callback methods to deliver click events to the activity:</p>
<pre>
-public class NoticeDialog extends DialogFragment {
+public class NoticeDialogFragment extends DialogFragment {
...
@Override
@@ -588,13 +585,13 @@
.setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Send the positive button event back to the host activity
- mListener.onDialogPositiveClick(NoticeDialog.this);
+ mListener.onDialogPositiveClick(NoticeDialogFragment.this);
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Send the negative button event back to the host activity
- mListener.onDialogPositiveClick(NoticeDialog.this);
+ mListener.onDialogPositiveClick(NoticeDialogFragment.this);
}
});
return builder.create();
@@ -604,8 +601,6 @@
-
-
<h2 id="ShowingADialog">Showing a Dialog</h2>
<p>When you want to show your dialog, create an instance of your {@link
@@ -621,7 +616,7 @@
<pre>
public void confirmFireMissiles() {
- DialogFragment newFragment = FireMissilesDialog.newInstance(this);
+ DialogFragment newFragment = new FireMissilesDialogFragment();
newFragment.show(getSupportFragmentManager(), "missiles");
}
</pre>
@@ -653,7 +648,7 @@
dialog or an embeddable fragment (using a layout named <code>purchase_items.xml</code>):</p>
<pre>
-public class CustomLayoutDialog extends DialogFragment {
+public class CustomDialogFragment extends DialogFragment {
/** The system calls this to get the DialogFragment's layout, regardless
of whether it's being displayed as a dialog or an embedded fragment. */
@Override
@@ -683,7 +678,7 @@
<pre>
public void showDialog() {
FragmentManager fragmentManager = getSupportFragmentManager();
- CustomLayoutDialog newFragment = new CustomLayoutDialog();
+ CustomDialogFragment newFragment = new CustomDialogFragment();
if (mIsLargeLayout) {
// The device is using a large layout, so show the fragment as a dialog
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 6238edb..688fd7a 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -201,9 +201,14 @@
*/
public void recycle() {
if (!mRecycled) {
- mBuffer = null;
- nativeRecycle(mNativeBitmap);
- mNinePatchChunk = null;
+ if (nativeRecycle(mNativeBitmap)) {
+ // return value indicates whether native pixel object was actually recycled.
+ // false indicates that it is still in use at the native level and these
+ // objects should not be collected now. They will be collected later when the
+ // Bitmap itself is collected.
+ mBuffer = null;
+ mNinePatchChunk = null;
+ }
mRecycled = true;
}
}
@@ -1030,6 +1035,51 @@
}
/**
+ * Indicates whether the renderer responsible for drawing this
+ * bitmap should attempt to use mipmaps when this bitmap is drawn
+ * scaled down.
+ *
+ * If you know that you are going to draw this bitmap at less than
+ * 50% of its original size, you may be able to obtain a higher
+ * quality
+ *
+ * This property is only a suggestion that can be ignored by the
+ * renderer. It is not guaranteed to have any effect.
+ *
+ * @return true if the renderer should attempt to use mipmaps,
+ * false otherwise
+ *
+ * @see #setHasMipMap(boolean)
+ */
+ public final boolean hasMipMap() {
+ return nativeHasMipMap(mNativeBitmap);
+ }
+
+ /**
+ * Set a hint for the renderer responsible for drawing this bitmap
+ * indicating that it should attempt to use mipmaps when this bitmap
+ * is drawn scaled down.
+ *
+ * If you know that you are going to draw this bitmap at less than
+ * 50% of its original size, you may be able to obtain a higher
+ * quality by turning this property on.
+ *
+ * Note that if the renderer respects this hint it might have to
+ * allocate extra memory to hold the mipmap levels for this bitmap.
+ *
+ * This property is only a suggestion that can be ignored by the
+ * renderer. It is not guaranteed to have any effect.
+ *
+ * @param hasMipMap indicates whether the renderer should attempt
+ * to use mipmaps
+ *
+ * @see #hasMipMap()
+ */
+ public final void setHasMipMap(boolean hasMipMap) {
+ nativeSetHasMipMap(mNativeBitmap, hasMipMap);
+ }
+
+ /**
* Fills the bitmap's pixels with the specified {@link Color}.
*
* @throws IllegalStateException if the bitmap is not mutable.
@@ -1346,7 +1396,7 @@
private static native Bitmap nativeCopy(int srcBitmap, int nativeConfig,
boolean isMutable);
private static native void nativeDestructor(int nativeBitmap);
- private static native void nativeRecycle(int nativeBitmap);
+ private static native boolean nativeRecycle(int nativeBitmap);
private static native boolean nativeCompress(int nativeBitmap, int format,
int quality, OutputStream stream,
@@ -1356,7 +1406,6 @@
private static native int nativeHeight(int nativeBitmap);
private static native int nativeRowBytes(int nativeBitmap);
private static native int nativeConfig(int nativeBitmap);
- private static native boolean nativeHasAlpha(int nativeBitmap);
private static native int nativeGetPixel(int nativeBitmap, int x, int y);
private static native void nativeGetPixels(int nativeBitmap, int[] pixels,
@@ -1385,7 +1434,10 @@
int[] offsetXY);
private static native void nativePrepareToDraw(int nativeBitmap);
+ private static native boolean nativeHasAlpha(int nativeBitmap);
private static native void nativeSetHasAlpha(int nBitmap, boolean hasAlpha);
+ private static native boolean nativeHasMipMap(int nativeBitmap);
+ private static native void nativeSetHasMipMap(int nBitmap, boolean hasMipMap);
private static native boolean nativeSameAs(int nb0, int nb1);
/* package */ final int ni() {
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index d18a5b0..e7085b0 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -399,9 +399,20 @@
if (scissorEnabled && (x != mScissorX || y != mScissorY ||
width != mScissorWidth || height != mScissorHeight)) {
- if (x < 0) x = 0;
- if (y < 0) y = 0;
-
+ if (x < 0) {
+ width += x;
+ x = 0;
+ }
+ if (y < 0) {
+ height += y;
+ y = 0;
+ }
+ if (width < 0) {
+ width = 0;
+ }
+ if (height < 0) {
+ height = 0;
+ }
glScissor(x, y, width, height);
mScissorX = x;
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 589d5c2..81e68bd 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -1434,7 +1434,7 @@
mHeight = height;
}
-int DisplayListRenderer::prepareDirty(float left, float top,
+status_t DisplayListRenderer::prepareDirty(float left, float top,
float right, float bottom, bool opaque) {
mSnapshot = new Snapshot(mFirstSnapshot,
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 2610055..e42def5 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -550,7 +550,7 @@
virtual bool isDeferred();
virtual void setViewport(int width, int height);
- virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque);
+ virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque);
virtual void finish();
virtual status_t callDrawGLFunction(Functor *functor, Rect& dirty);
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 882e4bb..1cdc063 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -31,6 +31,7 @@
meshIndices = NULL;
meshElementCount = 0;
cacheable = true;
+ dirty = false;
textureLayer = false;
renderTarget = GL_TEXTURE_2D;
texture.width = layerWidth;
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 69be317..e1f6a70 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -162,6 +162,14 @@
this->cacheable = cacheable;
}
+ inline bool isDirty() {
+ return dirty;
+ }
+
+ inline void setDirty(bool dirty) {
+ this->dirty = dirty;
+ }
+
inline bool isTextureLayer() {
return textureLayer;
}
@@ -209,6 +217,9 @@
}
inline void allocateTexture(GLenum format, GLenum storage) {
+#if DEBUG_LAYERS
+ ALOGD(" Allocate layer: %dx%d", getWidth(), getHeight());
+#endif
glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0, format, storage, NULL);
}
@@ -284,6 +295,12 @@
bool textureLayer;
/**
+ * When set to true, this layer is dirty and should be cleared
+ * before any rendering occurs.
+ */
+ bool dirty;
+
+ /**
* Indicates the render target.
*/
GLenum renderTarget;
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index f2e7f66..3484d41 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -18,6 +18,8 @@
#include <ui/Rect.h>
+#include <private/hwui/DrawGlInfo.h>
+
#include "LayerCache.h"
#include "LayerRenderer.h"
#include "Matrix.h"
@@ -41,7 +43,8 @@
initViewport(width, height);
}
-int LayerRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) {
+status_t LayerRenderer::prepareDirty(float left, float top, float right, float bottom,
+ bool opaque) {
LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo());
glBindFramebuffer(GL_FRAMEBUFFER, mLayer->getFbo());
@@ -63,6 +66,20 @@
return OpenGLRenderer::prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, opaque);
}
+status_t LayerRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
+ if (mLayer->isDirty()) {
+ getCaches().disableScissor();
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ getCaches().resetScissor();
+ mLayer->setDirty(false);
+
+ return DrawGlInfo::kStatusDone;
+ }
+
+ return OpenGLRenderer::clear(left, top, right, bottom, opaque);
+}
+
void LayerRenderer::finish() {
OpenGLRenderer::finish();
@@ -201,6 +218,7 @@
layer->setAlpha(255, SkXfermode::kSrcOver_Mode);
layer->setBlend(!isOpaque);
layer->setColorFilter(NULL);
+ layer->setDirty(true);
layer->region.clear();
GLuint previousFbo;
@@ -229,9 +247,6 @@
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
layer->getTexture(), 0);
- caches.disableScissor();
- glClear(GL_COLOR_BUFFER_BIT);
-
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
return layer;
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index acedbcc..c44abce 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -48,7 +48,8 @@
virtual ~LayerRenderer();
virtual void setViewport(int width, int height);
- virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque);
+ virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque);
+ virtual status_t clear(float left, float top, float right, float bottom, bool opaque);
virtual void finish();
ANDROID_API static Layer* createTextureLayer(bool isOpaque);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 89cefe0..914516c 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -49,7 +49,7 @@
#define ALPHA_THRESHOLD 0
-#define FILTER(paint) (paint && paint->isFilterBitmap() ? GL_LINEAR : GL_NEAREST)
+#define FILTER(paint) (!paint || paint->isFilterBitmap() ? GL_LINEAR : GL_NEAREST)
///////////////////////////////////////////////////////////////////////////////
// Globals
@@ -165,11 +165,12 @@
mFirstSnapshot->viewport.set(0, 0, width, height);
}
-int OpenGLRenderer::prepare(bool opaque) {
+status_t OpenGLRenderer::prepare(bool opaque) {
return prepareDirty(0.0f, 0.0f, mWidth, mHeight, opaque);
}
-int OpenGLRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) {
+status_t OpenGLRenderer::prepareDirty(float left, float top, float right, float bottom,
+ bool opaque) {
mCaches.clearGarbage();
mSnapshot = new Snapshot(mFirstSnapshot,
@@ -203,15 +204,18 @@
debugOverdraw(true, true);
+ return clear(left, top, right, bottom, opaque);
+}
+
+status_t OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
if (!opaque) {
mCaches.enableScissor();
mCaches.setScissor(left, mSnapshot->height - bottom, right - left, bottom - top);
glClear(GL_COLOR_BUFFER_BIT);
return DrawGlInfo::kStatusDrew;
- } else {
- mCaches.resetScissor();
}
+ mCaches.resetScissor();
return DrawGlInfo::kStatusDone;
}
@@ -743,6 +747,7 @@
bounds.getWidth() / float(layer->getWidth()), 0.0f);
layer->setColorFilter(mColorFilter);
layer->setBlend(true);
+ layer->setDirty(false);
// Save the layer in the snapshot
mSnapshot->flags |= Snapshot::kFlagIsLayer;
@@ -895,12 +900,6 @@
void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
float alpha = layer->getAlpha() / 255.0f;
- mat4& transform = layer->getTransform();
- if (!transform.isIdentity()) {
- save(0);
- mSnapshot->transform->multiply(transform);
- }
-
setupDraw();
if (layer->getRenderTarget() == GL_TEXTURE_2D) {
setupDrawWithTexture();
@@ -937,10 +936,6 @@
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
finishDrawTexture();
-
- if (!transform.isIdentity()) {
- restore();
- }
}
void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
@@ -2792,12 +2787,24 @@
return DrawGlInfo::kStatusDone;
}
+ mat4* transform = NULL;
+ if (layer->isTextureLayer()) {
+ transform = &layer->getTransform();
+ if (!transform->isIdentity()) {
+ save(0);
+ mSnapshot->transform->multiply(*transform);
+ }
+ }
+
Rect transformed;
Rect clip;
const bool rejected = quickRejectNoScissor(x, y,
x + layer->layer.getWidth(), y + layer->layer.getHeight(), transformed, clip);
if (rejected) {
+ if (transform && !transform->isIdentity()) {
+ restore();
+ }
return DrawGlInfo::kStatusDone;
}
@@ -2858,6 +2865,10 @@
}
}
+ if (transform && !transform->isIdentity()) {
+ restore();
+ }
+
return DrawGlInfo::kStatusDrew;
}
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index a40d69a..c5e4c8e 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -94,7 +94,7 @@
* and will not be cleared. If false, the target surface
* will be cleared
*/
- ANDROID_API int prepare(bool opaque);
+ ANDROID_API status_t prepare(bool opaque);
/**
* Prepares the renderer to draw a frame. This method must be invoked
@@ -110,7 +110,7 @@
* and will not be cleared. If false, the target surface
* will be cleared in the specified dirty rectangle
*/
- virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque);
+ virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque);
/**
* Indicates the end of a frame. This method must be invoked whenever
@@ -270,6 +270,11 @@
void initViewport(int width, int height);
/**
+ * Clears the underlying surface if needed.
+ */
+ virtual status_t clear(float left, float top, float right, float bottom, bool opaque);
+
+ /**
* Call this method after updating a layer during a drawing pass.
*/
void resumeAfterLayer();
@@ -355,6 +360,10 @@
return false;
}
+ Caches& getCaches() {
+ return mCaches;
+ }
+
private:
/**
* Ensures the state of the renderer is the same as the state of
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 81f7b94..347bd78 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -265,27 +265,38 @@
}
}
-void ResourceCache::recycle(SkBitmap* resource) {
+/**
+ * Return value indicates whether resource was actually recycled, which happens when RefCnt
+ * reaches 0.
+ */
+bool ResourceCache::recycle(SkBitmap* resource) {
Mutex::Autolock _l(mLock);
- recycleLocked(resource);
+ return recycleLocked(resource);
}
-void ResourceCache::recycleLocked(SkBitmap* resource) {
+/**
+ * Return value indicates whether resource was actually recycled, which happens when RefCnt
+ * reaches 0.
+ */
+bool ResourceCache::recycleLocked(SkBitmap* resource) {
ssize_t index = mCache->indexOfKey(resource);
if (index < 0) {
// not tracking this resource; just recycle the pixel data
resource->setPixels(NULL, NULL);
- return;
+ return true;
}
ResourceReference* ref = mCache->valueAt(index);
if (ref == NULL) {
// Should not get here - shouldn't get a call to recycle if we're not yet tracking it
- return;
+ return true;
}
ref->recycled = true;
if (ref->refCount == 0) {
deleteResourceReferenceLocked(resource, ref);
+ return true;
}
+ // Still referring to resource, don't recycle yet
+ return false;
}
/**
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index a80670c..ab493e5 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -99,8 +99,8 @@
void destructorLocked(SkiaShader* resource);
void destructorLocked(SkiaColorFilter* resource);
- void recycle(SkBitmap* resource);
- void recycleLocked(SkBitmap* resource);
+ bool recycle(SkBitmap* resource);
+ bool recycleLocked(SkBitmap* resource);
private:
void deleteResourceReferenceLocked(void* resource, ResourceReference* ref);
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index 03e2172..8d88bdc 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -36,6 +36,8 @@
minFilter = GL_NEAREST;
magFilter = GL_NEAREST;
+ mipMap = false;
+
firstFilter = true;
firstWrap = true;
@@ -83,6 +85,8 @@
glBindTexture(renderTarget, id);
}
+ if (mipMap && min == GL_LINEAR) min = GL_LINEAR_MIPMAP_LINEAR;
+
glTexParameteri(renderTarget, GL_TEXTURE_MIN_FILTER, min);
glTexParameteri(renderTarget, GL_TEXTURE_MAG_FILTER, mag);
}
@@ -116,7 +120,12 @@
* Optional, size of the original bitmap.
*/
uint32_t bitmapSize;
+ /**
+ * Indicates whether this texture will use trilinear filtering.
+ */
+ bool mipMap;
+private:
/**
* Last wrap modes set on this texture. Defaults to GL_CLAMP_TO_EDGE.
*/
@@ -129,7 +138,6 @@
GLenum minFilter;
GLenum magFilter;
-private:
bool firstFilter;
bool firstWrap;
}; // struct Texture
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 4d16bb4..10d112a 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -22,6 +22,7 @@
#include <utils/threads.h>
+#include "Caches.h"
#include "TextureCache.h"
#include "Properties.h"
@@ -216,8 +217,15 @@
return;
}
+ // We could also enable mipmapping if both bitmap dimensions are powers
+ // of 2 but we'd have to deal with size changes. Let's keep this simple
+ const bool canMipMap = Caches::getInstance().extensions.hasNPot();
+
+ // If the texture had mipmap enabled but not anymore,
+ // force a glTexImage2D to discard the mipmap levels
const bool resize = !regenerate || bitmap->width() != int(texture->width) ||
- bitmap->height() != int(texture->height);
+ bitmap->height() != int(texture->height) ||
+ (regenerate && canMipMap && texture->mipMap && !bitmap->hasHardwareMipMap());
if (!regenerate) {
glGenTextures(1, &texture->id);
@@ -261,6 +269,13 @@
break;
}
+ if (canMipMap) {
+ texture->mipMap = bitmap->hasHardwareMipMap();
+ if (texture->mipMap) {
+ glGenerateMipmap(GL_TEXTURE_2D);
+ }
+ }
+
if (!regenerate) {
texture->setFilter(GL_NEAREST);
texture->setWrap(GL_CLAMP_TO_EDGE);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 4ad8fd0..59a5624 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -72,15 +72,10 @@
* <p class="note">Unless noted, all Location API methods require
* the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} or
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permissions.
- * If your application only has the Coarse permission then it will still
- * receive location results, but the update rate will be throttled and
- * the exact location will be obfuscated to a coarse level of accuracy.
- *
- * <p> class="note">Before API level 17, the use of 'fine' location
- * providers such as GPS required the fine permission. As of API level
- * 17, applications with only the coarse permission may use all providers,
- * including GPS, but the locations are obfuscated (made coarse) before
- * being sent to the application.
+ * If your application only has the coarse permission then it will not have
+ * access to the GPS or passive location providers. Other providers will still
+ * return location results, but the update rate will be throttled and the exact
+ * location will be obfuscated to a coarse level of accuracy.
*/
public class LocationManager {
private static final String TAG = "LocationManager";
@@ -109,13 +104,8 @@
*
* <p>This provider determines location using
* satellites. Depending on conditions, this provider may take a while to return
- * a location fix.
- *
- * <p>Before API version 17, this provider required the
- * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission.
- * From API version 17 and onwards, this provider can also be used with
- * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}, however
- * the locations returned will be obfuscated to a coarse level of accuracy.
+ * a location fix. Requires the permission
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* <p> The extras Bundle for the GPS location provider can contain the
* following key/value pairs:
@@ -136,13 +126,9 @@
* when other applications or services request them without actually requesting
* the locations yourself. This provider will return locations generated by other
* providers. You can query the {@link Location#getProvider()} method to determine
- * the origin of the location update.
- *
- * <p>Before API version 17, this provider required the
- * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission.
- * From API version 17 and onwards, this provider can also be used with
- * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}, however
- * the locations returned will be obfuscated to a coarse level of accuracy.
+ * the origin of the location update. Requires the permission
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}, although if the GPS is
+ * not enabled this provider might only return coarse fixes.
*
* @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
*/
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index cb291ea..6871ee2 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -221,6 +221,18 @@
/** @hide */
public LocationRequest() { }
+ /** @hide */
+ public LocationRequest(LocationRequest src) {
+ mQuality = src.mQuality;
+ mInterval = src.mInterval;
+ mFastestInterval = src.mFastestInterval;
+ mExplicitFastestInterval = src.mExplicitFastestInterval;
+ mExpireAt = src.mExpireAt;
+ mNumUpdates = src.mNumUpdates;
+ mSmallestDisplacement = src.mSmallestDisplacement;
+ mProvider = src.mProvider;
+ }
+
/**
* Set the quality of the request.
*
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index f77cbfb..dd320a0 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -634,7 +634,8 @@
final ContentResolver cr = mContentResolver;
int ringerModeFromSettings =
- Settings.Global.getInt(cr, System.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
+ Settings.Global.getInt(
+ cr, Settings.Global.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
int ringerMode = ringerModeFromSettings;
// sanity check in case the settings are restored from a device with incompatible
// ringer modes
@@ -645,7 +646,7 @@
ringerMode = AudioManager.RINGER_MODE_SILENT;
}
if (ringerMode != ringerModeFromSettings) {
- Settings.Global.putInt(cr, System.MODE_RINGER, ringerMode);
+ Settings.Global.putInt(cr, Settings.Global.MODE_RINGER, ringerMode);
}
synchronized(mSettingsLock) {
mRingerMode = ringerMode;
@@ -3118,7 +3119,7 @@
}
private void persistRingerMode(int ringerMode) {
- Settings.Global.putInt(mContentResolver, System.MODE_RINGER, ringerMode);
+ Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode);
}
private void playSoundEffect(int effectType, int volume) {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
index 9b1098e..1c60401 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
@@ -114,10 +114,10 @@
mProcMemWriter = new BufferedWriter(new FileWriter
(new File(MEDIA_PROCMEM_OUTPUT), true));
mProcMemWriter.write(this.getName() + "\n");
- mMemWriter = new BufferedWriter(new FileWriter
- (new File(MEDIA_MEMORY_OUTPUT), true));
}
-
+ mMemWriter = new BufferedWriter(new FileWriter
+ (new File(MEDIA_MEMORY_OUTPUT), true));
+ mMemWriter.write(this.getName() + "\n");
}
@Override
@@ -126,10 +126,10 @@
MediaTestUtil.getNativeHeapDump(this.getName() + "_after");
if (MediaFrameworkPerfTestRunner.mGetProcmem) {
- mMemWriter.write("\n");
mProcMemWriter.close();
- mMemWriter.close();
}
+ mMemWriter.write("\n");
+ mMemWriter.close();
super.tearDown();
}
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 76b1ec6..cf56cba 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -259,6 +259,21 @@
eraseFiles(directory);
}
}
+
+ @Override
+ public long calculateInstalledSize(String packagePath, boolean isForwardLocked)
+ throws RemoteException {
+ final File packageFile = new File(packagePath);
+ try {
+ return calculateContainerSize(packageFile, isForwardLocked) * 1024 * 1024;
+ } catch (IOException e) {
+ /*
+ * Okay, something failed, so let's just estimate it to be 2x
+ * the file size. Note this will be 0 if the file doesn't exist.
+ */
+ return packageFile.length() * 2;
+ }
+ }
};
public DefaultContainerService() {
diff --git a/packages/FusedLocation/AndroidManifest.xml b/packages/FusedLocation/AndroidManifest.xml
index 4c57401..10b9064 100644
--- a/packages/FusedLocation/AndroidManifest.xml
+++ b/packages/FusedLocation/AndroidManifest.xml
@@ -18,7 +18,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.location.fused"
- coreApp="true">
+ coreApp="true"
+ android:sharedUserId="android.uid.system">
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
@@ -39,7 +40,7 @@
<intent-filter>
<action android:name="com.android.location.service.FusedLocationProvider" />
</intent-filter>
- <meta-data android:name="version" android:value="1" />
+ <meta-data android:name="serviceVersion" android:value="0" />
</service>
</application>
</manifest>
diff --git a/packages/SettingsProvider/res/values-af/defaults.xml b/packages/SettingsProvider/res/values-af/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-af/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-am/defaults.xml b/packages/SettingsProvider/res/values-am/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-am/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-ar/defaults.xml b/packages/SettingsProvider/res/values-ar/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-ar/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-be/defaults.xml b/packages/SettingsProvider/res/values-be/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-be/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-bg/defaults.xml b/packages/SettingsProvider/res/values-bg/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-bg/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-ca/defaults.xml b/packages/SettingsProvider/res/values-ca/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-ca/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-cs/defaults.xml b/packages/SettingsProvider/res/values-cs/defaults.xml
deleted file mode 100644
index f704333..0000000
--- a/packages/SettingsProvider/res/values-cs/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Spořič obrazovky"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-da/defaults.xml b/packages/SettingsProvider/res/values-da/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-da/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-de/defaults.xml b/packages/SettingsProvider/res/values-de/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-de/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-el/defaults.xml b/packages/SettingsProvider/res/values-el/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-el/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-en-rGB/defaults.xml b/packages/SettingsProvider/res/values-en-rGB/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-en-rGB/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-es-rUS/defaults.xml b/packages/SettingsProvider/res/values-es-rUS/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-es-rUS/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-es/defaults.xml b/packages/SettingsProvider/res/values-es/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-es/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-et/defaults.xml b/packages/SettingsProvider/res/values-et/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-et/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-fa/defaults.xml b/packages/SettingsProvider/res/values-fa/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-fa/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-fi/defaults.xml b/packages/SettingsProvider/res/values-fi/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-fi/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-fr/defaults.xml b/packages/SettingsProvider/res/values-fr/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-fr/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-hi/defaults.xml b/packages/SettingsProvider/res/values-hi/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-hi/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-hr/defaults.xml b/packages/SettingsProvider/res/values-hr/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-hr/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-hu/defaults.xml b/packages/SettingsProvider/res/values-hu/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-hu/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-in/defaults.xml b/packages/SettingsProvider/res/values-in/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-in/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-it/defaults.xml b/packages/SettingsProvider/res/values-it/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-it/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-iw/defaults.xml b/packages/SettingsProvider/res/values-iw/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-iw/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-ja/defaults.xml b/packages/SettingsProvider/res/values-ja/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-ja/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-ko/defaults.xml b/packages/SettingsProvider/res/values-ko/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-ko/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-lt/defaults.xml b/packages/SettingsProvider/res/values-lt/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-lt/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-lv/defaults.xml b/packages/SettingsProvider/res/values-lv/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-lv/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-ms/defaults.xml b/packages/SettingsProvider/res/values-ms/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-ms/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-nb/defaults.xml b/packages/SettingsProvider/res/values-nb/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-nb/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-nl/defaults.xml b/packages/SettingsProvider/res/values-nl/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-nl/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-pl/defaults.xml b/packages/SettingsProvider/res/values-pl/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-pl/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-pt-rPT/defaults.xml b/packages/SettingsProvider/res/values-pt-rPT/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-pt-rPT/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-pt/defaults.xml b/packages/SettingsProvider/res/values-pt/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-pt/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-ro/defaults.xml b/packages/SettingsProvider/res/values-ro/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-ro/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-ru/defaults.xml b/packages/SettingsProvider/res/values-ru/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-ru/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-sk/defaults.xml b/packages/SettingsProvider/res/values-sk/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-sk/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-sl/defaults.xml b/packages/SettingsProvider/res/values-sl/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-sl/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-sr/defaults.xml b/packages/SettingsProvider/res/values-sr/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-sr/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-sv/defaults.xml b/packages/SettingsProvider/res/values-sv/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-sv/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-sw/defaults.xml b/packages/SettingsProvider/res/values-sw/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-sw/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-th/defaults.xml b/packages/SettingsProvider/res/values-th/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-th/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-tl/defaults.xml b/packages/SettingsProvider/res/values-tl/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-tl/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-tr/defaults.xml b/packages/SettingsProvider/res/values-tr/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-tr/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-uk/defaults.xml b/packages/SettingsProvider/res/values-uk/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-uk/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-vi/defaults.xml b/packages/SettingsProvider/res/values-vi/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-vi/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-zh-rCN/defaults.xml b/packages/SettingsProvider/res/values-zh-rCN/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-zh-rCN/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-zh-rTW/defaults.xml b/packages/SettingsProvider/res/values-zh-rTW/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-zh-rTW/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values-zu/defaults.xml b/packages/SettingsProvider/res/values-zu/defaults.xml
deleted file mode 100644
index f8c3de3..0000000
--- a/packages/SettingsProvider/res/values-zu/defaults.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
-</resources>
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 9e137ce..94e2286 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -165,16 +165,6 @@
Value here is the same as WifiStateMachine.DEFAULT_MAX_DHCP_RETRIES -->
<integer name="def_max_dhcp_retries">9</integer>
- <!-- Dreams (screen saver) default settings -->
- <!-- Whether the feature is enabled when charging (Settings.Secure.SCREENSAVER_ENABLED) -->
- <bool name="def_screensaver_enabled">true</bool>
- <!-- Whether the feature activates when docked (SCREENSAVER_ACTIVATE_ON_DOCK) -->
- <bool name="def_screensaver_activate_on_dock">true</bool>
- <!-- Whether the feature activates when docked (SCREENSAVER_ACTIVATE_ON_SLEEP) -->
- <bool name="def_screensaver_activate_on_sleep">false</bool>
- <!-- ComponentName of the default screen saver (Settings.Secure.SCREENSAVER_COMPONENT) -->
- <string name="def_screensaver_component">com.google.android.deskclock/com.android.deskclock.Screensaver</string>
-
<!-- Default for Settings.Secure.USER_SETUP_COMPLETE -->
<bool name="def_user_setup_complete">false</bool>
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 0689268..b649b43 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -1166,15 +1166,15 @@
stmt = db.compileStatement("INSERT OR REPLACE INTO secure(name,value)"
+ " VALUES(?,?);");
loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ENABLED,
- R.bool.def_screensaver_enabled);
+ com.android.internal.R.bool.config_dreamsEnabledByDefault);
loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
- R.bool.def_screensaver_activate_on_dock);
+ com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
- R.bool.def_screensaver_activate_on_sleep);
- loadStringSetting(stmt, Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
- R.string.def_screensaver_component);
+ com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault);
loadStringSetting(stmt, Settings.Secure.SCREENSAVER_COMPONENTS,
- R.string.def_screensaver_component);
+ com.android.internal.R.string.config_dreamsDefaultComponent);
+ loadStringSetting(stmt, Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
+ com.android.internal.R.string.config_dreamsDefaultComponent);
db.setTransactionSuccessful();
} finally {
@@ -2027,15 +2027,15 @@
}
loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ENABLED,
- R.bool.def_screensaver_enabled);
+ com.android.internal.R.bool.config_dreamsEnabledByDefault);
loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
- R.bool.def_screensaver_activate_on_dock);
+ com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
- R.bool.def_screensaver_activate_on_sleep);
+ com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault);
loadStringSetting(stmt, Settings.Secure.SCREENSAVER_COMPONENTS,
- R.string.def_screensaver_component);
+ com.android.internal.R.string.config_dreamsDefaultComponent);
loadStringSetting(stmt, Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
- R.string.def_screensaver_component);
+ com.android.internal.R.string.config_dreamsDefaultComponent);
loadBooleanSetting(stmt, Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
R.bool.def_accessibility_display_magnification_enabled);
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index f0e5a87..cfe70dc 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -63,7 +63,6 @@
<uses-permission android:name="android.permission.WRITE_DREAM_STATE" />
<application
- android:name="com.android.systemui.SystemUIApplication"
android:persistent="true"
android:allowClearUserData="false"
android:allowBackup="false"
@@ -109,7 +108,7 @@
<activity android:name=".recent.RecentsActivity"
android:label="@string/accessibility_desc_recent_apps"
- android:theme="@android:style/Theme.Holo.Wallpaper.NoTitleBar"
+ android:theme="@style/RecentsStyle"
android:excludeFromRecents="true"
android:launchMode="singleInstance"
android:exported="true">
@@ -118,6 +117,15 @@
</intent-filter>
</activity>
+ <receiver
+ android:name=".recent.RecentsPreloadReceiver"
+ android:exported="false">
+ <intent-filter>
+ <action android:name="com.android.systemui.recent.action.PRELOAD" />
+ <action android:name="com.android.systemui.recent.action.CANCEL_PRELOAD" />
+ </intent-filter>
+ </receiver>
+
<!-- started from UsbDeviceSettingsManager -->
<activity android:name=".usb.UsbConfirmActivity"
android:exported="true"
diff --git a/packages/SystemUI/res/anim/recents_launch_from_launcher_enter.xml b/packages/SystemUI/res/anim/recents_launch_from_launcher_enter.xml
index 73ae9f2..1135bc0 100644
--- a/packages/SystemUI/res/anim/recents_launch_from_launcher_enter.xml
+++ b/packages/SystemUI/res/anim/recents_launch_from_launcher_enter.xml
@@ -18,7 +18,6 @@
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:detachWallpaper="true"
android:shareInterpolator="false"
android:zAdjustment="normal">
<!--scale android:fromXScale="2.0" android:toXScale="1.0"
@@ -28,9 +27,4 @@
android:fillBefore="true" android:fillAfter="true"
android:pivotX="50%p" android:pivotY="50%p"
android:duration="250" /-->
- <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
- android:fillEnabled="true"
- android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@android:interpolator/decelerate_cubic"
- android:duration="250"/>
</set>
diff --git a/packages/SystemUI/res/anim/recents_launch_from_launcher_exit.xml b/packages/SystemUI/res/anim/recents_launch_from_launcher_exit.xml
index becc9d0..fa28cf4 100644
--- a/packages/SystemUI/res/anim/recents_launch_from_launcher_exit.xml
+++ b/packages/SystemUI/res/anim/recents_launch_from_launcher_exit.xml
@@ -19,7 +19,7 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false"
- android:zAdjustment="normal">
+ android:zAdjustment="top">
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
diff --git a/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_enter.xml b/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_enter.xml
new file mode 100644
index 0000000..121daae
--- /dev/null
+++ b/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_enter.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false"
+ android:zAdjustment="normal">
+ <!--scale android:fromXScale="2.0" android:toXScale="1.0"
+ android:fromYScale="2.0" android:toYScale="1.0"
+ android:interpolator="@android:interpolator/decelerate_cubic"
+ android:fillEnabled="true"
+ android:fillBefore="true" android:fillAfter="true"
+ android:pivotX="50%p" android:pivotY="50%p"
+ android:duration="250" /-->
+ <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+ android:fillEnabled="true"
+ android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/decelerate_cubic"
+ android:duration="250"/>
+</set>
diff --git a/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_exit.xml b/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_exit.xml
new file mode 100644
index 0000000..fa28cf4
--- /dev/null
+++ b/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_exit.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false"
+ android:zAdjustment="top">
+ <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+ android:fillEnabled="true"
+ android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/decelerate_cubic"
+ android:duration="250"/>
+</set>
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notifications.png b/packages/SystemUI/res/drawable-hdpi/ic_notifications.png
deleted file mode 100644
index 612ab72..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_notifications.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notifications2.png b/packages/SystemUI/res/drawable-hdpi/ic_notifications2.png
deleted file mode 100644
index 315c488..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_notifications2.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notifications_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notifications_normal.png
new file mode 100644
index 0000000..62afe76
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notifications_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_normal.png
index a54761f..ead184d 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_normal.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_pressed.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_pressed.png
index f3f336c..203e232 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_pressed.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png
new file mode 100644
index 0000000..2adafea
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_open_pressed.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_open_pressed.png
new file mode 100644
index 0000000..8521ffc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_open_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png
index 172fd55..4436359 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_pressed.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_pressed.png
index 5318a6e..c86710d 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_pressed.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notifications.png b/packages/SystemUI/res/drawable-mdpi/ic_notifications.png
deleted file mode 100644
index 612ab72..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_notifications.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notifications2.png b/packages/SystemUI/res/drawable-mdpi/ic_notifications2.png
deleted file mode 100644
index 1d07cbf..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_notifications2.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notifications_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notifications_normal.png
new file mode 100644
index 0000000..62afe76
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notifications_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_normal.png
index b44b527..5dacccb 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_normal.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_pressed.png
index 94c8165..f1f6b00 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png
new file mode 100644
index 0000000..2ab0cd7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_open_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_open_pressed.png
new file mode 100644
index 0000000..49ac94b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_open_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png
index 6104424..09d2c55 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_pressed.png
index 625da59..322d1a7 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notifications.png b/packages/SystemUI/res/drawable-xhdpi/ic_notifications.png
deleted file mode 100644
index 28a902c..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notifications.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notifications2.png b/packages/SystemUI/res/drawable-xhdpi/ic_notifications2.png
deleted file mode 100644
index b02e7a1..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notifications2.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notifications_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notifications_normal.png
new file mode 100644
index 0000000..983302c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notifications_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_normal.png
index 870beb4..c882e9a 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_normal.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_pressed.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_pressed.png
index 94a4646..992b50d 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_pressed.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png
new file mode 100644
index 0000000..b0e35a1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_pressed.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_pressed.png
new file mode 100644
index 0000000..42bbbbc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png
index 477c067..2d445279 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_pressed.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_pressed.png
index 6e5c4af..ddf2c7a 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_pressed.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_notifications.xml b/packages/SystemUI/res/drawable/ic_notifications.xml
index 2c8012e..68c4774 100644
--- a/packages/SystemUI/res/drawable/ic_notifications.xml
+++ b/packages/SystemUI/res/drawable/ic_notifications.xml
@@ -16,8 +16,8 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
- android:drawable="@drawable/ic_notifications" />
+ android:drawable="@drawable/ic_notifications_normal" />
<item
- android:drawable="@drawable/ic_notifications" />
+ android:drawable="@drawable/ic_notifications_normal" />
</selector>
diff --git a/packages/SystemUI/res/drawable/ic_notify_quicksettings.xml b/packages/SystemUI/res/drawable/ic_notify_quicksettings.xml
index d8ea524..7cf3175 100644
--- a/packages/SystemUI/res/drawable/ic_notify_quicksettings.xml
+++ b/packages/SystemUI/res/drawable/ic_notify_quicksettings.xml
@@ -16,7 +16,7 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
- android:drawable="@drawable/ic_notify_quicksettings_pressed" />
+ android:drawable="@drawable/ic_notify_quicksettings_normal" />
<item
android:drawable="@drawable/ic_notify_quicksettings_normal" />
</selector>
diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
index fbbd7e5..afa4cfc 100644
--- a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
@@ -141,6 +141,16 @@
/>
</LinearLayout>
+ <ImageView
+ android:layout_width="128dp"
+ android:id="@+id/search_light"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/ic_sysbar_lights_out_dot_large"
+ android:scaleType="center"
+ android:visibility="gone"
+ />
+
<com.android.systemui.statusbar.policy.DeadZone
android:id="@+id/deadzone"
android:layout_height="match_parent"
@@ -272,6 +282,16 @@
/>
</LinearLayout>
+ <ImageView
+ android:layout_width="162dp"
+ android:id="@+id/search_light"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/ic_sysbar_lights_out_dot_large"
+ android:scaleType="center"
+ android:visibility="gone"
+ />
+
<com.android.systemui.statusbar.policy.DeadZone
android:id="@+id/deadzone"
android:layout_height="match_parent"
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index 33b5dbb..133f79d 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -145,6 +145,16 @@
/>
</LinearLayout>
+ <ImageView
+ android:layout_width="80dp"
+ android:id="@+id/search_light"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/ic_sysbar_lights_out_dot_large"
+ android:scaleType="center"
+ android:visibility="gone"
+ />
+
<com.android.systemui.statusbar.policy.DeadZone
android:id="@+id/deadzone"
android:layout_height="match_parent"
@@ -279,6 +289,16 @@
/>
</LinearLayout>
+ <ImageView
+ android:id="@+id/search_light"
+ android:layout_height="80dp"
+ android:layout_width="match_parent"
+ android:layout_gravity="center_vertical"
+ android:src="@drawable/ic_sysbar_lights_out_dot_large"
+ android:scaleType="center"
+ android:visibility="gone"
+ />
+
<com.android.systemui.statusbar.policy.DeadZone
android:id="@+id/deadzone"
android:layout_height="match_parent"
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
index 5a5769b..f7b1d78 100644
--- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
@@ -21,6 +21,8 @@
<ImageView
android:id="@+id/brightness_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingRight="10dp"
android:src="@drawable/ic_qs_brightness_auto_off"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 5408f76..b71025e 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -63,7 +63,7 @@
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Network.EmergencyOnly"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:paddingBottom="4dp"
+ android:padding="4dp"
android:gravity="center"
android:visibility="gone"
/>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index c13405a..556210e 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -20,37 +20,40 @@
xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
android:id="@+id/header"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="@dimen/notification_panel_header_height"
android:background="@drawable/notification_header_bg"
android:orientation="horizontal"
android:gravity="center_vertical"
android:baselineAligned="false"
>
- <LinearLayout
+ <RelativeLayout
+ android:id="@+id/datetime"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
+ android:layout_height="match_parent"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:background="@drawable/ic_notify_button_bg"
+ android:enabled="false"
>
<com.android.systemui.statusbar.policy.Clock
android:id="@+id/clock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
- android:gravity="bottom"
+ android:layout_centerVertical="true"
/>
<com.android.systemui.statusbar.policy.DateView android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginLeft="8dp"
- android:layout_marginRight="8dp"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
- android:gravity="bottom"
+ android:layout_toRightOf="@id/clock"
+ android:layout_alignBaseline="@id/clock"
/>
- </LinearLayout>
+ </RelativeLayout>
<Space
android:layout_width="0dp"
@@ -74,16 +77,16 @@
<ImageView android:id="@+id/clear_all_button"
android:layout_width="50dp"
android:layout_height="50dp"
- android:layout_marginRight="12dp"
android:scaleType="center"
android:src="@drawable/ic_notify_clear"
android:background="@drawable/ic_notify_button_bg"
android:contentDescription="@string/accessibility_clear_all"
/>
- <FrameLayout
+ <FrameLayout android:id="@+id/settings_button_holder"
android:layout_width="50dp"
android:layout_height="50dp"
+ android:layout_marginLeft="12dp"
>
<ImageView android:id="@+id/settings_button"
android:layout_width="50dp"
@@ -91,7 +94,7 @@
android:scaleType="center"
android:src="@drawable/ic_notify_settings"
android:background="@drawable/ic_notify_button_bg"
- android:contentDescription="@string/accessibility_settings_button"
+ android:contentDescription="@string/accessibility_desc_quick_settings"
/>
<ImageView android:id="@+id/notification_button"
android:layout_width="50dp"
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 07aca6c..2b56618 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -36,7 +36,6 @@
android:id="@+id/panel_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_marginTop="@*android:dimen/status_bar_height"
>
<include layout="@layout/status_bar_expanded"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml b/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml
index 2d1bda4..59544f4 100644
--- a/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml
+++ b/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml
@@ -170,7 +170,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_sysbar_quicksettings"
- android:contentDescription="@string/accessibility_settings_button"
+ android:contentDescription="@string/accessibility_desc_quick_settings"
/>
<ImageView
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index f7f963e..da78d29 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"تم تجاهل الإشعار."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"مركز الإشعارات."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"الإعدادات السريعة."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"التطبيقات الحديثة"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"المستخدم <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"الجوال <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 4b8aad2..79bc53a 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -149,8 +149,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Апавяшчэнне прапушчана."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Цень апавяшчэння.."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Хуткія налады."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Апошнія прыкладанні."</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Карыстальнік: <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Мабiльны сiгнал: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index c05fc59..59ba693 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Известието е отхвърлено."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Падащ панел с известия."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Бързи настройки."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Скорошни приложения."</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Потребител: <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Мобилно устройство: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 72fe18e..5e632fa 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -149,8 +149,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Oznámení je zavřeno."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Panel oznámení."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Rychlé nastavení."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Naposledy použité aplikace"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Uživatel <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobil: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 2575d2c..3e767a0 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -149,8 +149,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Benachrichtigung geschlossen"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Benachrichtigungsleiste"</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Schnelleinstellungen"</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Kürzlich geöffnete Apps"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Nutzer: <xliff:g id="USER">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>, <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobilfunkverbindung: <xliff:g id="SIGNAL">%1$s</xliff:g>, <xliff:g id="TYPE">%2$s</xliff:g>, <xliff:g id="NETWORK">%3$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 1460996..9bbd5d7 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -149,8 +149,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificación ignorada"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Pantalla de notificaciones"</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Configuración rápida"</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Aplicaciones recientes"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Usuario <xliff:g id="USER">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Móvil <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index d984bf8..6accc9f 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"اعلان ردشد."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"مجموعه اعلان."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"تنظیمات سریع."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"برنامههای اخیر"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"کاربر <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"تلفن همراه <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 9d28900..3bc0371 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Ilmoitus hylätty."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Ilmoitusalue."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Pika-asetukset."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Viimeaikaiset sovellukset"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Käyttäjä: <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobiiliverkkoyhteys: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index ab98d24..02eb529 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -149,8 +149,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification masquée"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Volet des notifications"</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Paramètres rapides"</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Applications récentes"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Utilisateur <xliff:g id="USER">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>, <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Signal mobile : <xliff:g id="SIGNAL">%1$s</xliff:g>, <xliff:g id="TYPE">%2$s</xliff:g>, <xliff:g id="NETWORK">%3$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 718d267..e2bc2c3 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"सूचना खारिज की गई."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"सूचना शेड."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"त्वरित सेटिंग."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"हाल ही के एप्लिकेशन."</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"उपयोगकर्ता <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"मोबाइल <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index bd19a44..e318120 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obavijest je odbačena."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Zaslon obavijesti."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Brze postavke."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Nedavne aplikacije."</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Korisnik <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobitel <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 96bb897..3dafd2b 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Értesítés elvetve."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Értesítési felület."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Gyorsbeállítások."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Legutóbbi alkalmazások"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Felhasználó: <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobil <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index dce8076..c26cdce 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pemberitahuan disingkirkan."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bayangan pemberitahuan."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Setelan cepat."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Aplikasi terkini."</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Pengguna <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Seluler <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index a1e7aba..0481d63 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"הודעה נדחתה."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"תריס התראות."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"הגדרות מהירות."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"יישומים אחרונים"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"משתמש <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"נייד <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 23babd0..1b89e13 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -149,8 +149,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"通知が削除されました。"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"通知シェード"</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"クイック設定"</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"最近使ったアプリです。"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"ユーザー: <xliff:g id="USER">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>、<xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"モバイル: <xliff:g id="SIGNAL">%1$s</xliff:g>、<xliff:g id="TYPE">%2$s</xliff:g>、<xliff:g id="NETWORK">%3$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index f01d7eb..71d305f 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"알림이 제거되었습니다."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"알림 세부정보"</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"빠른 설정"</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"최근 앱"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"사용자 <xliff:g id="USER">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"모바일 <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index a70c12e..01751b0 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pemberitahuan diketepikan."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bidai pemberitahuan."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Tetapan pantas."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Apl terbaru."</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Pengguna <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mudah Alih <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index d3df443..98f13c7 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Zamknięto powiadomienie."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Obszar powiadomień."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Szybkie ustawienia."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Ostatnii używane aplikacje."</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Użytkownik: <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Sieć komórkowa: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index a4a871e..9eeb01b 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -149,8 +149,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificação dispensada."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Aba de notificações."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Configurações rápidas."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Aplicativos recentes."</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Usuário <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Celular <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index a73ad1a..616ddb7 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificarea a fost închisă."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Fereastră pentru notificări."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Setări rapide."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Aplicaţii recente"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Utilizatorul <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Semnal mobil: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index a04d732..6e10de4 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -149,8 +149,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Уведомление закрыто"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Панель уведомлений"</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Быстрые настройки"</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Недавние приложения"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Пользователь <xliff:g id="USER">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="NETWORK">%2$s</xliff:g>: <xliff:g id="SIGNAL">%1$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Мобильная сеть: <xliff:g id="NETWORK">%3$s</xliff:g> (<xliff:g id="TYPE">%2$s</xliff:g>, <xliff:g id="SIGNAL">%1$s</xliff:g>)"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 6d126b1..9151512 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -149,8 +149,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Upozornenie bolo zrušené."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Panel upozornení."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Rýchle nastavenia."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Nedávne aplikácie"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Používateľ: <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobil: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 2d4006b..7be851c 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obvestilo je bilo odstranjeno."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Zaslon z obvestili."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Hitre nastavitve."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Nedavne aplikacije."</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Uporabnik: <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobilni telefon: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index fce2c57..9d9da87 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Обавештење је одбачено."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Прозор са обавештењима."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Брза подешавања."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Недавне апликације."</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Корисник: <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Мобилна мрежа: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 16b8316..bae649d 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Meddelandet ignorerades."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Meddelandepanel."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Snabbinställningar."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Senaste apparna"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Användare <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobil <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index df6ed19..fc80f5c 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -47,4 +47,8 @@
<!-- Minimum fraction of the screen that should be taken up by the notification panel. -->
<item type="dimen" name="notification_panel_min_height_frac">40%</item>
+
+ <!-- How far to slide the panel out when you touch it -->
+ <!-- On tablets this is just the close_handle_height -->
+ <dimen name="peek_height">@dimen/close_handle_height</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 646225d..668504e 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"ปิดการแจ้งเตือนแล้ว"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"หน้าต่างแจ้งเตือน"</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"การตั้งค่าด่วน"</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"แอปพลิเคชันล่าสุด"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"ผู้ใช้ <xliff:g id="USER">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g> <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"มือถือ <xliff:g id="SIGNAL">%1$s</xliff:g> <xliff:g id="TYPE">%2$s</xliff:g> <xliff:g id="NETWORK">%3$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 7baad61..312d8fd 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Na-dismiss ang notification."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Notification shade."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Mga mabilisang setting."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Kamakailang apps."</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"User na si <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobile <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index c6ba738..5012bc5 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Bildirim kapatıldı."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bildirim gölgesi."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Hızlı ayarlar."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Son uygulamalar."</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Kullanıcı: <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobil <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 26ae34b..ba36be6 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Сповіщення відхилено."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Панель сповіщень."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Швидке налаштування."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Нещодавні програми."</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Користувач <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>, <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Мобільне передавання даних: <xliff:g id="SIGNAL">%1$s</xliff:g>, <xliff:g id="TYPE">%2$s</xliff:g>, <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 468375f..ce90afc 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -147,8 +147,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Đã loại bỏ thông báo."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bóng thông báo."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Cài đặt nhanh."</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Ứng dụng gần đây."</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Người dùng <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Di động <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 4cfb7d0..ba0d9c8 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -149,8 +149,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"已关闭通知。"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"通知栏。"</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"快速设置。"</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"最近使用的应用。"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"用户:<xliff:g id="USER">%s</xliff:g>。"</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>,<xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"移动数据连接:<xliff:g id="SIGNAL">%1$s</xliff:g>,<xliff:g id="TYPE">%2$s</xliff:g>,<xliff:g id="NETWORK">%3$s</xliff:g>。"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index d0323f0..a77dd8c 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -149,8 +149,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"已關閉通知。"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"通知欄。"</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"快速設定。"</string>
- <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"最近使用的應用程式。"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"使用者:<xliff:g id="USER">%s</xliff:g>。"</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>,<xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"行動數據連線:<xliff:g id="SIGNAL">%1$s</xliff:g>,<xliff:g id="TYPE">%2$s</xliff:g>,<xliff:g id="NETWORK">%3$s</xliff:g>。"</string>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 4de0891..ed08115 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -201,4 +201,8 @@
<!-- The size of the gesture span needed to activate the "pull" notification expansion -->
<dimen name="pull_span_min">25dp</dimen>
+
+ <!-- How far to slide the panel out when you touch it -->
+ <!-- For phones, this is close_handle_height + header_height -->
+ <dimen name="peek_height">84dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 18c1c34..1a59d6c 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -16,6 +16,24 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <style name="RecentsStyle" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
+ <item name="android:windowAnimationStyle">@style/Animation.RecentsActivity</item>
+ </style>
+
+ <!-- Animations for a non-full-screen window or activity. -->
+ <style name="Animation.RecentsActivity" parent="@android:style/Animation.Activity">
+ <item name="android:activityOpenEnterAnimation">@anim/recents_launch_from_launcher_enter</item>
+ <item name="android:activityOpenExitAnimation">@anim/recents_launch_from_launcher_exit</item>
+ <item name="android:taskOpenEnterAnimation">@anim/recents_launch_from_launcher_enter</item>
+ <item name="android:taskOpenExitAnimation">@anim/recents_launch_from_launcher_exit</item>
+ <item name="android:taskToFrontEnterAnimation">@anim/recents_launch_from_launcher_enter</item>
+ <item name="android:taskToFrontExitAnimation">@anim/recents_launch_from_launcher_exit</item>
+ <item name="android:wallpaperOpenEnterAnimation">@anim/recents_launch_from_launcher_enter</item>
+ <item name="android:wallpaperOpenExitAnimation">@anim/recents_launch_from_launcher_exit</item>
+ <item name="android:wallpaperIntraOpenEnterAnimation">@anim/wallpaper_recents_launch_from_launcher_enter</item>
+ <item name="android:wallpaperIntraOpenExitAnimation">@anim/wallpaper_recents_launch_from_launcher_exit</item>
+ </style>
+
<style name="TextAppearance.StatusBar.IntruderAlert"
parent="@*android:style/TextAppearance.StatusBar">
</style>
diff --git a/packages/SystemUI/src/com/android/systemui/BootReceiver.java b/packages/SystemUI/src/com/android/systemui/BootReceiver.java
index de005aa..d3ce30d 100644
--- a/packages/SystemUI/src/com/android/systemui/BootReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/BootReceiver.java
@@ -35,7 +35,7 @@
try {
// Start the load average overlay, if activated
ContentResolver res = context.getContentResolver();
- if (Settings.System.getInt(res, Settings.System.SHOW_PROCESSES, 0) != 0) {
+ if (Settings.Global.getInt(res, Settings.Global.SHOW_PROCESSES, 0) != 0) {
Intent loadavg = new Intent(context, com.android.systemui.LoadAverageService.class);
context.startService(loadavg);
}
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 0958f70..0a7dd7c 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -109,7 +109,7 @@
private WallpaperObserver mReceiver;
Bitmap mBackground;
- int mBackgroundWidth = -1, mBackgroundHeight = -1;
+ int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;
int mLastRotation = -1;
float mXOffset;
float mYOffset;
@@ -156,7 +156,7 @@
}
synchronized (mLock) {
- mBackgroundWidth = mBackgroundHeight = -1;
+ mLastSurfaceWidth = mLastSurfaceHeight = -1;
mBackground = null;
mRedrawNeeded = true;
drawFrameLocked();
@@ -172,6 +172,9 @@
public void trimMemory(int level) {
if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW &&
mBackground != null && mIsHwAccelerated) {
+ if (DEBUG) {
+ Log.d(TAG, "trimMemory");
+ }
mBackground.recycle();
mBackground = null;
mWallpaperManager.forgetLoadedWallpaper();
@@ -286,13 +289,13 @@
@Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
super.onSurfaceDestroyed(holder);
- mBackgroundWidth = mBackgroundHeight = -1;
+ mLastSurfaceWidth = mLastSurfaceHeight = -1;
}
@Override
public void onSurfaceCreated(SurfaceHolder holder) {
super.onSurfaceCreated(holder);
- mBackgroundWidth = mBackgroundHeight = -1;
+ mLastSurfaceWidth = mLastSurfaceHeight = -1;
}
@Override
@@ -314,9 +317,9 @@
final int dh = frame.height();
int newRotation = ((WindowManager) getSystemService(WINDOW_SERVICE)).
getDefaultDisplay().getRotation();
+ boolean surfaceDimensionsChanged = dw != mLastSurfaceWidth || dh != mLastSurfaceHeight;
- boolean redrawNeeded = dw != mBackgroundWidth || dh != mBackgroundHeight ||
- newRotation != mLastRotation;
+ boolean redrawNeeded = surfaceDimensionsChanged || newRotation != mLastRotation;
if (!redrawNeeded && !mOffsetsChanged) {
if (DEBUG) {
Log.d(TAG, "Suppressed drawFrame since redraw is not needed "
@@ -327,21 +330,41 @@
mLastRotation = newRotation;
// Load bitmap if it is not yet loaded or if it was loaded at a different size
- if (mBackground == null || dw != mBackgroundWidth || dw != mBackgroundHeight) {
+ if (mBackground == null || surfaceDimensionsChanged) {
if (DEBUG) {
- Log.d(TAG, "Reloading bitmap");
+ Log.d(TAG, "Reloading bitmap: mBackground, bgw, bgh, dw, dh = " +
+ mBackground + ", " +
+ ((mBackground == null) ? 0 : mBackground.getWidth()) + ", " +
+ ((mBackground == null) ? 0 : mBackground.getHeight()) + ", " +
+ dw + ", " + dh);
}
- mWallpaperManager.forgetLoadedWallpaper();
updateWallpaperLocked();
+ if (mBackground == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Unable to load bitmap");
+ }
+ return;
+ }
+ if (DEBUG) {
+ if (dw != mBackground.getWidth() || dh != mBackground.getHeight()) {
+ Log.d(TAG, "Surface != bitmap dimensions: surface w/h, bitmap w/h: " +
+ dw + ", " + dh + ", " + mBackground.getWidth() + ", " +
+ mBackground.getHeight());
+ }
+ }
}
- final int availw = dw - mBackgroundWidth;
- final int availh = dh - mBackgroundHeight;
+ final int availw = dw - mBackground.getWidth();
+ final int availh = dh - mBackground.getHeight();
int xPixels = availw < 0 ? (int)(availw * mXOffset + .5f) : (availw / 2);
int yPixels = availh < 0 ? (int)(availh * mYOffset + .5f) : (availh / 2);
mOffsetsChanged = false;
mRedrawNeeded = false;
+ if (surfaceDimensionsChanged) {
+ mLastSurfaceWidth = dw;
+ mLastSurfaceHeight = dh;
+ }
mLastXTranslation = xPixels;
mLastYTranslation = yPixels;
if (!redrawNeeded && xPixels == mLastXTranslation && yPixels == mLastYTranslation) {
@@ -374,9 +397,10 @@
}
- void updateWallpaperLocked() {
+ private void updateWallpaperLocked() {
Throwable exception = null;
try {
+ mWallpaperManager.forgetLoadedWallpaper(); // force reload
mBackground = mWallpaperManager.getBitmap();
} catch (RuntimeException e) {
exception = e;
@@ -397,9 +421,6 @@
Log.w(TAG, "Unable reset to default wallpaper!", ex);
}
}
-
- mBackgroundWidth = mBackground != null ? mBackground.getWidth() : 0;
- mBackgroundHeight = mBackground != null ? mBackground.getHeight() : 0;
}
private void drawWallpaperWithCanvas(SurfaceHolder sh, int w, int h, int x, int y) {
@@ -413,7 +434,8 @@
c.translate(x, y);
if (w < 0 || h < 0) {
c.save(Canvas.CLIP_SAVE_FLAG);
- c.clipRect(0, 0, mBackgroundWidth, mBackgroundHeight, Op.DIFFERENCE);
+ c.clipRect(0, 0, mBackground.getWidth(), mBackground.getHeight(),
+ Op.DIFFERENCE);
c.drawColor(0xff000000);
c.restore();
}
@@ -429,8 +451,8 @@
private boolean drawWallpaperWithOpenGL(SurfaceHolder sh, int w, int h, int left, int top) {
if (!initGL(sh)) return false;
- final float right = left + mBackgroundWidth;
- final float bottom = top + mBackgroundHeight;
+ final float right = left + mBackground.getWidth();
+ final float bottom = top + mBackground.getHeight();
final Rect frame = sh.getSurfaceFrame();
final Matrix4f ortho = new Matrix4f();
diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
index bc61ab0..4b0e818 100644
--- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
@@ -17,6 +17,7 @@
package com.android.systemui;
import android.animation.LayoutTransition;
+import android.app.ActivityManagerNative;
import android.app.ActivityOptions;
import android.app.SearchManager;
import android.content.ActivityNotFoundException;
@@ -24,6 +25,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.os.Vibrator;
import android.provider.Settings;
@@ -71,12 +73,21 @@
}
private void startAssistActivity() {
+ if (!mBar.isDeviceProvisioned()) return;
+
// Close Recent Apps if needed
mBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL);
// Launch Assist
Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
.getAssistIntent(mContext, UserHandle.USER_CURRENT);
if (intent == null) return;
+
+ // Dismiss the keyguard if possible. XXX: TODO: invoke bouncer.
+ try {
+ ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
+ } catch (RemoteException e) {
+ }
+
try {
ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
R.anim.search_launch_enter, R.anim.search_launch_exit,
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
deleted file mode 100644
index c120690..0000000
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui;
-
-import android.app.Application;
-
-import com.android.systemui.recent.RecentTasksLoader;
-import com.android.systemui.recent.RecentsActivity;
-
-public class SystemUIApplication extends Application {
- private RecentTasksLoader mRecentTasksLoader;
- private boolean mWaitingForWinAnimStart;
- private RecentsActivity.WindowAnimationStartListener mWinAnimStartListener;
-
- public RecentTasksLoader getRecentTasksLoader() {
- if (mRecentTasksLoader == null) {
- mRecentTasksLoader = new RecentTasksLoader(this);
- }
- return mRecentTasksLoader;
- }
-
- public void setWaitingForWinAnimStart(boolean waiting) {
- mWaitingForWinAnimStart = waiting;
- }
-
- public void setWindowAnimationStartListener(
- RecentsActivity.WindowAnimationStartListener startListener) {
- mWinAnimStartListener = startListener;
- }
-
- public RecentsActivity.WindowAnimationStartListener getWindowAnimationListener() {
- return mWinAnimStartListener;
- }
-
- public void onWindowAnimationStart() {
- if (mWinAnimStartListener != null) {
- mWinAnimStartListener.onWindowAnimationStart();
- }
- mWaitingForWinAnimStart = false;
- }
-
- public boolean isWaitingForWindowAnimationStart() {
- return mWaitingForWinAnimStart;
- }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 07fd0ab..318448e 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -237,9 +237,9 @@
}
final ContentResolver cr = mContext.getContentResolver();
- if (Settings.System.getInt(cr, Settings.System.POWER_SOUNDS_ENABLED, 1) == 1) {
- final String soundPath = Settings.System.getString(cr,
- Settings.System.LOW_BATTERY_SOUND);
+ if (Settings.Global.getInt(cr, Settings.Global.POWER_SOUNDS_ENABLED, 1) == 1) {
+ final String soundPath = Settings.Global.getString(cr,
+ Settings.Global.LOW_BATTERY_SOUND);
if (soundPath != null) {
final Uri soundUri = Uri.parse("file://" + soundPath);
if (soundUri != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
index 7260844..4338fa0 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -30,6 +30,7 @@
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Process;
+import android.os.UserHandle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
@@ -52,6 +53,8 @@
private Context mContext;
private RecentsPanelView mRecentsPanel;
+
+ private Object mFirstTaskLock = new Object();
private TaskDescription mFirstTask;
private boolean mFirstTaskLoaded;
@@ -70,23 +73,16 @@
private enum State { LOADING, LOADED, CANCELLED };
private State mState = State.CANCELLED;
- public TaskDescription getFirstTask() {
- while (!mFirstTaskLoaded) {
- if (mState == State.CANCELLED) {
- loadTasksInBackground();
- }
- try {
- if (mState == State.LOADED) {
- break;
- }
- Thread.sleep(5);
- } catch (InterruptedException e) {
- }
+
+ private static RecentTasksLoader sInstance;
+ public static RecentTasksLoader getInstance(Context context) {
+ if (sInstance == null) {
+ sInstance = new RecentTasksLoader(context);
}
- return mFirstTask;
+ return sInstance;
}
- public RecentTasksLoader(Context context) {
+ private RecentTasksLoader(Context context) {
mContext = context;
mHandler = new Handler();
@@ -295,8 +291,6 @@
mThumbnailLoader = null;
}
mLoadedTasks = null;
- mFirstTask = null;
- mFirstTaskLoaded = false;
if (mRecentsPanel != null) {
mRecentsPanel.onTaskLoadingCancelled();
}
@@ -304,6 +298,102 @@
mState = State.CANCELLED;
}
+ private void clearFirstTask() {
+ synchronized (mFirstTaskLock) {
+ mFirstTask = null;
+ mFirstTaskLoaded = false;
+ }
+ }
+
+ public void preloadFirstTask() {
+ Thread bgLoad = new Thread() {
+ public void run() {
+ TaskDescription first = loadFirstTask();
+ synchronized(mFirstTaskLock) {
+ if (mCancelPreloadingFirstTask) {
+ clearFirstTask();
+ } else {
+ mFirstTask = first;
+ mFirstTaskLoaded = true;
+ }
+ mPreloadingFirstTask = false;
+ }
+ }
+ };
+ synchronized(mFirstTaskLock) {
+ if (!mPreloadingFirstTask) {
+ clearFirstTask();
+ mPreloadingFirstTask = true;
+ bgLoad.start();
+ }
+ }
+ }
+
+ public void cancelPreloadingFirstTask() {
+ synchronized(mFirstTaskLock) {
+ if (mPreloadingFirstTask) {
+ mCancelPreloadingFirstTask = true;
+ } else {
+ clearFirstTask();
+ }
+ }
+ }
+
+ boolean mPreloadingFirstTask;
+ boolean mCancelPreloadingFirstTask;
+ public TaskDescription getFirstTask() {
+ while(true) {
+ synchronized(mFirstTaskLock) {
+ if (mFirstTaskLoaded) {
+ return mFirstTask;
+ } else if (!mFirstTaskLoaded && !mPreloadingFirstTask) {
+ mFirstTask = loadFirstTask();
+ mFirstTaskLoaded = true;
+ return mFirstTask;
+ }
+ }
+ try {
+ Thread.sleep(3);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ public TaskDescription loadFirstTask() {
+ final ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+
+ final List<ActivityManager.RecentTaskInfo> recentTasks = am.getRecentTasksForUser(
+ 1, ActivityManager.RECENT_IGNORE_UNAVAILABLE, UserHandle.CURRENT.getIdentifier());
+ TaskDescription item = null;
+ if (recentTasks.size() > 0) {
+ ActivityManager.RecentTaskInfo recentInfo = recentTasks.get(0);
+
+ Intent intent = new Intent(recentInfo.baseIntent);
+ if (recentInfo.origActivity != null) {
+ intent.setComponent(recentInfo.origActivity);
+ }
+
+ // Don't load the current home activity.
+ if (isCurrentHomeActivity(intent.getComponent(), null)) {
+ return null;
+ }
+
+ // Don't load ourselves
+ if (intent.getComponent().getPackageName().equals(mContext.getPackageName())) {
+ return null;
+ }
+
+ item = createTaskDescription(recentInfo.id,
+ recentInfo.persistentId, recentInfo.baseIntent,
+ recentInfo.origActivity, recentInfo.description);
+ if (item != null) {
+ loadThumbnailAndIcon(item);
+ }
+ return item;
+ }
+ return null;
+ }
+
public void loadTasksInBackground() {
loadTasksInBackground(false);
}
@@ -367,9 +457,6 @@
// Don't load the current home activity.
if (isCurrentHomeActivity(intent.getComponent(), homeInfo)) {
- if (index == 0) {
- mFirstTaskLoaded = true;
- }
continue;
}
@@ -466,10 +553,6 @@
}
loadThumbnailAndIcon(td);
- if (!mFirstTaskLoaded) {
- mFirstTask = td;
- mFirstTaskLoaded = true;
- }
publishProgress(td);
}
@@ -477,8 +560,6 @@
return null;
}
};
- mFirstTask = null;
- mFirstTaskLoaded = false;
mThumbnailLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java
index ef9f36e..676326a 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java
@@ -30,14 +30,18 @@
import android.view.WindowManager;
import com.android.systemui.R;
-import com.android.systemui.SystemUIApplication;
import com.android.systemui.statusbar.tablet.StatusBarPanel;
import java.util.List;
public class RecentsActivity extends Activity {
- public static final String TOGGLE_RECENTS_INTENT = "com.android.systemui.TOGGLE_RECENTS";
- public static final String CLOSE_RECENTS_INTENT = "com.android.systemui.CLOSE_RECENTS";
+ public static final String TOGGLE_RECENTS_INTENT = "com.android.systemui.recent.action.TOGGLE_RECENTS";
+ public static final String PRELOAD_INTENT = "com.android.systemui.recent.action.PRELOAD";
+ public static final String CANCEL_PRELOAD_INTENT = "com.android.systemui.recent.CANCEL_PRELOAD";
+ public static final String CLOSE_RECENTS_INTENT = "com.android.systemui.recent.action.CLOSE";
+ public static final String WINDOW_ANIMATION_START_INTENT = "com.android.systemui.recent.action.WINDOW_ANIMATION_START";
+ public static final String PRELOAD_PERMISSION = "com.android.systemui.recent.permission.PRELOAD";
+ public static final String WAITING_FOR_WINDOW_ANIMATION_PARAM = "com.android.systemui.recent.WAITING_FOR_WINDOW_ANIMATION";
private static final String WAS_SHOWING = "was_showing";
private RecentsPanelView mRecentsPanel;
@@ -48,19 +52,21 @@
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
- if (mShowing && !mForeground) {
- // Captures the case right before we transition to another activity
- mRecentsPanel.show(false);
+ if (CLOSE_RECENTS_INTENT.equals(intent.getAction())) {
+ if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
+ if (mShowing && !mForeground) {
+ // Captures the case right before we transition to another activity
+ mRecentsPanel.show(false);
+ }
+ }
+ } else if (WINDOW_ANIMATION_START_INTENT.equals(intent.getAction())) {
+ if (mRecentsPanel != null) {
+ mRecentsPanel.onWindowAnimationStart();
}
}
}
};
- public static interface WindowAnimationStartListener {
- void onWindowAnimationStart();
- }
-
public class TouchOutsideListener implements View.OnTouchListener {
private StatusBarPanel mPanel;
@@ -107,10 +113,14 @@
}
}
+ public static boolean forceOpaqueBackground(Context context) {
+ return WallpaperManager.getInstance(context).getWallpaperInfo() != null;
+ }
+
@Override
public void onStart() {
// Hide wallpaper if it's not a static image
- if (WallpaperManager.getInstance(this).getWallpaperInfo() != null) {
+ if (forceOpaqueBackground(this)) {
updateWallpaperVisibility(false);
} else {
updateWallpaperVisibility(true);
@@ -164,25 +174,23 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
- final SystemUIApplication app = (SystemUIApplication) getApplication();
- final RecentTasksLoader recentTasksLoader = app.getRecentTasksLoader();
-
setContentView(R.layout.status_bar_recent_panel);
mRecentsPanel = (RecentsPanelView) findViewById(R.id.recents_root);
mRecentsPanel.setOnTouchListener(new TouchOutsideListener(mRecentsPanel));
- mRecentsPanel.setRecentTasksLoader(recentTasksLoader);
+
+ final RecentTasksLoader recentTasksLoader = RecentTasksLoader.getInstance(this);
recentTasksLoader.setRecentsPanel(mRecentsPanel, mRecentsPanel);
mRecentsPanel.setMinSwipeAlpha(
getResources().getInteger(R.integer.config_recent_item_min_alpha) / 100f);
if (savedInstanceState == null ||
savedInstanceState.getBoolean(WAS_SHOWING)) {
- handleIntent(getIntent());
+ handleIntent(getIntent(), (savedInstanceState == null));
}
mIntentFilter = new IntentFilter();
mIntentFilter.addAction(CLOSE_RECENTS_INTENT);
+ mIntentFilter.addAction(WINDOW_ANIMATION_START_INTENT);
registerReceiver(mIntentReceiver, mIntentFilter);
- app.setWindowAnimationStartListener(mRecentsPanel);
super.onCreate(savedInstanceState);
}
@@ -193,20 +201,17 @@
@Override
protected void onDestroy() {
- final SystemUIApplication app = (SystemUIApplication) getApplication();
- final RecentTasksLoader recentTasksLoader = app.getRecentTasksLoader();
- recentTasksLoader.setRecentsPanel(null, mRecentsPanel);
+ RecentTasksLoader.getInstance(this).setRecentsPanel(null, mRecentsPanel);
unregisterReceiver(mIntentReceiver);
- app.setWindowAnimationStartListener(null);
super.onDestroy();
}
@Override
protected void onNewIntent(Intent intent) {
- handleIntent(intent);
+ handleIntent(intent, true);
}
- private void handleIntent(Intent intent) {
+ private void handleIntent(Intent intent, boolean checkWaitingForAnimationParam) {
super.onNewIntent(intent);
if (TOGGLE_RECENTS_INTENT.equals(intent.getAction())) {
@@ -214,10 +219,11 @@
if (mRecentsPanel.isShowing()) {
dismissAndGoBack();
} else {
- final SystemUIApplication app = (SystemUIApplication) getApplication();
- final RecentTasksLoader recentTasksLoader = app.getRecentTasksLoader();
+ final RecentTasksLoader recentTasksLoader = RecentTasksLoader.getInstance(this);
+ boolean waitingForWindowAnimation = checkWaitingForAnimationParam &&
+ intent.getBooleanExtra(WAITING_FOR_WINDOW_ANIMATION_PARAM, false);
mRecentsPanel.show(true, recentTasksLoader.getLoadedTasks(),
- recentTasksLoader.isFirstScreenful());
+ recentTasksLoader.isFirstScreenful(), waitingForWindowAnimation);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 57d2ed3..cd3bc42 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -19,7 +19,6 @@
import android.animation.Animator;
import android.animation.LayoutTransition;
import android.animation.TimeInterpolator;
-import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.ActivityOptions;
@@ -59,7 +58,6 @@
import android.widget.TextView;
import com.android.systemui.R;
-import com.android.systemui.SystemUIApplication;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.tablet.StatusBarPanel;
@@ -68,7 +66,7 @@
import java.util.ArrayList;
public class RecentsPanelView extends FrameLayout implements OnItemClickListener, RecentsCallback,
- StatusBarPanel, Animator.AnimatorListener, RecentsActivity.WindowAnimationStartListener {
+ StatusBarPanel, Animator.AnimatorListener {
static final String TAG = "RecentsPanelView";
static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false;
private PopupMenu mPopup;
@@ -81,6 +79,7 @@
private boolean mWaitingToShow;
private int mNumItemsWaitingForThumbnailsAndIcons;
private ViewHolder mItemToAnimateInWhenWindowAnimationIsFinished;
+ private boolean mWaitingForWindowAnimation;
private RecentTasksLoader mRecentTasksLoader;
private ArrayList<TaskDescription> mRecentTaskDescriptions;
@@ -147,13 +146,9 @@
(ImageView) convertView.findViewById(R.id.app_thumbnail_image);
// If we set the default thumbnail now, we avoid an onLayout when we update
// the thumbnail later (if they both have the same dimensions)
- if (mRecentTasksLoader != null) {
- updateThumbnail(holder, mRecentTasksLoader.getDefaultThumbnail(), false, false);
- }
+ updateThumbnail(holder, mRecentTasksLoader.getDefaultThumbnail(), false, false);
holder.iconView = (ImageView) convertView.findViewById(R.id.app_icon);
- if (mRecentTasksLoader != null) {
- holder.iconView.setImageBitmap(mRecentTasksLoader.getDefaultIcon());
- }
+ holder.iconView.setImageBitmap(mRecentTasksLoader.getDefaultIcon());
holder.labelView = (TextView) convertView.findViewById(R.id.app_label);
holder.calloutLine = convertView.findViewById(R.id.recents_callout_line);
holder.descriptionView = (TextView) convertView.findViewById(R.id.app_description);
@@ -182,21 +177,31 @@
mNumItemsWaitingForThumbnailsAndIcons--;
}
if (index == 0) {
- final Activity activity = (Activity) RecentsPanelView.this.getContext();
- final SystemUIApplication app = (SystemUIApplication) activity.getApplication();
- if (app.isWaitingForWindowAnimationStart()) {
+ if (mWaitingForWindowAnimation) {
+ if (mItemToAnimateInWhenWindowAnimationIsFinished != null) {
+ holder.iconView.setAlpha(1f);
+ holder.iconView.setTranslationX(0f);
+ holder.iconView.setTranslationY(0f);
+ holder.labelView.setAlpha(1f);
+ holder.labelView.setTranslationX(0f);
+ holder.labelView.setTranslationY(0f);
+ if (holder.calloutLine != null) {
+ holder.calloutLine.setAlpha(1f);
+ holder.calloutLine.setTranslationX(0f);
+ holder.calloutLine.setTranslationY(0f);
+ }
+ }
mItemToAnimateInWhenWindowAnimationIsFinished = holder;
final int translation = -getResources().getDimensionPixelSize(
R.dimen.status_bar_recents_app_icon_translate_distance);
final Configuration config = getResources().getConfiguration();
if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
- for (View v :
- new View[] { holder.iconView, holder.labelView, holder.calloutLine }) {
- if (v != null) {
- v.setAlpha(0f);
- v.setTranslationX(translation);
- }
- }
+ holder.iconView.setAlpha(0f);
+ holder.iconView.setTranslationX(translation);
+ holder.labelView.setAlpha(0f);
+ holder.labelView.setTranslationX(translation);
+ holder.calloutLine.setAlpha(0f);
+ holder.calloutLine.setTranslationX(translation);
} else {
holder.iconView.setAlpha(0f);
holder.iconView.setTranslationY(translation);
@@ -220,6 +225,17 @@
holder.thumbnailView.setTag(null);
holder.thumbnailView.setOnLongClickListener(null);
holder.thumbnailView.setVisibility(INVISIBLE);
+ holder.iconView.setAlpha(1f);
+ holder.iconView.setTranslationX(0f);
+ holder.iconView.setTranslationY(0f);
+ holder.labelView.setAlpha(1f);
+ holder.labelView.setTranslationX(0f);
+ holder.labelView.setTranslationY(0f);
+ if (holder.calloutLine != null) {
+ holder.calloutLine.setAlpha(1f);
+ holder.calloutLine.setTranslationX(0f);
+ holder.calloutLine.setTranslationY(0f);
+ }
holder.taskDescription = null;
holder.loadedThumbnailAndIcon = false;
}
@@ -237,6 +253,7 @@
defStyle, 0);
mRecentItemLayoutId = a.getResourceId(R.styleable.RecentsPanelView_recentItemLayout, 0);
+ mRecentTasksLoader = RecentTasksLoader.getInstance(context);
a.recycle();
}
@@ -270,11 +287,12 @@
}
public void show(boolean show) {
- show(show, null, false);
+ show(show, null, false, false);
}
public void show(boolean show, ArrayList<TaskDescription> recentTaskDescriptions,
- boolean firstScreenful) {
+ boolean firstScreenful, boolean waitingForWindowAnimation) {
+ mWaitingForWindowAnimation = waitingForWindowAnimation;
if (show) {
mWaitingToShow = true;
refreshRecentTasksList(recentTaskDescriptions, firstScreenful);
@@ -532,6 +550,7 @@
}
}
mItemToAnimateInWhenWindowAnimationIsFinished = null;
+ mWaitingForWindowAnimation = false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPreloadReceiver.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPreloadReceiver.java
new file mode 100644
index 0000000..eb5892007
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPreloadReceiver.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recent;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class RecentsPreloadReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (RecentsActivity.PRELOAD_INTENT.equals(intent.getAction())) {
+ RecentTasksLoader.getInstance(context).preloadRecentTasksList();
+ } else if (RecentsActivity.CANCEL_PRELOAD_INTENT.equals(intent.getAction())){
+ RecentTasksLoader.getInstance(context).cancelPreloadingRecentTasksList();
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 577b1f4..fe33b02 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -25,7 +25,6 @@
import com.android.systemui.R;
import com.android.systemui.SearchPanelView;
import com.android.systemui.SystemUI;
-import com.android.systemui.SystemUIApplication;
import com.android.systemui.recent.RecentTasksLoader;
import com.android.systemui.recent.RecentsActivity;
import com.android.systemui.recent.TaskDescription;
@@ -37,7 +36,6 @@
import android.app.ActivityOptions;
import android.app.KeyguardManager;
import android.app.PendingIntent;
-import android.app.Service;
import android.app.TaskStackBuilder;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
@@ -72,9 +70,9 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
-import android.view.WindowManagerGlobal;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupMenu;
@@ -428,10 +426,6 @@
protected abstract WindowManager.LayoutParams getSearchLayoutParams(
LayoutParams layoutParams);
- protected RecentTasksLoader getRecentTasksLoader() {
- final SystemUIApplication app = (SystemUIApplication) ((Service) mContext).getApplication();
- return app.getRecentTasksLoader();
- }
protected void updateSearchPanel() {
// Search Panel
@@ -475,8 +469,8 @@
protected void toggleRecentsActivity() {
try {
- final RecentTasksLoader recentTasksLoader = getRecentTasksLoader();
- TaskDescription firstTask = recentTasksLoader.getFirstTask();
+
+ TaskDescription firstTask = RecentTasksLoader.getInstance(mContext).getFirstTask();
Intent intent = new Intent(RecentsActivity.TOGGLE_RECENTS_INTENT);
intent.setClassName("com.android.systemui",
@@ -485,11 +479,18 @@
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
if (firstTask == null) {
- ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
- R.anim.recents_launch_from_launcher_enter,
- R.anim.recents_launch_from_launcher_exit);
- mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
- UserHandle.USER_CURRENT));
+ if (RecentsActivity.forceOpaqueBackground(mContext)) {
+ ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
+ R.anim.recents_launch_from_launcher_enter,
+ R.anim.recents_launch_from_launcher_exit);
+ mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
+ UserHandle.USER_CURRENT));
+ } else {
+ // The correct window animation will be applied via the activity's style
+ mContext.startActivityAsUser(intent, new UserHandle(
+ UserHandle.USER_CURRENT));
+ }
+
} else {
Bitmap first = firstTask.getThumbnail();
final Resources res = mContext.getResources();
@@ -576,17 +577,17 @@
+ recentsItemTopPadding + thumbBgPadding + statusBarHeight);
}
- final SystemUIApplication app =
- (SystemUIApplication) ((Service) mContext).getApplication();
- app.setWaitingForWinAnimStart(true);
ActivityOptions opts = ActivityOptions.makeThumbnailScaleDownAnimation(
getStatusBarView(),
first, x, y,
new ActivityOptions.OnAnimationStartedListener() {
public void onAnimationStarted() {
- app.onWindowAnimationStart();
+ Intent intent = new Intent(RecentsActivity.WINDOW_ANIMATION_START_INTENT);
+ intent.setPackage("com.android.systemui");
+ mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
}
});
+ intent.putExtra(RecentsActivity.WAITING_FOR_WINDOW_ANIMATION_PARAM, true);
mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
UserHandle.USER_CURRENT));
}
@@ -596,8 +597,49 @@
}
}
+ protected View.OnTouchListener mRecentsPreloadOnTouchListener = new View.OnTouchListener() {
+ // additional optimization when we have software system buttons - start loading the recent
+ // tasks on touch down
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ int action = event.getAction() & MotionEvent.ACTION_MASK;
+ if (action == MotionEvent.ACTION_DOWN) {
+ preloadRecentTasksList();
+ } else if (action == MotionEvent.ACTION_CANCEL) {
+ cancelPreloadingRecentTasksList();
+ } else if (action == MotionEvent.ACTION_UP) {
+ if (!v.isPressed()) {
+ cancelPreloadingRecentTasksList();
+ }
+
+ }
+ return false;
+ }
+ };
+
+ protected void preloadRecentTasksList() {
+ if (DEBUG) Slog.d(TAG, "preloading recents");
+ Intent intent = new Intent(RecentsActivity.PRELOAD_INTENT);
+ intent.setClassName("com.android.systemui",
+ "com.android.systemui.recent.RecentsPreloadReceiver");
+ mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+
+ RecentTasksLoader.getInstance(mContext).preloadFirstTask();
+ }
+
+ protected void cancelPreloadingRecentTasksList() {
+ if (DEBUG) Slog.d(TAG, "cancel preloading recents");
+ Intent intent = new Intent(RecentsActivity.CANCEL_PRELOAD_INTENT);
+ intent.setClassName("com.android.systemui",
+ "com.android.systemui.recent.RecentsPreloadReceiver");
+ mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+
+ RecentTasksLoader.getInstance(mContext).cancelPreloadingFirstTask();
+ }
+
protected class H extends Handler {
public void handleMessage(Message m) {
+ Intent intent;
switch (m.what) {
case MSG_TOGGLE_RECENTS_PANEL:
if (DEBUG) Slog.d(TAG, "toggle recents panel");
@@ -605,17 +647,15 @@
break;
case MSG_CLOSE_RECENTS_PANEL:
if (DEBUG) Slog.d(TAG, "closing recents panel");
- Intent intent = new Intent(RecentsActivity.CLOSE_RECENTS_INTENT);
+ intent = new Intent(RecentsActivity.CLOSE_RECENTS_INTENT);
intent.setPackage("com.android.systemui");
mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
break;
case MSG_PRELOAD_RECENT_APPS:
- if (DEBUG) Slog.d(TAG, "preloading recents");
- getRecentTasksLoader().preloadRecentTasksList();
+ preloadRecentTasksList();
break;
case MSG_CANCEL_PRELOAD_RECENT_APPS:
- if (DEBUG) Slog.d(TAG, "cancel preloading recents");
- getRecentTasksLoader().cancelPreloadingRecentTasksList();
+ cancelPreloadingRecentTasksList();
break;
case MSG_OPEN_SEARCH_PANEL:
if (DEBUG) Slog.d(TAG, "opening search panel");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
index 4f33e23..3ac1bcf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
@@ -49,7 +49,7 @@
public boolean onInterceptTouchEvent(MotionEvent event) {
if (mSourceView == null || mDelegateView == null
- || mBar.shouldDisableNavbarGestures() || mBar.inKeyguardRestrictedInputMode()) {
+ || mBar.shouldDisableNavbarGestures()) {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index dcc2e57..770ae6d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -142,6 +142,11 @@
return mCurrentView.findViewById(R.id.home);
}
+ // for when home is disabled, but search isn't
+ public View getSearchLight() {
+ return mCurrentView.findViewById(R.id.search_light);
+ }
+
public NavigationBarView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -222,12 +227,15 @@
final boolean disableHome = ((disabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
final boolean disableRecent = ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0);
final boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0);
+ final boolean disableSearch = ((disabledFlags & View.STATUS_BAR_DISABLE_SEARCH) != 0);
setSlippery(disableHome && disableRecent && disableBack);
getBackButton() .setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
getHomeButton() .setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE);
getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
+
+ getSearchLight().setVisibility((disableHome && !disableSearch) ? View.VISIBLE : View.GONE);
}
public void setSlippery(boolean newSlippery) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index c832fb8..248a516 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -21,6 +21,8 @@
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
+import android.util.Slog;
+import android.view.MotionEvent;
import android.view.View;
import com.android.systemui.R;
@@ -31,11 +33,18 @@
Drawable mHandleBar;
float mHandleBarHeight;
View mHandleView;
+ int mFingers;
+ PhoneStatusBar mStatusBar;
+ boolean mOkToFlip;
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
}
+ public void setStatusBar(PhoneStatusBar bar) {
+ mStatusBar = bar;
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
@@ -79,4 +88,35 @@
mHandleBar.draw(canvas);
canvas.translate(0, -off);
}
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (PhoneStatusBar.SETTINGS_DRAG_SHORTCUT && mStatusBar.mHasFlipSettings) {
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ mOkToFlip = getExpandedHeight() == 0;
+ break;
+ case MotionEvent.ACTION_POINTER_DOWN:
+ if (mOkToFlip) {
+ float miny = event.getY(0);
+ float maxy = miny;
+ for (int i=1; i<event.getPointerCount(); i++) {
+ final float y = event.getY(i);
+ if (y < miny) miny = y;
+ if (y > maxy) maxy = y;
+ }
+ if (maxy - miny < mHandleBarHeight) {
+ if (getMeasuredHeight() < mHandleBarHeight) {
+ mStatusBar.switchToSettings();
+ } else {
+ mStatusBar.flipToSettings();
+ }
+ mOkToFlip = false;
+ }
+ }
+ break;
+ }
+ }
+ return mHandleView.dispatchTouchEvent(event);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index d0fc340..c9a137c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -102,7 +102,7 @@
startOpeningPanel(panel);
}
final boolean result = mTouchingPanel != null
- ? mTouchingPanel.getHandle().dispatchTouchEvent(event)
+ ? mTouchingPanel.onTouchEvent(event)
: true;
return result;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 7eb84e1..6184e30 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -98,7 +98,7 @@
if (mPeekAnimator == null) {
mPeekAnimator = ObjectAnimator.ofFloat(this,
"expandedHeight", mPeekHeight)
- .setDuration(300);
+ .setDuration(250);
}
mPeekAnimator.start();
}
@@ -206,7 +206,7 @@
mFlingGestureMaxOutputVelocityPx = res.getDimension(R.dimen.fling_gesture_max_output_velocity);
- mPeekHeight = res.getDimension(R.dimen.close_handle_height)
+ mPeekHeight = res.getDimension(R.dimen.peek_height)
+ getPaddingBottom() // our window might have a dropshadow
- (mHandleView == null ? 0 : mHandleView.getPaddingTop()); // the handle might have a topshadow
}
@@ -250,6 +250,7 @@
case MotionEvent.ACTION_DOWN:
mTracking = true;
mHandleView.setPressed(true);
+ postInvalidate(); // catch the press state change
mInitialTouchY = y;
mVelocityTracker = VelocityTracker.obtain();
trackMovement(event);
@@ -283,6 +284,7 @@
mFinalTouchY = y;
mTracking = false;
mHandleView.setPressed(false);
+ postInvalidate(); // catch the press state change
mBar.onTrackingStopped(PanelView.this);
trackMovement(event);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 64bce22..f906176 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -40,7 +40,6 @@
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.NinePatchDrawable;
import android.inputmethodservice.InputMethodService;
import android.os.Handler;
import android.os.IBinder;
@@ -110,6 +109,8 @@
public static final boolean ENABLE_NOTIFICATION_PANEL_CLING = false;
+ public static final boolean SETTINGS_DRAG_SHORTCUT = true;
+
// additional instrumentation for testing purposes; intended to be left on during development
public static final boolean CHATTY = DEBUG;
@@ -180,7 +181,7 @@
View mMoreIcon;
// expanded notifications
- PanelView mNotificationPanel; // the sliding/resizing panel within the notification window
+ NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
ScrollView mScrollView;
View mExpandedContents;
int mNotificationPanelGravity;
@@ -198,6 +199,8 @@
int mSettingsPanelGravity;
// top bar
+ View mNotificationPanelHeader;
+ View mDateTimeView;
View mClearButton;
ImageView mSettingsButton, mNotificationButton;
@@ -295,7 +298,7 @@
if (MULTIUSER_DEBUG) Slog.d(TAG, String.format("User setup changed: " +
"selfChange=%s userSetup=%s mUserSetup=%s",
selfChange, userSetup, mUserSetup));
- if (mSettingsButton != null) {
+ if (mSettingsButton != null && !mHasSettingsPanel) {
mSettingsButton.setVisibility(userSetup ? View.VISIBLE : View.INVISIBLE);
}
if (mSettingsPanel != null) {
@@ -361,7 +364,8 @@
PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder);
mStatusBarView.setPanelHolder(holder);
- mNotificationPanel = (PanelView) mStatusBarWindow.findViewById(R.id.notification_panel);
+ mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(R.id.notification_panel);
+ mNotificationPanel.setStatusBar(this);
mNotificationPanelIsFullScreenWidth =
(mNotificationPanel.getLayoutParams().width == ViewGroup.LayoutParams.MATCH_PARENT);
@@ -420,6 +424,8 @@
mPile.setLongPressListener(getNotificationLongClicker());
mExpandedContents = mPile; // was: expanded.findViewById(R.id.notificationLinearLayout);
+ mNotificationPanelHeader = mStatusBarWindow.findViewById(R.id.header);
+
mClearButton = mStatusBarWindow.findViewById(R.id.clear_all_button);
mClearButton.setOnClickListener(mClearButtonListener);
mClearButton.setAlpha(0f);
@@ -430,6 +436,12 @@
mHasSettingsPanel = res.getBoolean(R.bool.config_hasSettingsPanel);
mHasFlipSettings = res.getBoolean(R.bool.config_hasFlipSettingsPanel);
+ mDateTimeView = mNotificationPanelHeader.findViewById(R.id.datetime);
+ if (mHasFlipSettings) {
+ mDateTimeView.setOnClickListener(mClockClickListener);
+ mDateTimeView.setEnabled(true);
+ }
+
mSettingsButton = (ImageView) mStatusBarWindow.findViewById(R.id.settings_button);
if (mSettingsButton != null) {
mSettingsButton.setOnClickListener(mSettingsButtonListener);
@@ -440,7 +452,11 @@
mSettingsButton.setVisibility(View.VISIBLE);
} else {
// there is a settings panel, but it's on the other side of the (large) screen
- mSettingsButton.setVisibility(View.GONE);
+ final View buttonHolder = mStatusBarWindow.findViewById(
+ R.id.settings_button_holder);
+ if (buttonHolder != null) {
+ buttonHolder.setVisibility(View.GONE);
+ }
}
} else {
// no settings panel, go straight to settings
@@ -457,10 +473,12 @@
mScrollView = (ScrollView)mStatusBarWindow.findViewById(R.id.scroll);
mScrollView.setVerticalScrollBarEnabled(false); // less drawing during pulldowns
- mScrollView.setSystemUiVisibility(
- View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER |
- View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS |
- View.STATUS_BAR_DISABLE_CLOCK);
+ if (!mNotificationPanelIsFullScreenWidth) {
+ mScrollView.setSystemUiVisibility(
+ View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER |
+ View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS |
+ View.STATUS_BAR_DISABLE_CLOCK);
+ }
mTicker = new MyTicker(context, mStatusBarView);
@@ -488,6 +506,8 @@
mEmergencyCallLabel = (TextView)mStatusBarWindow.findViewById(R.id.emergency_calls_only);
if (mEmergencyCallLabel != null) {
mNetworkController.addEmergencyLabelView(mEmergencyCallLabel);
+ mEmergencyCallLabel.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) { }});
mEmergencyCallLabel.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
@@ -541,8 +561,6 @@
}
if (mSettingsPanel != null) {
- mSettingsPanel.setBar(mStatusBarView);
-
if (!ActivityManager.isHighEndGfx()) {
mSettingsPanel.setBackground(new FastColorDrawable(context.getResources().getColor(
R.color.notification_panel_solid_background)));
@@ -555,14 +573,16 @@
mStatusBarWindow.findViewById(R.id.quick_settings_container);
if (mSettingsContainer != null) {
mQS = new QuickSettings(mContext, mSettingsContainer);
- mSettingsContainer.setSystemUiVisibility(
- View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER
- | View.STATUS_BAR_DISABLE_SYSTEM_INFO);
-
+ if (!mNotificationPanelIsFullScreenWidth) {
+ mSettingsContainer.setSystemUiVisibility(
+ View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER
+ | View.STATUS_BAR_DISABLE_SYSTEM_INFO);
+ }
if (mSettingsPanel != null) {
mSettingsPanel.setQuickSettings(mQS);
}
mQS.setService(this);
+ mQS.setBar(mStatusBarView);
mQS.setup(mNetworkController, mBluetoothController, mBatteryController,
mLocationController);
} else {
@@ -660,6 +680,10 @@
@Override
public void showSearchPanel() {
super.showSearchPanel();
+
+ // we want to freeze the sysui state wherever it is
+ mSearchPanelView.setSystemUiVisibility(mSystemUiVisibility);
+
WindowManager.LayoutParams lp =
(android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
@@ -706,7 +730,7 @@
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
- if (!shouldDisableNavbarGestures() && !inKeyguardRestrictedInputMode()) {
+ if (!shouldDisableNavbarGestures()) {
mHandler.removeCallbacks(mShowSearchPanel);
mHandler.postDelayed(mShowSearchPanel, mShowSearchHoldoff);
}
@@ -736,7 +760,7 @@
mNavigationBarView.reorient();
mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
- mNavigationBarView.getRecentsButton().setOnTouchListener(getRecentTasksLoader());
+ mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPreloadOnTouchListener);
mNavigationBarView.getHomeButton().setOnTouchListener(mHomeSearchActionListener);
updateSearchPanel();
}
@@ -1065,7 +1089,13 @@
+ " any=" + any + " clearable=" + clearable);
}
- if (mClearButton.isShown()) {
+ if (mHasFlipSettings
+ && mFlipSettingsView != null
+ && mFlipSettingsView.getVisibility() == View.VISIBLE
+ && mScrollView.getVisibility() != View.VISIBLE) {
+ // the flip settings panel is unequivocally showing; we should not be shown
+ mClearButton.setVisibility(View.INVISIBLE);
+ } else if (mClearButton.isShown()) {
if (clearable != (mClearButton.getAlpha() == 1.0f)) {
ObjectAnimator clearAnimation = ObjectAnimator.ofFloat(
mClearButton, "alpha", clearable ? 1.0f : 0.0f).setDuration(250);
@@ -1156,6 +1186,8 @@
flagdbg.append(((diff & StatusBarManager.DISABLE_RECENT) != 0) ? "* " : " ");
flagdbg.append(((state & StatusBarManager.DISABLE_CLOCK) != 0) ? "CLOCK" : "clock");
flagdbg.append(((diff & StatusBarManager.DISABLE_CLOCK) != 0) ? "* " : " ");
+ flagdbg.append(((state & StatusBarManager.DISABLE_SEARCH) != 0) ? "SEARCH" : "search");
+ flagdbg.append(((diff & StatusBarManager.DISABLE_SEARCH) != 0) ? "* " : " ");
flagdbg.append(">");
Slog.d(TAG, flagdbg.toString());
@@ -1193,7 +1225,8 @@
if ((diff & (StatusBarManager.DISABLE_HOME
| StatusBarManager.DISABLE_RECENT
- | StatusBarManager.DISABLE_BACK)) != 0) {
+ | StatusBarManager.DISABLE_BACK
+ | StatusBarManager.DISABLE_SEARCH)) != 0) {
// the nav bar will take care of these
if (mNavigationBarView != null) mNavigationBarView.setDisabledFlags(state);
@@ -1266,6 +1299,10 @@
}
}
+ public Handler getHandler() {
+ return mHandler;
+ }
+
View.OnFocusChangeListener mFocusChangeListener = new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
// Because 'v' is a ViewGroup, all its children will be (un)selected
@@ -1280,17 +1317,6 @@
return;
}
- if (mHasFlipSettings && !mExpandedVisible) {
- // reset things to their proper state
- mScrollView.setScaleX(1f);
- mScrollView.setVisibility(View.VISIBLE);
- mSettingsButton.setAlpha(1f);
- mSettingsButton.setVisibility(View.VISIBLE);
- mNotificationPanel.setVisibility(View.GONE);
- mFlipSettingsView.setVisibility(View.GONE);
- mNotificationButton.setVisibility(View.GONE);
- }
-
mExpandedVisible = true;
mPile.setLayoutTransitionsEnabled(true);
if (mNavigationBarView != null)
@@ -1400,51 +1426,53 @@
}
mNotificationPanel.expand();
- if (mHasFlipSettings) {
- if (mScrollView.getVisibility() != View.VISIBLE) {
- if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
- if (mScrollViewAnim != null) mScrollViewAnim.cancel();
- if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
- if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
- if (mClearButtonAnim != null) mClearButtonAnim.cancel();
-
- mScrollView.setVisibility(View.VISIBLE);
- mScrollViewAnim = start(
- startDelay(FLIP_DURATION_OUT,
- interpolator(mDecelerateInterpolator,
- ObjectAnimator.ofFloat(mScrollView, View.SCALE_X, 0f, 1f)
- .setDuration(FLIP_DURATION_IN)
- )));
- mFlipSettingsViewAnim = start(
- setVisibilityWhenDone(
- interpolator(mAccelerateInterpolator,
- ObjectAnimator.ofFloat(mFlipSettingsView, View.SCALE_X, 1f, 0f)
- )
- .setDuration(FLIP_DURATION_OUT),
- mFlipSettingsView, View.INVISIBLE));
- mNotificationButtonAnim = start(
- setVisibilityWhenDone(
- ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 0f)
- .setDuration(FLIP_DURATION),
- mNotificationButton, View.INVISIBLE));
- mSettingsButton.setVisibility(View.VISIBLE);
- mSettingsButtonAnim = start(
- ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 1f)
- .setDuration(FLIP_DURATION));
- mClearButton.setVisibility(View.VISIBLE);
- mClearButton.setAlpha(0f);
- setAreThereNotifications(); // this will show/hide the button as necessary
- mNotificationPanel.postDelayed(new Runnable() {
- public void run() {
- updateCarrierLabelVisibility(false);
- }
- }, FLIP_DURATION - 150);
- }
+ if (mHasFlipSettings && mScrollView.getVisibility() != View.VISIBLE) {
+ flipToNotifications();
}
if (false) postStartTracing();
}
+ public void flipToNotifications() {
+ if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
+ if (mScrollViewAnim != null) mScrollViewAnim.cancel();
+ if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
+ if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
+ if (mClearButtonAnim != null) mClearButtonAnim.cancel();
+
+ mScrollView.setVisibility(View.VISIBLE);
+ mScrollViewAnim = start(
+ startDelay(FLIP_DURATION_OUT,
+ interpolator(mDecelerateInterpolator,
+ ObjectAnimator.ofFloat(mScrollView, View.SCALE_X, 0f, 1f)
+ .setDuration(FLIP_DURATION_IN)
+ )));
+ mFlipSettingsViewAnim = start(
+ setVisibilityWhenDone(
+ interpolator(mAccelerateInterpolator,
+ ObjectAnimator.ofFloat(mFlipSettingsView, View.SCALE_X, 1f, 0f)
+ )
+ .setDuration(FLIP_DURATION_OUT),
+ mFlipSettingsView, View.INVISIBLE));
+ mNotificationButtonAnim = start(
+ setVisibilityWhenDone(
+ ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 0f)
+ .setDuration(FLIP_DURATION),
+ mNotificationButton, View.INVISIBLE));
+ mSettingsButton.setVisibility(View.VISIBLE);
+ mSettingsButtonAnim = start(
+ ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 1f)
+ .setDuration(FLIP_DURATION));
+ mClearButton.setVisibility(View.VISIBLE);
+ mClearButton.setAlpha(0f);
+ setAreThereNotifications(); // this will show/hide the button as necessary
+ mNotificationPanel.postDelayed(new Runnable() {
+ public void run() {
+ updateCarrierLabelVisibility(false);
+ }
+ }, FLIP_DURATION - 150);
+ }
+
@Override
public void animateExpandSettingsPanel() {
if (SPEW) Slog.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
@@ -1455,46 +1483,7 @@
if (mHasFlipSettings) {
mNotificationPanel.expand();
if (mFlipSettingsView.getVisibility() != View.VISIBLE) {
- if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
- if (mScrollViewAnim != null) mScrollViewAnim.cancel();
- if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
- if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
- if (mClearButtonAnim != null) mClearButtonAnim.cancel();
-
- mFlipSettingsView.setVisibility(View.VISIBLE);
- mFlipSettingsView.setScaleX(0f);
- mFlipSettingsViewAnim = start(
- startDelay(FLIP_DURATION_OUT,
- interpolator(mDecelerateInterpolator,
- ObjectAnimator.ofFloat(mFlipSettingsView, View.SCALE_X, 0f, 1f)
- .setDuration(FLIP_DURATION_IN)
- )));
- mScrollViewAnim = start(
- setVisibilityWhenDone(
- interpolator(mAccelerateInterpolator,
- ObjectAnimator.ofFloat(mScrollView, View.SCALE_X, 1f, 0f)
- )
- .setDuration(FLIP_DURATION_OUT),
- mScrollView, View.INVISIBLE));
- mSettingsButtonAnim = start(
- setVisibilityWhenDone(
- ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 0f)
- .setDuration(FLIP_DURATION),
- mScrollView, View.INVISIBLE));
- mNotificationButton.setVisibility(View.VISIBLE);
- mNotificationButtonAnim = start(
- ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 1f)
- .setDuration(FLIP_DURATION));
- mClearButtonAnim = start(
- setVisibilityWhenDone(
- ObjectAnimator.ofFloat(mClearButton, View.ALPHA, 0f)
- .setDuration(FLIP_DURATION),
- mClearButton, View.INVISIBLE));
- mNotificationPanel.postDelayed(new Runnable() {
- public void run() {
- updateCarrierLabelVisibility(false);
- }
- }, FLIP_DURATION - 150);
+ flipToSettings();
}
} else if (mSettingsPanel != null) {
mSettingsPanel.expand();
@@ -1503,10 +1492,78 @@
if (false) postStartTracing();
}
+ public void switchToSettings() {
+ mFlipSettingsView.setScaleX(1f);
+ mFlipSettingsView.setVisibility(View.VISIBLE);
+ mSettingsButton.setVisibility(View.GONE);
+ mScrollView.setVisibility(View.GONE);
+ mScrollView.setScaleX(0f);
+ mNotificationButton.setVisibility(View.VISIBLE);
+ mNotificationButton.setAlpha(1f);
+ mClearButton.setVisibility(View.GONE);
+ }
+
+ public void flipToSettings() {
+ if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
+ if (mScrollViewAnim != null) mScrollViewAnim.cancel();
+ if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
+ if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
+ if (mClearButtonAnim != null) mClearButtonAnim.cancel();
+
+ mFlipSettingsView.setVisibility(View.VISIBLE);
+ mFlipSettingsView.setScaleX(0f);
+ mFlipSettingsViewAnim = start(
+ startDelay(FLIP_DURATION_OUT,
+ interpolator(mDecelerateInterpolator,
+ ObjectAnimator.ofFloat(mFlipSettingsView, View.SCALE_X, 0f, 1f)
+ .setDuration(FLIP_DURATION_IN)
+ )));
+ mScrollViewAnim = start(
+ setVisibilityWhenDone(
+ interpolator(mAccelerateInterpolator,
+ ObjectAnimator.ofFloat(mScrollView, View.SCALE_X, 1f, 0f)
+ )
+ .setDuration(FLIP_DURATION_OUT),
+ mScrollView, View.INVISIBLE));
+ mSettingsButtonAnim = start(
+ setVisibilityWhenDone(
+ ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 0f)
+ .setDuration(FLIP_DURATION),
+ mScrollView, View.INVISIBLE));
+ mNotificationButton.setVisibility(View.VISIBLE);
+ mNotificationButtonAnim = start(
+ ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 1f)
+ .setDuration(FLIP_DURATION));
+ mClearButtonAnim = start(
+ setVisibilityWhenDone(
+ ObjectAnimator.ofFloat(mClearButton, View.ALPHA, 0f)
+ .setDuration(FLIP_DURATION),
+ mClearButton, View.INVISIBLE));
+ mNotificationPanel.postDelayed(new Runnable() {
+ public void run() {
+ updateCarrierLabelVisibility(false);
+ }
+ }, FLIP_DURATION - 150);
+ }
+
+ public void flipPanels() {
+ if (mHasFlipSettings) {
+ if (mFlipSettingsView.getVisibility() != View.VISIBLE) {
+ flipToSettings();
+ } else {
+ flipToNotifications();
+ }
+ }
+ }
+
public void animateCollapseQuickSettings() {
mStatusBarView.collapseAllPanels(true);
}
+ void makeExpandedInvisibleSoon() {
+ mHandler.postDelayed(new Runnable() { public void run() { makeExpandedInvisible(); }}, 50);
+ }
+
void makeExpandedInvisible() {
if (SPEW) Slog.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible
+ " mExpandedVisible=" + mExpandedVisible);
@@ -1518,6 +1575,24 @@
// Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868)
mStatusBarView.collapseAllPanels(/*animate=*/ false);
+ if (mHasFlipSettings) {
+ // reset things to their proper state
+ if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
+ if (mScrollViewAnim != null) mScrollViewAnim.cancel();
+ if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
+ if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
+ if (mClearButtonAnim != null) mClearButtonAnim.cancel();
+
+ mScrollView.setScaleX(1f);
+ mScrollView.setVisibility(View.VISIBLE);
+ mSettingsButton.setAlpha(1f);
+ mSettingsButton.setVisibility(View.VISIBLE);
+ mNotificationPanel.setVisibility(View.GONE);
+ mFlipSettingsView.setVisibility(View.GONE);
+ mNotificationButton.setVisibility(View.GONE);
+ setAreThereNotifications(); // show the clear button
+ }
+
mExpandedVisible = false;
mPile.setLayoutTransitionsEnabled(false);
if (mNavigationBarView != null)
@@ -2128,24 +2203,36 @@
}
};
+ public void startActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned) {
+ if (onlyProvisioned && !isDeviceProvisioned()) return;
+ try {
+ // Dismiss the lock screen when Settings starts.
+ ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
+ } catch (RemoteException e) {
+ }
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ animateCollapsePanels();
+ }
+
private View.OnClickListener mSettingsButtonListener = new View.OnClickListener() {
public void onClick(View v) {
if (mHasSettingsPanel) {
animateExpandSettingsPanel();
} else {
- try {
- // Dismiss the lock screen when Settings starts.
- ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
- } catch (RemoteException e) {
- }
- Intent intent = new Intent(android.provider.Settings.ACTION_SETTINGS);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
- animateCollapsePanels();
+ startActivityDismissingKeyguard(
+ new Intent(android.provider.Settings.ACTION_SETTINGS), true);
}
}
};
+ private View.OnClickListener mClockClickListener = new View.OnClickListener() {
+ public void onClick(View v) {
+ startActivityDismissingKeyguard(
+ new Intent(Intent.ACTION_QUICK_CLOCK), true); // have fun, everyone
+ }
+ };
+
private View.OnClickListener mNotificationButtonListener = new View.OnClickListener() {
public void onClick(View v) {
animateExpandNotificationsPanel();
@@ -2345,7 +2432,9 @@
@Override
protected boolean shouldDisableNavbarGestures() {
- return mExpandedVisible || (mDisabled & StatusBarManager.DISABLE_HOME) != 0;
+ return !isDeviceProvisioned()
+ || mExpandedVisible
+ || (mDisabled & StatusBarManager.DISABLE_SEARCH) != 0;
}
private static class FastColorDrawable extends Drawable {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 3c2f0e6..af6a149 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -154,7 +154,8 @@
@Override
public void onAllPanelsCollapsed() {
super.onAllPanelsCollapsed();
- mBar.makeExpandedInvisible();
+ // give animations time to settle
+ mBar.makeExpandedInvisibleSoon();
mFadingPanel = null;
mLastFullyOpenedPanel = null;
}
@@ -191,14 +192,34 @@
if (panel == mFadingPanel && mScrimColor != 0 && ActivityManager.isHighEndGfx()) {
if (mShouldFade) {
frac = mPanelExpandedFractionSum; // don't judge me
- // woo, special effects
- final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2.2f))));
- // attenuate background color alpha by k
- final int color = (int) ((mScrimColor >>> 24) * k) << 24 | (mScrimColor & 0xFFFFFF);
- mBar.mStatusBarWindow.setBackgroundColor(color);
+ // let's start this 20% of the way down the screen
+ frac = frac * 1.2f - 0.2f;
+ if (frac <= 0) {
+ mBar.mStatusBarWindow.setBackgroundColor(0);
+ } else {
+ // woo, special effects
+ final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f))));
+ // attenuate background color alpha by k
+ final int color = (int) ((mScrimColor >>> 24) * k) << 24 | (mScrimColor & 0xFFFFFF);
+ mBar.mStatusBarWindow.setBackgroundColor(color);
+ }
}
}
+ // fade out the panel as it gets buried into the status bar to avoid overdrawing the
+ // status bar on the last frame of a close animation
+ final int H = mBar.getStatusBarHeight();
+ final float ph = panel.getExpandedHeight() + panel.getPaddingBottom();
+ float alpha = 1f;
+ if (ph < 2*H) {
+ if (ph < H) alpha = 0f;
+ else alpha = (ph - H) / H;
+ alpha = alpha * alpha; // get there faster
+ }
+ if (panel.getAlpha() != alpha) {
+ panel.setAlpha(alpha);
+ }
+
mBar.updateCarrierLabelVisibility(false);
}
}
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 5b550c2..599b7e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -145,6 +145,7 @@
IntentFilter filter = new IntentFilter();
filter.addAction(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
+ filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
filter.addAction(Intent.ACTION_USER_SWITCHED);
mContext.registerReceiver(mReceiver, filter);
@@ -321,7 +322,31 @@
parent.addView(userTile);
mDynamicSpannedTiles.add(userTile);
+ // Brightness
+ QuickSettingsTileView brightnessTile = (QuickSettingsTileView)
+ inflater.inflate(R.layout.quick_settings_tile, parent, false);
+ brightnessTile.setContent(R.layout.quick_settings_tile_brightness, inflater);
+ brightnessTile.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mBar.collapseAllPanels(true);
+ showBrightnessDialog();
+ }
+ });
+ mModel.addBrightnessTile(brightnessTile, new QuickSettingsModel.RefreshCallback() {
+ @Override
+ public void refreshView(QuickSettingsTileView view, State state) {
+ TextView tv = (TextView) view.findViewById(R.id.brightness_textview);
+ tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0);
+ tv.setText(state.label);
+ dismissBrightnessDialog(mBrightnessDialogShortTimeout);
+ }
+ });
+ parent.addView(brightnessTile);
+ mDynamicSpannedTiles.add(brightnessTile);
+
// Time tile
+ /*
QuickSettingsTileView timeTile = (QuickSettingsTileView)
inflater.inflate(R.layout.quick_settings_tile, parent, false);
timeTile.setContent(R.layout.quick_settings_tile_time, inflater);
@@ -338,6 +363,7 @@
});
parent.addView(timeTile);
mDynamicSpannedTiles.add(timeTile);
+ */
// Settings tile
QuickSettingsTileView settingsTile = (QuickSettingsTileView)
@@ -549,27 +575,6 @@
parent.addView(bluetoothTile);
}
- // Brightness
- QuickSettingsTileView brightnessTile = (QuickSettingsTileView)
- inflater.inflate(R.layout.quick_settings_tile, parent, false);
- brightnessTile.setContent(R.layout.quick_settings_tile_brightness, inflater);
- brightnessTile.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- mBar.collapseAllPanels(true);
- showBrightnessDialog();
- }
- });
- mModel.addBrightnessTile(brightnessTile, new QuickSettingsModel.RefreshCallback() {
- @Override
- public void refreshView(QuickSettingsTileView view, State state) {
- TextView tv = (TextView) view.findViewById(R.id.brightness_textview);
- tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0);
- tv.setText(state.label);
- dismissBrightnessDialog(mBrightnessDialogShortTimeout);
- }
- });
- parent.addView(brightnessTile);
}
private void addTemporaryTiles(final ViewGroup parent, final LayoutInflater inflater) {
@@ -766,6 +771,8 @@
});
mBrightnessDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ mBrightnessDialog.getWindow().getAttributes().privateFlags |=
+ WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
mBrightnessDialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
}
if (!mBrightnessDialog.isShowing()) {
@@ -850,6 +857,11 @@
DisplayManager.EXTRA_WIFI_DISPLAY_STATUS);
mWifiDisplayStatus = status;
applyWifiDisplayStatus();
+ } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
+ int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
+ BluetoothAdapter.ERROR);
+ mBluetoothState.enabled = (state == BluetoothAdapter.STATE_ON);
+ applyBluetoothStatus();
} else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
int status = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
BluetoothAdapter.STATE_DISCONNECTED);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
index 67846a3..ecc70d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
@@ -53,6 +53,16 @@
private TextSwitcher mTextSwitcher;
private float mIconScale;
+ public static boolean isGraphicOrEmoji(char c) {
+ int gc = Character.getType(c);
+ return gc != Character.CONTROL
+ && gc != Character.FORMAT
+ && gc != Character.UNASSIGNED
+ && gc != Character.LINE_SEPARATOR
+ && gc != Character.PARAGRAPH_SEPARATOR
+ && gc != Character.SPACE_SEPARATOR;
+ }
+
private final class Segment {
StatusBarNotification notification;
Drawable icon;
@@ -68,7 +78,7 @@
}
CharSequence rtrim(CharSequence substr, int start, int end) {
- while (end > start && !TextUtils.isGraphic(substr.charAt(end-1))) {
+ while (end > start && !isGraphicOrEmoji(substr.charAt(end-1))) {
end--;
}
if (end > start) {
@@ -101,7 +111,7 @@
this.first = false;
int index = this.next;
final int len = this.text.length();
- while (index < len && !TextUtils.isGraphic(this.text.charAt(index))) {
+ while (index < len && !isGraphicOrEmoji(this.text.charAt(index))) {
index++;
}
if (index >= len) {
@@ -136,7 +146,7 @@
this.text = text;
int index = 0;
final int len = text.length();
- while (index < len && !TextUtils.isGraphic(text.charAt(index))) {
+ while (index < len && !isGraphicOrEmoji(text.charAt(index))) {
index++;
}
this.current = index;
@@ -194,7 +204,8 @@
final Drawable icon = StatusBarIconView.getIcon(mContext,
new StatusBarIcon(n.pkg, n.user, n.notification.icon, n.notification.iconLevel, 0,
n.notification.tickerText));
- final Segment newSegment = new Segment(n, icon, n.notification.tickerText);
+ final CharSequence text = n.notification.tickerText;
+ final Segment newSegment = new Segment(n, icon, text);
// If there's already a notification schedule for this package and id, remove it.
for (int i=0; i<mSegments.size(); i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 97451ae..86c247a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -60,8 +60,6 @@
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.statusbar.StatusBarNotification;
import com.android.systemui.R;
-import com.android.systemui.recent.RecentTasksLoader;
-import com.android.systemui.recent.RecentsPanelView;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.DoNotDisturb;
@@ -353,7 +351,7 @@
mWindowManager.addView(mCompatModePanel, lp);
- mRecentButton.setOnTouchListener(getRecentTasksLoader());
+ mRecentButton.setOnTouchListener(mRecentsPreloadOnTouchListener);
mPile = (NotificationRowLayout)mNotificationPanel.findViewById(R.id.content);
mPile.removeAllViews();
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 9ea47f9..c215f1b 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -290,7 +290,7 @@
}
});
AlertDialog dialog = builder.create();
- dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
+ dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
dialog.show();
}
@@ -339,7 +339,7 @@
return mAdapter.getItem(position).onLongPress();
}
});
- dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
+ dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
dialog.setOnDismissListener(this);
@@ -390,11 +390,7 @@
refreshSilentMode();
mAirplaneModeOn.updateState(mAirplaneState);
mAdapter.notifyDataSetChanged();
- if (mKeyguardShowing) {
- mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- } else {
- mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
- }
+ mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
if (SHOW_SILENT_TOGGLE) {
IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
mContext.registerReceiver(mRingerModeReceiver, filter);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 72cb1dd..41d67bc 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -2867,8 +2867,6 @@
mDecor = generateDecor();
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
- mDecor.setLayoutDirection(
- getContext().getResources().getConfiguration().getLayoutDirection());
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 91d5eaa..fefd4fb 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -299,6 +299,7 @@
int mCarDockRotation;
int mDeskDockRotation;
int mHdmiRotation;
+ boolean mHdmiRotationLock;
int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
int mUserRotation = Surface.ROTATION_0;
@@ -412,7 +413,9 @@
boolean mForceStatusBarFromKeyguard;
boolean mHideLockScreen;
boolean mDismissKeyguard;
- boolean mNoDreamEnterAnim;
+ boolean mShowingLockscreen;
+ boolean mShowingDream;
+ boolean mDreamingLockscreen;
boolean mHomePressed;
boolean mHomeLongPressed;
Intent mHomeIntent;
@@ -1035,11 +1038,14 @@
mCanHideNavigationBar = false;
}
+ // For demo purposes, allow the rotation of the HDMI display to be controlled.
+ // By default, HDMI locks rotation to landscape.
if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
mHdmiRotation = mPortraitRotation;
} else {
mHdmiRotation = mLandscapeRotation;
}
+ mHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", true);
}
public void updateSettings() {
@@ -1722,7 +1728,7 @@
if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
return com.android.internal.R.anim.app_starting_exit;
}
- } else if (win.getAttrs().type == TYPE_DREAM && mNoDreamEnterAnim
+ } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
&& transit == TRANSIT_ENTER) {
// Special case: we are animating in a dream, while the keyguard
// is shown. We don't want an animation on the dream, because
@@ -1908,15 +1914,15 @@
Intent service = new Intent();
service.setClassName(mContext, "com.android.server.LoadAverageService");
ContentResolver res = mContext.getContentResolver();
- boolean shown = Settings.System.getInt(
- res, Settings.System.SHOW_PROCESSES, 0) != 0;
+ boolean shown = Settings.Global.getInt(
+ res, Settings.Global.SHOW_PROCESSES, 0) != 0;
if (!shown) {
mContext.startService(service);
} else {
mContext.stopService(service);
}
- Settings.System.putInt(
- res, Settings.System.SHOW_PROCESSES, shown ? 0 : 1);
+ Settings.Global.putInt(
+ res, Settings.Global.SHOW_PROCESSES, shown ? 0 : 1);
return -1;
}
}
@@ -2923,7 +2929,8 @@
mHideLockScreen = false;
mAllowLockscreenWhenOn = false;
mDismissKeyguard = false;
- mNoDreamEnterAnim = false;
+ mShowingLockscreen = false;
+ mShowingDream = false;
}
/** {@inheritDoc} */
@@ -2941,18 +2948,24 @@
}
}
if (attrs.type == TYPE_KEYGUARD) {
- mNoDreamEnterAnim = true;
+ mShowingLockscreen = true;
}
- if (((attrs.type >= FIRST_APPLICATION_WINDOW && attrs.type <= LAST_APPLICATION_WINDOW)
- || (attrs.type == TYPE_DREAM && win.isVisibleLw()))
+ boolean applyWindow = attrs.type >= FIRST_APPLICATION_WINDOW
+ && attrs.type <= LAST_APPLICATION_WINDOW;
+ if (attrs.type == TYPE_DREAM) {
+ mShowingDream = true;
+ if (!mDreamingLockscreen) {
+ applyWindow = true;
+ } else if (win.isVisibleLw() && win.hasDrawnLw()) {
+ applyWindow = true;
+ }
+ }
+ if (applyWindow
&& attrs.x == 0 && attrs.y == 0
&& attrs.width == WindowManager.LayoutParams.MATCH_PARENT
&& attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
if (DEBUG_LAYOUT) Log.v(TAG, "Fullscreen window: " + win);
mTopFullscreenOpaqueWindowState = win;
- if (attrs.type == TYPE_DREAM) {
- mForceStatusBarFromKeyguard = true;
- }
if ((attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
if (DEBUG_LAYOUT) Log.v(TAG, "Setting mHideLockScreen to true by win " + win);
mHideLockScreen = true;
@@ -2979,6 +2992,12 @@
? mTopFullscreenOpaqueWindowState.getAttrs()
: null;
+ // If we are not currently showing a dream, then update the lockscreen
+ // state that will apply if a dream is shown next time.
+ if (!mShowingDream) {
+ mDreamingLockscreen = mShowingLockscreen;
+ }
+
if (mStatusBar != null) {
if (DEBUG_LAYOUT) Log.i(TAG, "force=" + mForceStatusBar
+ " forcefkg=" + mForceStatusBarFromKeyguard
@@ -3873,7 +3892,7 @@
// enable 180 degree rotation while docked.
preferredRotation = mDeskDockEnablesAccelerometer
? sensorRotation : mDeskDockRotation;
- } else if (mHdmiPlugged) {
+ } else if (mHdmiPlugged && mHdmiRotationLock) {
// Ignore sensor when plugged into HDMI.
// Note that the dock orientation overrides the HDMI orientation.
preferredRotation = mHdmiRotation;
@@ -4519,9 +4538,12 @@
pw.print(","); pw.print(mDockBottom); pw.println(")");
pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
+ pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen);
+ pw.print(" mShowingDream="); pw.print(mShowingDream);
+ pw.print(" mDreamingLockscreen="); pw.println(mDreamingLockscreen);
pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
pw.println(mTopFullscreenOpaqueWindowState);
- pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
+ pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
pw.print(" mForceStatusBarFromKeyguard=");
@@ -4538,5 +4560,7 @@
pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
+ pw.print(prefix); pw.print("mHdmiRotation="); pw.print(mHdmiRotation);
+ pw.print(" mHdmiRotationLock="); pw.println(mHdmiRotationLock);
}
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/ClockView.java b/policy/src/com/android/internal/policy/impl/keyguard/ClockView.java
index 97a3f26..6c701c7 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/ClockView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/ClockView.java
@@ -23,6 +23,7 @@
import android.database.ContentObserver;
import android.graphics.Typeface;
import android.os.Handler;
+import android.os.UserHandle;
import android.provider.Settings;
import android.text.format.DateFormat;
import android.util.AttributeSet;
@@ -172,7 +173,7 @@
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
- mContext.registerReceiver(mIntentReceiver, filter);
+ mContext.registerReceiverAsUser(mIntentReceiver, UserHandle.OWNER, filter, null, null );
}
/* monitor 12/24-hour display preference */
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java
index 78fdda3..04ab871 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java
@@ -75,7 +75,7 @@
public void onDetachedFromWindow() {
if (DEBUG) Log.d(TAG, "onDetachedFromWindow()");
if (mBiometricUnlock != null) {
- mBiometricUnlock.stopAndShowBackup();
+ mBiometricUnlock.stop();
}
}
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 ebc54b32..b86e5b8 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -611,6 +611,7 @@
int layoutId = getLayoutIdFor(securityMode);
if (view == null && layoutId != 0) {
final LayoutInflater inflater = LayoutInflater.from(mContext);
+ if (DEBUG) Log.v(TAG, "inflating id = " + layoutId);
View v = inflater.inflate(layoutId, this, false);
mSecurityViewContainer.addView(v);
updateSecurityView(v);
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
index 0ad2404..b66c883 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
@@ -43,7 +43,7 @@
/**
* Manages creating, showing, hiding and resetting the keyguard. Calls back
- * via {@link com.android.internal.policy.impl.KeyguardViewCallback} to poke
+ * via {@link KeyguardViewMediator.ViewMediatorCallback} to poke
* the wake lock and report that the keyguard is done, which is in turn,
* reported to this class by the current {@link KeyguardViewBase}.
*/
@@ -233,6 +233,7 @@
if (mScreenOn) {
mKeyguardView.show();
+ mKeyguardView.requestFocus();
}
}
@@ -314,22 +315,25 @@
// Caller should wait for this window to be shown before turning
// on the screen.
- if (mKeyguardHost.getVisibility() == View.VISIBLE) {
- // Keyguard may be in the process of being shown, but not yet
- // updated with the window manager... give it a chance to do so.
- mKeyguardHost.post(new Runnable() {
- public void run() {
- if (mKeyguardHost.getVisibility() == View.VISIBLE) {
- showListener.onShown(mKeyguardHost.getWindowToken());
- } else {
- showListener.onShown(null);
+ if (showListener != null) {
+ if (mKeyguardHost.getVisibility() == View.VISIBLE) {
+ // Keyguard may be in the process of being shown, but not yet
+ // updated with the window manager... give it a chance to do so.
+ mKeyguardHost.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mKeyguardHost.getVisibility() == View.VISIBLE) {
+ showListener.onShown(mKeyguardHost.getWindowToken());
+ } else {
+ showListener.onShown(null);
+ }
}
- }
- });
- } else {
- showListener.onShown(null);
+ });
+ } else {
+ showListener.onShown(null);
+ }
}
- } else {
+ } else if (showListener != null) {
showListener.onShown(null);
}
}
@@ -356,10 +360,9 @@
if (mKeyguardView != null) {
mKeyguardView.wakeWhenReadyTq(keyCode);
return true;
- } else {
- Log.w(TAG, "mKeyguardView is null in wakeWhenReadyTq");
- return false;
}
+ Log.w(TAG, "mKeyguardView is null in wakeWhenReadyTq");
+ return false;
}
/**
@@ -382,6 +385,7 @@
final KeyguardViewBase lastView = mKeyguardView;
mKeyguardView = null;
mKeyguardHost.postDelayed(new Runnable() {
+ @Override
public void run() {
synchronized (KeyguardViewManager.this) {
lastView.cleanUp();
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
index 92f9dfd..ceb0325 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
@@ -629,9 +629,7 @@
mScreenOn = true;
cancelDoKeyguardLaterLocked();
if (DEBUG) Log.d(TAG, "onScreenTurnedOn, seq = " + mDelayedShowingSequence);
- if (showListener != null) {
- notifyScreenOnLocked(showListener);
- }
+ notifyScreenOnLocked(showListener);
}
maybeSendUserPresentBroadcast();
}
@@ -1365,7 +1363,7 @@
/**
* Handle message sent by {@link #verifyUnlock}
- * @see #RESET
+ * @see #VERIFY_UNLOCK
*/
private void handleVerifyUnlock() {
synchronized (KeyguardViewMediator.this) {
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index e7e4f87..06d37dc 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -98,21 +98,19 @@
IntentFilter userFilter = new IntentFilter();
userFilter.addAction(Intent.ACTION_USER_REMOVED);
+ userFilter.addAction(Intent.ACTION_USER_STOPPING);
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1));
+ if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
+ onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+ UserHandle.USER_NULL));
+ } else if (Intent.ACTION_USER_STOPPING.equals(intent.getAction())) {
+ onUserStopping(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+ UserHandle.USER_NULL));
+ }
}
}, userFilter);
-
- IntentFilter userStopFilter = new IntentFilter();
- userStopFilter.addAction(Intent.ACTION_USER_STOPPED);
- mContext.registerReceiverAsUser(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- onUserStopped(getSendingUserId());
- }
- }, UserHandle.ALL, userFilter, null, null);
}
/**
@@ -203,7 +201,7 @@
synchronized (mAppWidgetServices) {
AppWidgetServiceImpl impl = mAppWidgetServices.get(userId);
mAppWidgetServices.remove(userId);
-
+
if (impl == null) {
AppWidgetServiceImpl.getSettingsFile(userId).delete();
} else {
@@ -212,7 +210,15 @@
}
}
- public void onUserStopped(int userId) {
+ public void onUserStopping(int userId) {
+ if (userId < 1) return;
+ synchronized (mAppWidgetServices) {
+ AppWidgetServiceImpl impl = mAppWidgetServices.get(userId);
+ if (impl != null) {
+ mAppWidgetServices.remove(userId);
+ impl.onUserStopping();
+ }
+ }
}
private AppWidgetServiceImpl getImplForUser(int userId) {
@@ -324,11 +330,11 @@
String action = intent.getAction();
// Slog.d(TAG, "received " + action);
if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
- int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+ int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
if (userId >= 0) {
getImplForUser(userId).sendInitialBroadcasts();
} else {
- Slog.w(TAG, "Not user handle supplied in " + intent);
+ Slog.w(TAG, "Incorrect user handle supplied in " + intent);
}
} else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
for (int i = 0; i < mAppWidgetServices.size(); i++) {
diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/java/com/android/server/AppWidgetServiceImpl.java
index 9fea6f3..6a313a0 100644
--- a/services/java/com/android/server/AppWidgetServiceImpl.java
+++ b/services/java/com/android/server/AppWidgetServiceImpl.java
@@ -1778,13 +1778,16 @@
return new AtomicFile(settingsFile);
}
- void onUserRemoved() {
+ void onUserStopping() {
// prune the ones we don't want to keep
int N = mInstalledProviders.size();
for (int i = N - 1; i >= 0; i--) {
Provider p = mInstalledProviders.get(i);
cancelBroadcasts(p);
}
+ }
+
+ void onUserRemoved() {
getSettingsFile(mUserId).delete();
}
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 9f01eca..dcbf3f5 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -836,7 +836,8 @@
if ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
if (DEBUG) Slog.v(TAG, "Binding to Google transport");
Intent intent = new Intent().setComponent(transportComponent);
- context.bindService(intent, mGoogleConnection, Context.BIND_AUTO_CREATE);
+ context.bindService(intent, mGoogleConnection, Context.BIND_AUTO_CREATE,
+ UserHandle.USER_OWNER);
} else {
Slog.w(TAG, "Possible Google transport spoof: ignoring " + info);
}
@@ -1474,6 +1475,7 @@
if (MORE_DEBUG) Slog.v(TAG, " removing participant " + packageName);
removeEverBackedUp(packageName);
set.remove(packageName);
+ mPendingBackups.remove(packageName);
}
}
@@ -1625,6 +1627,7 @@
} catch (InterruptedException e) {
// just bail
if (DEBUG) Slog.w(TAG, "Interrupted: " + e);
+ mActivityManager.clearPendingBackup();
return null;
}
}
@@ -1632,6 +1635,7 @@
// if we timed out with no connect, abort and move on
if (mConnecting == true) {
Slog.w(TAG, "Timeout waiting for agent " + app);
+ mActivityManager.clearPendingBackup();
return null;
}
if (DEBUG) Slog.i(TAG, "got agent " + mConnectedAgent);
diff --git a/services/java/com/android/server/BootReceiver.java b/services/java/com/android/server/BootReceiver.java
index 22874e6..7e1de5a 100644
--- a/services/java/com/android/server/BootReceiver.java
+++ b/services/java/com/android/server/BootReceiver.java
@@ -88,6 +88,8 @@
final String headers = new StringBuilder(512)
.append("Build: ").append(Build.FINGERPRINT).append("\n")
.append("Hardware: ").append(Build.BOARD).append("\n")
+ .append("Revision: ")
+ .append(SystemProperties.get("ro.revision", "")).append("\n")
.append("Bootloader: ").append(Build.BOOTLOADER).append("\n")
.append("Radio: ").append(Build.RADIO).append("\n")
.append("Kernel: ")
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index ffbfef6..679a22a 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -1561,7 +1561,7 @@
intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_BEFORE, originalString);
intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_AFTER, suggestions[index]);
intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_HASHCODE, span.hashCode());
- mContext.sendBroadcast(intent);
+ mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
return true;
}
}
@@ -1649,7 +1649,7 @@
Intent intent = new Intent(Intent.ACTION_INPUT_METHOD_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra("input_method_id", id);
- mContext.sendBroadcast(intent);
+ mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
}
unbindCurrentClientLocked();
} finally {
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 6948927..37dee19 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -23,8 +23,11 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.content.pm.Signature;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.location.Address;
@@ -90,10 +93,13 @@
private static final String WAKELOCK_KEY = TAG;
private static final String THREAD_NAME = TAG;
- private static final String ACCESS_FINE_LOCATION =
- android.Manifest.permission.ACCESS_FINE_LOCATION;
- private static final String ACCESS_COARSE_LOCATION =
- android.Manifest.permission.ACCESS_COARSE_LOCATION;
+ // Location resolution level: no location data whatsoever
+ private static final int RESOLUTION_LEVEL_NONE = 0;
+ // Location resolution level: coarse location data only
+ private static final int RESOLUTION_LEVEL_COARSE = 1;
+ // Location resolution level: fine location data
+ private static final int RESOLUTION_LEVEL_FINE = 2;
+
private static final String ACCESS_MOCK_LOCATION =
android.Manifest.permission.ACCESS_MOCK_LOCATION;
private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
@@ -246,6 +252,74 @@
updateProvidersLocked();
}
+ private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) {
+ PackageManager pm = mContext.getPackageManager();
+ String systemPackageName = mContext.getPackageName();
+ ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
+
+ List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
+ new Intent(FUSED_LOCATION_SERVICE_ACTION),
+ PackageManager.GET_META_DATA, mCurrentUserId);
+ for (ResolveInfo rInfo : rInfos) {
+ String packageName = rInfo.serviceInfo.packageName;
+
+ // Check that the signature is in the list of supported sigs. If it's not in
+ // this list the standard provider binding logic won't bind to it.
+ try {
+ PackageInfo pInfo;
+ pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
+ if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
+ Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
+ ", but has wrong signature, ignoring");
+ continue;
+ }
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "missing package: " + packageName);
+ continue;
+ }
+
+ // Get the version info
+ if (rInfo.serviceInfo.metaData == null) {
+ Log.w(TAG, "Found fused provider without metadata: " + packageName);
+ continue;
+ }
+
+ int version = rInfo.serviceInfo.metaData.getInt(
+ ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
+ if (version == 0) {
+ // This should be the fallback fused location provider.
+
+ // Make sure it's in the system partition.
+ if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+ if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
+ continue;
+ }
+
+ // Check that the fallback is signed the same as the OS
+ // as a proxy for coreApp="true"
+ if (pm.checkSignatures(systemPackageName, packageName)
+ != PackageManager.SIGNATURE_MATCH) {
+ if (D) Log.d(TAG, "Fallback candidate not signed the same as system: "
+ + packageName);
+ continue;
+ }
+
+ // Found a valid fallback.
+ if (D) Log.d(TAG, "Found fallback provider: " + packageName);
+ return;
+ } else {
+ if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
+ }
+ }
+
+ throw new IllegalStateException("Unable to find a fused location provider that is in the "
+ + "system partition with version 0 and signed with the platform certificate. "
+ + "Such a package is needed to provide a default fused location provider in the "
+ + "event that no other fused location provider has been installed or is currently "
+ + "available. For example, coreOnly boot mode when decrypting the data "
+ + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
+ }
+
private void loadProvidersLocked() {
// create a passive location provider, which is always enabled
PassiveProvider passiveProvider = new PassiveProvider(this);
@@ -275,14 +349,13 @@
*/
Resources resources = mContext.getResources();
ArrayList<String> providerPackageNames = new ArrayList<String>();
- String[] pkgs1 = resources.getStringArray(
+ String[] pkgs = resources.getStringArray(
com.android.internal.R.array.config_locationProviderPackageNames);
- String[] pkgs2 = resources.getStringArray(
- com.android.internal.R.array.config_overlay_locationProviderPackageNames);
- if (D) Log.d(TAG, "built-in location providers: " + Arrays.toString(pkgs1));
- if (D) Log.d(TAG, "overlay location providers: " + Arrays.toString(pkgs2));
- if (pkgs1 != null) providerPackageNames.addAll(Arrays.asList(pkgs1));
- if (pkgs2 != null) providerPackageNames.addAll(Arrays.asList(pkgs2));
+ if (D) Log.d(TAG, "certificates for location providers pulled from: " +
+ Arrays.toString(pkgs));
+ if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));
+
+ ensureFallbackFusedProviderPresentLocked(providerPackageNames);
// bind to network provider
LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
@@ -347,7 +420,7 @@
final int mUid; // uid of receiver
final int mPid; // pid of receiver
final String mPackageName; // package name of receiver
- final String mPermission; // best permission that receiver has
+ final int mAllowedResolutionLevel; // resolution level allowed to receiver
final ILocationListener mListener;
final PendingIntent mPendingIntent;
@@ -366,7 +439,7 @@
} else {
mKey = intent;
}
- mPermission = checkPermission();
+ mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
mUid = uid;
mPid = pid;
mPackageName = packageName;
@@ -440,7 +513,7 @@
// synchronize to ensure incrementPendingBroadcastsLocked()
// is called before decrementPendingBroadcasts()
mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
- mPermission);
+ getResolutionPermission(mAllowedResolutionLevel));
// call this after broadcasting so we do not increment
// if we throw an exeption.
incrementPendingBroadcastsLocked();
@@ -474,7 +547,7 @@
// synchronize to ensure incrementPendingBroadcastsLocked()
// is called before decrementPendingBroadcasts()
mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
- mPermission);
+ getResolutionPermission(mAllowedResolutionLevel));
// call this after broadcasting so we do not increment
// if we throw an exeption.
incrementPendingBroadcastsLocked();
@@ -512,7 +585,7 @@
// synchronize to ensure incrementPendingBroadcastsLocked()
// is called before decrementPendingBroadcasts()
mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
- mPermission);
+ getResolutionPermission(mAllowedResolutionLevel));
// call this after broadcasting so we do not increment
// if we throw an exeption.
incrementPendingBroadcastsLocked();
@@ -609,51 +682,76 @@
}
/**
- * Returns the best permission available to the caller.
+ * Returns the permission string associated with the specified resolution level.
+ *
+ * @param resolutionLevel the resolution level
+ * @return the permission string
*/
- private String getBestCallingPermission() {
- if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) ==
- PackageManager.PERMISSION_GRANTED) {
- return ACCESS_FINE_LOCATION;
- } else if (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION) ==
- PackageManager.PERMISSION_GRANTED) {
- return ACCESS_COARSE_LOCATION;
+ private String getResolutionPermission(int resolutionLevel) {
+ switch (resolutionLevel) {
+ case RESOLUTION_LEVEL_FINE:
+ return android.Manifest.permission.ACCESS_FINE_LOCATION;
+ case RESOLUTION_LEVEL_COARSE:
+ return android.Manifest.permission.ACCESS_COARSE_LOCATION;
+ default:
+ return null;
}
- return null;
}
/**
- * Throw SecurityException if caller has neither COARSE or FINE.
- * Otherwise, return the best permission.
+ * Returns the resolution level allowed to the given PID/UID pair.
+ *
+ * @param pid the PID
+ * @param uid the UID
+ * @return resolution level allowed to the pid/uid pair
*/
- private String checkPermission() {
- String perm = getBestCallingPermission();
- if (perm == null) {
- throw new SecurityException("Location requires either ACCESS_COARSE_LOCATION or" +
- " ACCESS_FINE_LOCATION permission");
+ private int getAllowedResolutionLevel(int pid, int uid) {
+ if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
+ pid, uid) == PackageManager.PERMISSION_GRANTED) {
+ return RESOLUTION_LEVEL_FINE;
+ } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
+ pid, uid) == PackageManager.PERMISSION_GRANTED) {
+ return RESOLUTION_LEVEL_COARSE;
+ } else {
+ return RESOLUTION_LEVEL_NONE;
}
- return perm;
}
/**
- * Throw SecurityException if caller lacks permission to use Geofences.
+ * Returns the resolution level allowed to the caller
+ *
+ * @return resolution level allowed to caller
*/
- private void checkGeofencePermission() {
- if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) !=
- PackageManager.PERMISSION_GRANTED) {
+ private int getCallerAllowedResolutionLevel() {
+ return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
+ }
+
+ /**
+ * Throw SecurityException if specified resolution level is insufficient to use geofences.
+ *
+ * @param allowedResolutionLevel resolution level allowed to caller
+ */
+ private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
+ if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
}
}
- private String getMinimumPermissionForProvider(String provider) {
+ /**
+ * Return the minimum resolution level required to use the specified location provider.
+ *
+ * @param provider the name of the location provider
+ * @return minimum resolution level required for provider
+ */
+ private int getMinimumResolutionLevelForProviderUse(String provider) {
if (LocationManager.GPS_PROVIDER.equals(provider) ||
LocationManager.PASSIVE_PROVIDER.equals(provider)) {
// gps and passive providers require FINE permission
- return ACCESS_FINE_LOCATION;
+ return RESOLUTION_LEVEL_FINE;
} else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
LocationManager.FUSED_PROVIDER.equals(provider)) {
// network and fused providers are ok with COARSE or FINE
- return ACCESS_COARSE_LOCATION;
+ return RESOLUTION_LEVEL_COARSE;
} else {
// mock providers
LocationProviderInterface lp = mMockProviders.get(provider);
@@ -662,41 +760,38 @@
if (properties != null) {
if (properties.mRequiresSatellite) {
// provider requiring satellites require FINE permission
- return ACCESS_FINE_LOCATION;
+ return RESOLUTION_LEVEL_FINE;
} else if (properties.mRequiresNetwork || properties.mRequiresCell) {
// provider requiring network and or cell require COARSE or FINE
- return ACCESS_COARSE_LOCATION;
+ return RESOLUTION_LEVEL_COARSE;
}
}
}
}
-
- return null;
+ return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
}
- private boolean isPermissionSufficient(String perm, String minPerm) {
- if (ACCESS_FINE_LOCATION.equals(minPerm)) {
- return ACCESS_FINE_LOCATION.equals(perm);
- } else if (ACCESS_COARSE_LOCATION.equals(minPerm)) {
- return ACCESS_FINE_LOCATION.equals(perm) ||
- ACCESS_COARSE_LOCATION.equals(perm);
- } else {
- return false;
- }
- }
-
- private void checkPermissionForProvider(String perm, String provider) {
- String minPerm = getMinimumPermissionForProvider(provider);
- if (!isPermissionSufficient(perm, minPerm)) {
- if (ACCESS_FINE_LOCATION.equals(minPerm)) {
- throw new SecurityException("Location provider \"" + provider +
- "\" requires ACCESS_FINE_LOCATION permission.");
- } else if (ACCESS_COARSE_LOCATION.equals(minPerm)) {
- throw new SecurityException("Location provider \"" + provider +
- "\" requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
- } else {
- throw new SecurityException("Insufficient permission for location provider \"" +
- provider + "\".");
+ /**
+ * Throw SecurityException if specified resolution level is insufficient to use the named
+ * location provider.
+ *
+ * @param allowedResolutionLevel resolution level allowed to caller
+ * @param providerName the name of the location provider
+ */
+ private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel,
+ String providerName) {
+ int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName);
+ if (allowedResolutionLevel < requiredResolutionLevel) {
+ switch (requiredResolutionLevel) {
+ case RESOLUTION_LEVEL_FINE:
+ throw new SecurityException("\"" + providerName + "\" location provider " +
+ "requires ACCESS_FINE_LOCATION permission.");
+ case RESOLUTION_LEVEL_COARSE:
+ throw new SecurityException("\"" + providerName + "\" location provider " +
+ "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
+ default:
+ throw new SecurityException("Insufficient permission for \"" + providerName +
+ "\" location provider.");
}
}
}
@@ -731,8 +826,8 @@
*/
@Override
public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
+ int allowedResolutionLevel = getCallerAllowedResolutionLevel();
ArrayList<String> out;
- String perm = getBestCallingPermission();
int callingUserId = UserHandle.getCallingUserId();
long identity = Binder.clearCallingIdentity();
try {
@@ -743,7 +838,7 @@
if (LocationManager.FUSED_PROVIDER.equals(name)) {
continue;
}
- if (isPermissionSufficient(perm, getMinimumPermissionForProvider(name))) {
+ if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
if (enabledOnly && !isAllowedBySettingsLocked(name, callingUserId)) {
continue;
}
@@ -803,8 +898,6 @@
@Override
public boolean providerMeetsCriteria(String provider, Criteria criteria) {
- checkPermission();
-
LocationProviderInterface p = mProvidersByName.get(provider);
if (p == null) {
throw new IllegalArgumentException("provider=" + provider);
@@ -1010,33 +1103,41 @@
return receiver;
}
- private String checkPermissionAndRequest(LocationRequest request) {
- String perm = getBestCallingPermission();
- String provider = request.getProvider();
- checkPermissionForProvider(perm, provider);
-
- if (ACCESS_COARSE_LOCATION.equals(perm)) {
- switch (request.getQuality()) {
+ /**
+ * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
+ * and consistency requirements.
+ *
+ * @param request the LocationRequest from which to create a sanitized version
+ * @param shouldBeCoarse whether the sanitized version should be held to coarse resolution
+ * constraints
+ * @param fastestCoarseIntervalMS minimum interval allowed for coarse resolution
+ * @return a version of request that meets the given resolution and consistency requirements
+ * @hide
+ */
+ private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel) {
+ LocationRequest sanitizedRequest = new LocationRequest(request);
+ if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
+ switch (sanitizedRequest.getQuality()) {
case LocationRequest.ACCURACY_FINE:
- request.setQuality(LocationRequest.ACCURACY_BLOCK);
+ sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
break;
case LocationRequest.POWER_HIGH:
- request.setQuality(LocationRequest.POWER_LOW);
+ sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
break;
}
// throttle
- if (request.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
- request.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
+ if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
+ sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
}
- if (request.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
- request.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
+ if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
+ sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
}
}
// make getFastestInterval() the minimum of interval and fastest interval
- if (request.getFastestInterval() > request.getInterval()) {
+ if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
request.setFastestInterval(request.getInterval());
}
- return perm;
+ return sanitizedRequest;
}
private void checkPackageName(String packageName) {
@@ -1079,7 +1180,10 @@
PendingIntent intent, String packageName) {
if (request == null) request = DEFAULT_LOCATION_REQUEST;
checkPackageName(packageName);
- checkPermissionAndRequest(request);
+ int allowedResolutionLevel = getCallerAllowedResolutionLevel();
+ checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
+ request.getProvider());
+ LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
@@ -1089,7 +1193,7 @@
long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- requestLocationUpdatesLocked(request, recevier, pid, uid, packageName);
+ requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -1132,7 +1236,7 @@
public void removeUpdates(ILocationListener listener, PendingIntent intent,
String packageName) {
checkPackageName(packageName);
- checkPermission();
+
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
Receiver receiver = checkListenerOrIntent(listener, intent, pid, uid, packageName);
@@ -1188,8 +1292,11 @@
public Location getLastLocation(LocationRequest request, String packageName) {
if (D) Log.d(TAG, "getLastLocation: " + request);
if (request == null) request = DEFAULT_LOCATION_REQUEST;
- String perm = checkPermissionAndRequest(request);
+ int allowedResolutionLevel = getCallerAllowedResolutionLevel();
checkPackageName(packageName);
+ checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
+ request.getProvider());
+ // no need to sanitize this request, as only the provider name is used
long identity = Binder.clearCallingIdentity();
try {
@@ -1213,13 +1320,13 @@
if (location == null) {
return null;
}
- if (ACCESS_FINE_LOCATION.equals(perm)) {
- return location;
- } else {
+ if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
if (noGPSLocation != null) {
return mLocationFudger.getOrCreate(noGPSLocation);
}
+ } else {
+ return location;
}
}
return null;
@@ -1232,18 +1339,21 @@
public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
String packageName) {
if (request == null) request = DEFAULT_LOCATION_REQUEST;
- checkGeofencePermission();
- checkPermissionAndRequest(request);
+ int allowedResolutionLevel = getCallerAllowedResolutionLevel();
+ checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
checkPendingIntent(intent);
checkPackageName(packageName);
+ checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
+ request.getProvider());
+ LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
- if (D) Log.d(TAG, "requestGeofence: " + request + " " + geofence + " " + intent);
+ if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
// geo-fence manager uses the public location API, need to clear identity
int uid = Binder.getCallingUid();
long identity = Binder.clearCallingIdentity();
try {
- mGeofenceManager.addFence(request, geofence, intent, uid, packageName);
+ mGeofenceManager.addFence(sanitizedRequest, geofence, intent, uid, packageName);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1251,7 +1361,7 @@
@Override
public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
- checkGeofencePermission();
+ checkResolutionLevelIsSufficientForGeofenceUse(getCallerAllowedResolutionLevel());
checkPendingIntent(intent);
checkPackageName(packageName);
@@ -1272,10 +1382,8 @@
if (mGpsStatusProvider == null) {
return false;
}
- if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) !=
- PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
- }
+ checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
+ LocationManager.GPS_PROVIDER);
try {
mGpsStatusProvider.addGpsStatusListener(listener);
@@ -1303,8 +1411,9 @@
// throw NullPointerException to remain compatible with previous implementation
throw new NullPointerException();
}
+ checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
+ provider);
- checkPermission();
// and check for ACCESS_LOCATION_EXTRA_COMMANDS
if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
!= PackageManager.PERMISSION_GRANTED)) {
@@ -1340,7 +1449,12 @@
*/
@Override
public ProviderProperties getProviderProperties(String provider) {
- checkPermissionForProvider(getBestCallingPermission(), provider);
+ if (mProvidersByName.get(provider) == null) {
+ return null;
+ }
+
+ checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
+ provider);
LocationProviderInterface p;
synchronized (mLock) {
@@ -1353,7 +1467,8 @@
@Override
public boolean isProviderEnabled(String provider) {
- checkPermissionForProvider(getBestCallingPermission(), provider);
+ checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
+ provider);
if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
long identity = Binder.clearCallingIdentity();
@@ -1518,10 +1633,10 @@
}
Location notifyLocation = null;
- if (ACCESS_FINE_LOCATION.equals(receiver.mPermission)) {
- notifyLocation = lastLocation; // use fine location
+ if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
+ notifyLocation = coarseLocation; // use coarse location
} else {
- notifyLocation = coarseLocation; // use coarse location if available
+ notifyLocation = lastLocation; // use fine location
}
if (notifyLocation != null) {
Location lastLoc = r.mLastFixBroadcast;
diff --git a/services/java/com/android/server/ServiceWatcher.java b/services/java/com/android/server/ServiceWatcher.java
index 5598b0a..2e7c6d1 100644
--- a/services/java/com/android/server/ServiceWatcher.java
+++ b/services/java/com/android/server/ServiceWatcher.java
@@ -43,7 +43,7 @@
*/
public class ServiceWatcher implements ServiceConnection {
private static final boolean D = false;
- private static final String EXTRA_VERSION = "version";
+ public static final String EXTRA_SERVICE_VERSION = "serviceVersion";
private final String mTag;
private final Context mContext;
@@ -58,9 +58,27 @@
// all fields below synchronized on mLock
private IBinder mBinder; // connected service
private String mPackageName; // current best package
- private int mVersion; // current best version
+ private int mVersion = Integer.MIN_VALUE; // current best version
private int mCurrentUserId;
+ public static ArrayList<HashSet<Signature>> getSignatureSets(Context context,
+ List<String> initialPackageNames) {
+ PackageManager pm = context.getPackageManager();
+ ArrayList<HashSet<Signature>> sigSets = new ArrayList<HashSet<Signature>>();
+ for (int i = 0, size = initialPackageNames.size(); i < size; i++) {
+ String pkg = initialPackageNames.get(i);
+ try {
+ HashSet<Signature> set = new HashSet<Signature>();
+ Signature[] sigs = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES).signatures;
+ set.addAll(Arrays.asList(sigs));
+ sigSets.add(set);
+ } catch (NameNotFoundException e) {
+ Log.w("ServiceWatcher", pkg + " not found");
+ }
+ }
+ return sigSets;
+ }
+
public ServiceWatcher(Context context, String logTag, String action,
List<String> initialPackageNames, Runnable newServiceWork, Handler handler, int userId) {
mContext = context;
@@ -71,20 +89,7 @@
mHandler = handler;
mCurrentUserId = userId;
- mSignatureSets = new ArrayList<HashSet<Signature>>();
- for (int i=0; i < initialPackageNames.size(); i++) {
- String pkg = initialPackageNames.get(i);
- HashSet<Signature> set = new HashSet<Signature>();
- try {
- Signature[] sigs =
- mPm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES).signatures;
- set.addAll(Arrays.asList(sigs));
- mSignatureSets.add(set);
- } catch (NameNotFoundException e) {
- Log.w(logTag, pkg + " not found");
- }
- }
-
+ mSignatureSets = getSignatureSets(context, initialPackageNames);
}
public boolean start() {
@@ -132,15 +137,16 @@
// check version
int version = 0;
if (rInfo.serviceInfo.metaData != null) {
- version = rInfo.serviceInfo.metaData.getInt(EXTRA_VERSION, 0);
+ version = rInfo.serviceInfo.metaData.getInt(EXTRA_SERVICE_VERSION, 0);
}
+
if (version > mVersion) {
bestVersion = version;
bestPackage = packageName;
}
}
- if (D) Log.d(mTag, String.format("bindBestPackage %s found %d, %s",
+ if (D) Log.d(mTag, String.format("bindBestPackage for %s : %s found %d, %s", mAction,
(justCheckThisPackage == null ? "" : "(" + justCheckThisPackage + ") "),
rInfos.size(),
(bestPackage == null ? "no new best package" : "new best packge: " + bestPackage)));
@@ -174,7 +180,8 @@
| Context.BIND_ALLOW_OOM_MANAGEMENT | Context.BIND_NOT_VISIBLE, mCurrentUserId);
}
- private boolean isSignatureMatch(Signature[] signatures) {
+ public static boolean isSignatureMatch(Signature[] signatures,
+ List<HashSet<Signature>> sigSets) {
if (signatures == null) return false;
// build hashset of input to test against
@@ -184,7 +191,7 @@
}
// test input against each of the signature sets
- for (HashSet<Signature> referenceSet : mSignatureSets) {
+ for (HashSet<Signature> referenceSet : sigSets) {
if (referenceSet.equals(inputSet)) {
return true;
}
@@ -192,6 +199,10 @@
return false;
}
+ private boolean isSignatureMatch(Signature[] signatures) {
+ return isSignatureMatch(signatures, mSignatureSets);
+ }
+
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
/**
* Called when package has been reinstalled
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index eaaf33f..894c4d0 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -37,6 +37,7 @@
import android.os.StrictMode;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.server.search.SearchManagerService;
import android.service.dreams.DreamService;
import android.util.DisplayMetrics;
@@ -737,7 +738,7 @@
}
if (context.getResources().getBoolean(
- com.android.internal.R.bool.config_enableDreams)) {
+ com.android.internal.R.bool.config_dreamsSupported)) {
try {
Slog.i(TAG, "Dreams Service");
// Dreams (interactive idle-time views, a/k/a screen savers)
@@ -1005,7 +1006,7 @@
intent.setComponent(new ComponentName("com.android.systemui",
"com.android.systemui.SystemUIService"));
Slog.d(TAG, "Starting service: " + intent);
- context.startService(intent);
+ context.startServiceAsUser(intent, UserHandle.OWNER);
}
}
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index e0f3814..a02fc8d 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -458,15 +458,21 @@
IntentFilter userFilter = new IntentFilter();
userFilter.addAction(Intent.ACTION_USER_REMOVED);
+ userFilter.addAction(Intent.ACTION_USER_STOPPING);
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_USER_REMOVED.equals(action)) {
- removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+ onRemoveUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+ UserHandle.USER_NULL));
+ } else if (Intent.ACTION_USER_STOPPING.equals(action)) {
+ onStoppingUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+ UserHandle.USER_NULL));
}
}
}, userFilter);
+
try {
ActivityManagerNative.getDefault().registerUserSwitchObserver(
new IUserSwitchObserver.Stub() {
@@ -491,13 +497,24 @@
}
}
- void removeUser(int userId) {
+ void onStoppingUser(int userId) {
+ if (userId < 1) return;
synchronized (mLock) {
WallpaperData wallpaper = mWallpaperMap.get(userId);
if (wallpaper != null) {
- wallpaper.wallpaperObserver.stopWatching();
+ if (wallpaper.wallpaperObserver != null) {
+ wallpaper.wallpaperObserver.stopWatching();
+ wallpaper.wallpaperObserver = null;
+ }
mWallpaperMap.remove(userId);
}
+ }
+ }
+
+ void onRemoveUser(int userId) {
+ if (userId < 1) return;
+ synchronized (mLock) {
+ onStoppingUser(userId);
File wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
wallpaperFile.delete();
File wallpaperInfoFile = new File(getWallpaperDir(userId), WALLPAPER_INFO);
diff --git a/services/java/com/android/server/accessibility/ScreenMagnifier.java b/services/java/com/android/server/accessibility/ScreenMagnifier.java
index d5a8537..482bff5 100644
--- a/services/java/com/android/server/accessibility/ScreenMagnifier.java
+++ b/services/java/com/android/server/accessibility/ScreenMagnifier.java
@@ -38,7 +38,9 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.provider.Settings;
+import android.text.TextUtils;
import android.util.Property;
import android.util.Slog;
import android.view.Display;
@@ -70,6 +72,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.Locale;
/**
* This class handles the screen magnification when accessibility is enabled.
@@ -173,6 +176,8 @@
private PointerCoords[] mTempPointerCoords;
private PointerProperties[] mTempPointerProperties;
+ private long mDelegatingStateDownTime;
+
public ScreenMagnifier(Context context) {
mContext = context;
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
@@ -262,10 +267,15 @@
private void handleMotionEventStateDelegating(MotionEvent event,
MotionEvent rawEvent, int policyFlags) {
- if (event.getActionMasked() == MotionEvent.ACTION_UP) {
- if (mDetectingStateHandler.mDelayedEventQueue == null) {
- transitionToState(STATE_DETECTING);
- }
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN: {
+ mDelegatingStateDownTime = event.getDownTime();
+ } break;
+ case MotionEvent.ACTION_UP: {
+ if (mDetectingStateHandler.mDelayedEventQueue == null) {
+ transitionToState(STATE_DETECTING);
+ }
+ } break;
}
if (mNext != null) {
// If the event is within the magnified portion of the screen we have
@@ -292,6 +302,13 @@
coords, 0, 0, 1.0f, 1.0f, event.getDeviceId(), 0, event.getSource(),
event.getFlags());
}
+ // We cache some events to see if the user wants to trigger magnification.
+ // If no magnification is triggered we inject these events with adjusted
+ // time and down time to prevent subsequent transformations being confused
+ // by stale events. After the cached events, which always have a down, are
+ // injected we need to also update the down time of all subsequent non cached
+ // events. All delegated events cached and non-cached are delivered here.
+ event.setDownTime(mDelegatingStateDownTime);
mNext.onMotionEvent(event, rawEvent, policyFlags);
}
}
@@ -662,12 +679,33 @@
while (mDelayedEventQueue != null) {
MotionEventInfo info = mDelayedEventQueue;
mDelayedEventQueue = info.mNext;
- ScreenMagnifier.this.onMotionEvent(info.mEvent, info.mRawEvent,
- info.mPolicyFlags);
+ final long offset = SystemClock.uptimeMillis() - info.mCachedTimeMillis;
+ MotionEvent event = obtainEventWithOffsetTimeAndDownTime(info.mEvent, offset);
+ MotionEvent rawEvent = obtainEventWithOffsetTimeAndDownTime(info.mRawEvent, offset);
+ ScreenMagnifier.this.onMotionEvent(event, rawEvent, info.mPolicyFlags);
+ event.recycle();
+ rawEvent.recycle();
info.recycle();
}
}
+ private MotionEvent obtainEventWithOffsetTimeAndDownTime(MotionEvent event, long offset) {
+ final int pointerCount = event.getPointerCount();
+ PointerCoords[] coords = getTempPointerCoordsWithMinSize(pointerCount);
+ PointerProperties[] properties = getTempPointerPropertiesWithMinSize(pointerCount);
+ for (int i = 0; i < pointerCount; i++) {
+ event.getPointerCoords(i, coords[i]);
+ event.getPointerProperties(i, properties[i]);
+ }
+ final long downTime = event.getDownTime() + offset;
+ final long eventTime = event.getEventTime() + offset;
+ return MotionEvent.obtain(downTime, eventTime,
+ event.getAction(), pointerCount, properties, coords,
+ event.getMetaState(), event.getButtonState(),
+ 1.0f, 1.0f, event.getDeviceId(), event.getEdgeFlags(),
+ event.getSource(), event.getFlags());
+ }
+
private void clearDelayedMotionEvents() {
while (mDelayedEventQueue != null) {
MotionEventInfo info = mDelayedEventQueue;
@@ -746,6 +784,7 @@
public MotionEvent mEvent;
public MotionEvent mRawEvent;
public int mPolicyFlags;
+ public long mCachedTimeMillis;
public static MotionEventInfo obtain(MotionEvent event, MotionEvent rawEvent,
int policyFlags) {
@@ -770,6 +809,7 @@
mEvent = MotionEvent.obtain(event);
mRawEvent = MotionEvent.obtain(rawEvent);
mPolicyFlags = policyFlags;
+ mCachedTimeMillis = SystemClock.uptimeMillis();
}
public void recycle() {
@@ -793,6 +833,7 @@
mRawEvent.recycle();
mRawEvent = null;
mPolicyFlags = 0;
+ mCachedTimeMillis = 0;
}
}
@@ -975,45 +1016,44 @@
mViewport.recomputeBounds(mMagnificationController.isMagnifying());
} break;
}
- } else {
- switch (transition) {
- case WindowManagerPolicy.TRANSIT_ENTER:
- case WindowManagerPolicy.TRANSIT_SHOW: {
- if (!magnifying || !isScreenMagnificationAutoUpdateEnabled(mContext)) {
- break;
- }
- final int type = info.type;
- switch (type) {
- // TODO: Are these all the windows we want to make
- // visible when they appear on the screen?
- // Do we need to take some of them out?
- case WindowManager.LayoutParams.TYPE_APPLICATION:
- case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL:
- case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA:
- case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL:
- case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG:
- case WindowManager.LayoutParams.TYPE_SEARCH_BAR:
- case WindowManager.LayoutParams.TYPE_PHONE:
- case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
- case WindowManager.LayoutParams.TYPE_TOAST:
- case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
- case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE:
- case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
- case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG:
- case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
- case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY:
- case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL:
- case WindowManager.LayoutParams.TYPE_RECENTS_OVERLAY: {
- Rect magnifiedRegionBounds = mMagnificationController
- .getMagnifiedRegionBounds();
- Rect touchableRegion = info.touchableRegion;
- if (!magnifiedRegionBounds.intersect(touchableRegion)) {
- ensureRectangleInMagnifiedRegionBounds(
- magnifiedRegionBounds, touchableRegion);
- }
- } break;
- } break;
+ }
+ switch (transition) {
+ case WindowManagerPolicy.TRANSIT_ENTER:
+ case WindowManagerPolicy.TRANSIT_SHOW: {
+ if (!magnifying || !isScreenMagnificationAutoUpdateEnabled(mContext)) {
+ break;
}
+ final int type = info.type;
+ switch (type) {
+ // TODO: Are these all the windows we want to make
+ // visible when they appear on the screen?
+ // Do we need to take some of them out?
+ case WindowManager.LayoutParams.TYPE_APPLICATION:
+ case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL:
+ case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA:
+ case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL:
+ case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG:
+ case WindowManager.LayoutParams.TYPE_SEARCH_BAR:
+ case WindowManager.LayoutParams.TYPE_PHONE:
+ case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
+ case WindowManager.LayoutParams.TYPE_TOAST:
+ case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
+ case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE:
+ case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
+ case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG:
+ case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
+ case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY:
+ case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL:
+ case WindowManager.LayoutParams.TYPE_RECENTS_OVERLAY: {
+ Rect magnifiedRegionBounds = mMagnificationController
+ .getMagnifiedRegionBounds();
+ Rect touchableRegion = info.touchableRegion;
+ if (!magnifiedRegionBounds.intersect(touchableRegion)) {
+ ensureRectangleInMagnifiedRegionBounds(
+ magnifiedRegionBounds, touchableRegion);
+ }
+ } break;
+ } break;
}
}
} finally {
@@ -1042,7 +1082,12 @@
final float scrollX;
final float scrollY;
if (rectangle.width() > magnifiedRegionBounds.width()) {
- scrollX = rectangle.left - magnifiedRegionBounds.left;
+ final int direction = TextUtils.getLayoutDirectionFromLocale(Locale.getDefault());
+ if (direction == View.LAYOUT_DIRECTION_LTR) {
+ scrollX = rectangle.left - magnifiedRegionBounds.left;
+ } else {
+ scrollX = rectangle.right - magnifiedRegionBounds.right;
+ }
} else if (rectangle.left < magnifiedRegionBounds.left) {
scrollX = rectangle.left - magnifiedRegionBounds.left;
} else if (rectangle.right > magnifiedRegionBounds.right) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 7132e1e..5722326 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -7251,11 +7251,11 @@
// care about.
if (persistent) {
final ContentResolver resolver = mContext.getContentResolver();
- Settings.System.putString(
- resolver, Settings.System.DEBUG_APP,
+ Settings.Global.putString(
+ resolver, Settings.Global.DEBUG_APP,
packageName);
- Settings.System.putInt(
- resolver, Settings.System.WAIT_FOR_DEBUGGER,
+ Settings.Global.putInt(
+ resolver, Settings.Global.WAIT_FOR_DEBUGGER,
waitForDebugger ? 1 : 0);
}
@@ -7317,9 +7317,9 @@
enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
"setAlwaysFinish()");
- Settings.System.putInt(
+ Settings.Global.putInt(
mContext.getContentResolver(),
- Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
+ Settings.Global.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
synchronized (this) {
mAlwaysFinishActivities = enabled;
@@ -7596,12 +7596,12 @@
private void retrieveSettings() {
final ContentResolver resolver = mContext.getContentResolver();
- String debugApp = Settings.System.getString(
- resolver, Settings.System.DEBUG_APP);
- boolean waitForDebugger = Settings.System.getInt(
- resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
- boolean alwaysFinishActivities = Settings.System.getInt(
- resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
+ String debugApp = Settings.Global.getString(
+ resolver, Settings.Global.DEBUG_APP);
+ boolean waitForDebugger = Settings.Global.getInt(
+ resolver, Settings.Global.WAIT_FOR_DEBUGGER, 0) != 0;
+ boolean alwaysFinishActivities = Settings.Global.getInt(
+ resolver, Settings.Global.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
Configuration configuration = new Configuration();
Settings.System.getConfiguration(resolver, configuration);
@@ -11119,8 +11119,8 @@
// instantiated. The backup agent will invoke backupAgentCreated() on the
// activity manager to announce its creation.
public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
- if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
- enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
+ if (DEBUG_BACKUP) Slog.v(TAG, "bindBackupAgent: app=" + app + " mode=" + backupMode);
+ enforceCallingPermission("android.permission.BACKUP", "bindBackupAgent");
synchronized(this) {
// !!! TODO: currently no check here that we're already bound
@@ -11181,6 +11181,17 @@
return true;
}
+ @Override
+ public void clearPendingBackup() {
+ if (DEBUG_BACKUP) Slog.v(TAG, "clearPendingBackup");
+ enforceCallingPermission("android.permission.BACKUP", "clearPendingBackup");
+
+ synchronized (this) {
+ mBackupTarget = null;
+ mBackupAppName = null;
+ }
+ }
+
// A backup agent has just come up
public void backupAgentCreated(String agentPackageName, IBinder agent) {
if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
@@ -11217,32 +11228,34 @@
}
synchronized(this) {
- if (mBackupAppName == null) {
- Slog.w(TAG, "Unbinding backup agent with no active backup");
- return;
- }
-
- if (!mBackupAppName.equals(appInfo.packageName)) {
- Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
- return;
- }
-
- ProcessRecord proc = mBackupTarget.app;
- mBackupTarget = null;
- mBackupAppName = null;
-
- // Not backing this app up any more; reset its OOM adjustment
- updateOomAdjLocked(proc);
-
- // If the app crashed during backup, 'thread' will be null here
- if (proc.thread != null) {
- try {
- proc.thread.scheduleDestroyBackupAgent(appInfo,
- compatibilityInfoForPackageLocked(appInfo));
- } catch (Exception e) {
- Slog.e(TAG, "Exception when unbinding backup agent:");
- e.printStackTrace();
+ try {
+ if (mBackupAppName == null) {
+ Slog.w(TAG, "Unbinding backup agent with no active backup");
+ return;
}
+
+ if (!mBackupAppName.equals(appInfo.packageName)) {
+ Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
+ return;
+ }
+
+ // Not backing this app up any more; reset its OOM adjustment
+ final ProcessRecord proc = mBackupTarget.app;
+ updateOomAdjLocked(proc);
+
+ // If the app crashed during backup, 'thread' will be null here
+ if (proc.thread != null) {
+ try {
+ proc.thread.scheduleDestroyBackupAgent(appInfo,
+ compatibilityInfoForPackageLocked(appInfo));
+ } catch (Exception e) {
+ Slog.e(TAG, "Exception when unbinding backup agent:");
+ e.printStackTrace();
+ }
+ }
+ } finally {
+ mBackupTarget = null;
+ mBackupAppName = null;
}
}
}
diff --git a/services/java/com/android/server/display/DisplayAdapter.java b/services/java/com/android/server/display/DisplayAdapter.java
index abc1d32..b411a0d 100644
--- a/services/java/com/android/server/display/DisplayAdapter.java
+++ b/services/java/com/android/server/display/DisplayAdapter.java
@@ -42,6 +42,7 @@
public static final int DISPLAY_DEVICE_EVENT_CHANGED = 2;
public static final int DISPLAY_DEVICE_EVENT_REMOVED = 3;
+ // Called with SyncRoot lock held.
public DisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
Context context, Handler handler, Listener listener, String name) {
mSyncRoot = syncRoot;
diff --git a/services/java/com/android/server/display/DisplayDeviceInfo.java b/services/java/com/android/server/display/DisplayDeviceInfo.java
index b4dab86..e76bf44 100644
--- a/services/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/java/com/android/server/display/DisplayDeviceInfo.java
@@ -17,6 +17,7 @@
package com.android.server.display;
import android.util.DisplayMetrics;
+import android.view.Surface;
import libcore.util.Objects;
@@ -31,11 +32,21 @@
public static final int FLAG_DEFAULT_DISPLAY = 1 << 0;
/**
- * Flag: Indicates that this display device can rotate to show contents in a
- * different orientation. Otherwise the rotation is assumed to be fixed in the
- * natural orientation and the display manager should transform the content to fit.
+ * Flag: Indicates that the orientation of this display device is coupled to the
+ * rotation of its associated logical display.
+ * <p>
+ * This flag should be applied to the default display to indicate that the user
+ * physically rotates the display when content is presented in a different orientation.
+ * The display manager will apply a coordinate transformation assuming that the
+ * physical orientation of the display matches the logical orientation of its content.
+ * </p><p>
+ * The flag should not be set when the display device is mounted in a fixed orientation
+ * such as on a desk. The display manager will apply a coordinate transformation
+ * such as a scale and translation to letterbox or pillarbox format under the
+ * assumption that the physical orientation of the display is invariant.
+ * </p>
*/
- public static final int FLAG_SUPPORTS_ROTATION = 1 << 1;
+ public static final int FLAG_ROTATES_WITH_CONTENT = 1 << 1;
/**
* Flag: Indicates that this display device has secure video output, such as HDCP.
@@ -116,6 +127,17 @@
*/
public int touch;
+ /**
+ * The additional rotation to apply to all content presented on the display device
+ * relative to its physical coordinate system. Default is {@link Surface#ROTATION_0}.
+ * <p>
+ * This field can be used to compensate for the fact that the display has been
+ * physically rotated relative to its natural orientation such as an HDMI monitor
+ * that has been mounted sideways to appear to be portrait rather than landscape.
+ * </p>
+ */
+ public int rotation = Surface.ROTATION_0;
+
public void setAssumedDensityForExternalDisplay(int width, int height) {
densityDpi = Math.min(width, height) * DisplayMetrics.DENSITY_XHIGH / 1080;
// Technically, these values should be smaller than the apparent density
@@ -139,7 +161,8 @@
&& xDpi == other.xDpi
&& yDpi == other.yDpi
&& flags == other.flags
- && touch == other.touch;
+ && touch == other.touch
+ && rotation == other.rotation;
}
@Override
@@ -157,14 +180,18 @@
yDpi = other.yDpi;
flags = other.flags;
touch = other.touch;
+ rotation = other.rotation;
}
// For debugging purposes
@Override
public String toString() {
- return "DisplayDeviceInfo{\"" + name + "\": " + width + " x " + height + ", " + refreshRate + " fps, "
+ return "DisplayDeviceInfo{\"" + name + "\": " + width + " x " + height + ", "
+ + refreshRate + " fps, "
+ "density " + densityDpi + ", " + xDpi + " x " + yDpi + " dpi"
- + ", touch " + touchToString(touch) + flagsToString(flags) + "}";
+ + ", touch " + touchToString(touch) + flagsToString(flags)
+ + ", rotation " + rotation
+ + "}";
}
private static String touchToString(int touch) {
@@ -185,8 +212,8 @@
if ((flags & FLAG_DEFAULT_DISPLAY) != 0) {
msg.append(", FLAG_DEFAULT_DISPLAY");
}
- if ((flags & FLAG_SUPPORTS_ROTATION) != 0) {
- msg.append(", FLAG_SUPPORTS_ROTATION");
+ if ((flags & FLAG_ROTATES_WITH_CONTENT) != 0) {
+ msg.append(", FLAG_ROTATES_WITH_CONTENT");
}
if ((flags & FLAG_SECURE) != 0) {
msg.append(", FLAG_SECURE");
diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java
index 0a42528..e58a0a5cb 100644
--- a/services/java/com/android/server/display/DisplayManagerService.java
+++ b/services/java/com/android/server/display/DisplayManagerService.java
@@ -127,6 +127,13 @@
// services should be started. This option may disable certain display adapters.
public boolean mOnlyCore;
+ // True if the display manager service should pretend there is only one display
+ // and only tell applications about the existence of the default logical display.
+ // The display manager can still mirror content to secondary displays but applications
+ // cannot present unique content on those displays.
+ // Used for demonstration purposes only.
+ private final boolean mSingleDisplayDemoMode;
+
// All callback records indexed by calling process id.
public final SparseArray<CallbackRecord> mCallbacks =
new SparseArray<CallbackRecord>();
@@ -182,6 +189,7 @@
mHandler = new DisplayManagerHandler(mainHandler.getLooper());
mUiHandler = uiHandler;
mDisplayAdapterListener = new DisplayAdapterListener();
+ mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
}
@@ -305,6 +313,8 @@
DisplayDevice device = mDisplayDevices.get(i);
device.blankLocked();
}
+
+ scheduleTraversalLocked(false);
}
}
}
@@ -322,6 +332,8 @@
DisplayDevice device = mDisplayDevices.get(i);
device.unblankLocked();
}
+
+ scheduleTraversalLocked(false);
}
}
}
@@ -627,6 +639,12 @@
isDefault = false;
}
+ if (!isDefault && mSingleDisplayDemoMode) {
+ Slog.i(TAG, "Not creating a logical display for a secondary display "
+ + " because single display demo mode is enabled: " + deviceInfo);
+ return;
+ }
+
final int displayId = assignDisplayIdLocked(isDefault);
final int layerStack = assignLayerStackLocked(displayId);
@@ -755,7 +773,9 @@
+ device.getDisplayDeviceInfoLocked());
return;
} else {
- display.configureDisplayInTransactionLocked(device);
+ boolean isBlanked = (mAllDisplayBlankStateFromPowerManager
+ == DISPLAY_BLANK_STATE_BLANKED);
+ display.configureDisplayInTransactionLocked(device, isBlanked);
}
// Update the viewports if needed.
@@ -851,6 +871,7 @@
pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
pw.println(" mDefaultViewport=" + mDefaultViewport);
pw.println(" mExternalTouchViewport=" + mExternalTouchViewport);
+ pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
ipw.increaseIndent();
diff --git a/services/java/com/android/server/display/HeadlessDisplayAdapter.java b/services/java/com/android/server/display/HeadlessDisplayAdapter.java
index 7ec537f..919733d 100644
--- a/services/java/com/android/server/display/HeadlessDisplayAdapter.java
+++ b/services/java/com/android/server/display/HeadlessDisplayAdapter.java
@@ -29,6 +29,7 @@
final class HeadlessDisplayAdapter extends DisplayAdapter {
private static final String TAG = "HeadlessDisplayAdapter";
+ // Called with SyncRoot lock held.
public HeadlessDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
Context context, Handler handler, Listener listener) {
super(syncRoot, context, handler, listener, TAG);
diff --git a/services/java/com/android/server/display/LocalDisplayAdapter.java b/services/java/com/android/server/display/LocalDisplayAdapter.java
index d780006..d6c5248 100644
--- a/services/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/java/com/android/server/display/LocalDisplayAdapter.java
@@ -20,6 +20,7 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
+import android.os.SystemProperties;
import android.util.SparseArray;
import android.view.DisplayEventReceiver;
import android.view.Surface;
@@ -43,21 +44,21 @@
private final SparseArray<LocalDisplayDevice> mDevices =
new SparseArray<LocalDisplayDevice>();
- private final HotplugDisplayEventReceiver mHotplugReceiver;
+ private HotplugDisplayEventReceiver mHotplugReceiver;
private final PhysicalDisplayInfo mTempPhys = new PhysicalDisplayInfo();
+ // Called with SyncRoot lock held.
public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
Context context, Handler handler, Listener listener) {
super(syncRoot, context, handler, listener, TAG);
- mHotplugReceiver = new HotplugDisplayEventReceiver(handler.getLooper());
}
@Override
public void registerLocked() {
- // TODO: listen for notifications from Surface Flinger about
- // built-in displays being added or removed and rescan as needed.
super.registerLocked();
+
+ mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());
scanDisplaysLocked();
}
@@ -135,7 +136,7 @@
mInfo.name = getContext().getResources().getString(
com.android.internal.R.string.display_manager_built_in_display_name);
mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
- | DisplayDeviceInfo.FLAG_SUPPORTS_ROTATION;
+ | DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
mInfo.densityDpi = (int)(mPhys.density * 160 + 0.5f);
mInfo.xDpi = mPhys.xDpi;
mInfo.yDpi = mPhys.yDpi;
@@ -145,6 +146,12 @@
com.android.internal.R.string.display_manager_hdmi_display_name);
mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
mInfo.setAssumedDensityForExternalDisplay(mPhys.width, mPhys.height);
+
+ // For demonstration purposes, allow rotation of the external display.
+ // In the future we might allow the user to configure this directly.
+ if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
+ mInfo.rotation = Surface.ROTATION_270;
+ }
}
}
return mInfo;
diff --git a/services/java/com/android/server/display/LogicalDisplay.java b/services/java/com/android/server/display/LogicalDisplay.java
index c4b749c..aa7ea82 100644
--- a/services/java/com/android/server/display/LogicalDisplay.java
+++ b/services/java/com/android/server/display/LogicalDisplay.java
@@ -55,6 +55,10 @@
final class LogicalDisplay {
private final DisplayInfo mBaseDisplayInfo = new DisplayInfo();
+ // The layer stack we use when the display has been blanked to prevent any
+ // of its content from appearing.
+ private static final int BLANK_LAYER_STACK = -1;
+
private final int mDisplayId;
private final int mLayerStack;
private DisplayInfo mOverrideDisplayInfo; // set by the window manager
@@ -217,13 +221,15 @@
* where the display is being mirrored.
*
* @param device The display device to modify.
+ * @param isBlanked True if the device is being blanked.
*/
- public void configureDisplayInTransactionLocked(DisplayDevice device) {
+ public void configureDisplayInTransactionLocked(DisplayDevice device,
+ boolean isBlanked) {
final DisplayInfo displayInfo = getDisplayInfoLocked();
final DisplayDeviceInfo displayDeviceInfo = device.getDisplayDeviceInfoLocked();
// Set the layer stack.
- device.setLayerStackInTransactionLocked(mLayerStack);
+ device.setLayerStackInTransactionLocked(isBlanked ? BLANK_LAYER_STACK : mLayerStack);
// Set the viewport.
// This is the area of the logical display that we intend to show on the
@@ -235,10 +241,13 @@
// is rotated when the contents of the logical display are rendered.
int orientation = Surface.ROTATION_0;
if (device == mPrimaryDisplayDevice
- && (displayDeviceInfo.flags & DisplayDeviceInfo.FLAG_SUPPORTS_ROTATION) != 0) {
+ && (displayDeviceInfo.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0) {
orientation = displayInfo.rotation;
}
+ // Apply the physical rotation of the display device itself.
+ orientation = (orientation + displayDeviceInfo.rotation) % 4;
+
// Set the frame.
// The frame specifies the rotated physical coordinates into which the viewport
// is mapped. We need to take care to preserve the aspect ratio of the viewport.
diff --git a/services/java/com/android/server/display/OverlayDisplayAdapter.java b/services/java/com/android/server/display/OverlayDisplayAdapter.java
index dfacf2a..c35fd98 100644
--- a/services/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -64,6 +64,7 @@
new ArrayList<OverlayDisplayHandle>();
private String mCurrentOverlaySetting = "";
+ // Called with SyncRoot lock held.
public OverlayDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
Context context, Handler handler, Listener listener, Handler uiHandler) {
super(syncRoot, context, handler, listener, TAG);
@@ -281,7 +282,7 @@
@Override
public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate) {
synchronized (getSyncRoot()) {
- IBinder displayToken = Surface.createDisplay(mName);
+ IBinder displayToken = Surface.createDisplay(mName, false);
mDevice = new OverlayDisplayDevice(displayToken, mName,
mWidth, mHeight, refreshRate, mDensityDpi, surfaceTexture);
diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java
index c441b02..97fc3e6 100644
--- a/services/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/java/com/android/server/display/WifiDisplayAdapter.java
@@ -16,17 +16,28 @@
package com.android.server.display;
+import com.android.internal.R;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
import android.hardware.display.DisplayManager;
import android.hardware.display.WifiDisplay;
import android.hardware.display.WifiDisplayStatus;
import android.media.RemoteDisplay;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.UserHandle;
+import android.provider.Settings;
import android.util.Slog;
import android.view.Surface;
@@ -52,8 +63,18 @@
private static final boolean DEBUG = false;
+ private static final int MSG_SEND_STATUS_CHANGE_BROADCAST = 1;
+ private static final int MSG_UPDATE_NOTIFICATION = 2;
+
+ private static final String ACTION_DISCONNECT = "android.server.display.wfd.DISCONNECT";
+
+ private final WifiDisplayHandler mHandler;
private final PersistentDataStore mPersistentDataStore;
private final boolean mSupportsProtectedBuffers;
+ private final NotificationManager mNotificationManager;
+
+ private PendingIntent mSettingsPendingIntent;
+ private PendingIntent mDisconnectPendingIntent;
private WifiDisplayController mDisplayController;
private WifiDisplayDevice mDisplayDevice;
@@ -67,14 +88,19 @@
private WifiDisplay[] mRememberedDisplays = WifiDisplay.EMPTY_ARRAY;
private boolean mPendingStatusChangeBroadcast;
+ private boolean mPendingNotificationUpdate;
+ // Called with SyncRoot lock held.
public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
Context context, Handler handler, Listener listener,
PersistentDataStore persistentDataStore) {
super(syncRoot, context, handler, listener, TAG);
+ mHandler = new WifiDisplayHandler(handler.getLooper());
mPersistentDataStore = persistentDataStore;
mSupportsProtectedBuffers = context.getResources().getBoolean(
com.android.internal.R.bool.config_wifiDisplaySupportsProtectedBuffers);
+ mNotificationManager = (NotificationManager)context.getSystemService(
+ Context.NOTIFICATION_SERVICE);
}
@Override
@@ -89,6 +115,7 @@
pw.println("mAvailableDisplays=" + Arrays.toString(mAvailableDisplays));
pw.println("mRememberedDisplays=" + Arrays.toString(mRememberedDisplays));
pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast);
+ pw.println("mPendingNotificationUpdate=" + mPendingNotificationUpdate);
pw.println("mSupportsProtectedBuffers=" + mSupportsProtectedBuffers);
// Try to dump the controller state.
@@ -113,6 +140,9 @@
public void run() {
mDisplayController = new WifiDisplayController(
getContext(), getHandler(), mWifiDisplayListener);
+
+ getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
+ new IntentFilter(ACTION_DISCONNECT), null, mHandler);
}
});
}
@@ -262,10 +292,12 @@
float refreshRate = 60.0f; // TODO: get this for real
String name = display.getFriendlyDisplayName();
- IBinder displayToken = Surface.createDisplay(name);
+ IBinder displayToken = Surface.createDisplay(name, false);
mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height,
refreshRate, deviceFlags, surface);
sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED);
+
+ scheduleUpdateNotificationLocked();
}
private void handleDisconnectLocked() {
@@ -273,6 +305,8 @@
mDisplayDevice.clearSurfaceLocked();
sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED);
mDisplayDevice = null;
+
+ scheduleUpdateNotificationLocked();
}
}
@@ -280,28 +314,100 @@
mCurrentStatus = null;
if (!mPendingStatusChangeBroadcast) {
mPendingStatusChangeBroadcast = true;
- getHandler().post(mStatusChangeBroadcast);
+ mHandler.sendEmptyMessage(MSG_SEND_STATUS_CHANGE_BROADCAST);
}
}
- private final Runnable mStatusChangeBroadcast = new Runnable() {
- @Override
- public void run() {
- final Intent intent;
- synchronized (getSyncRoot()) {
- if (!mPendingStatusChangeBroadcast) {
- return;
- }
+ private void scheduleUpdateNotificationLocked() {
+ if (!mPendingNotificationUpdate) {
+ mPendingNotificationUpdate = true;
+ mHandler.sendEmptyMessage(MSG_UPDATE_NOTIFICATION);
+ }
+ }
- mPendingStatusChangeBroadcast = false;
- intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS,
- getWifiDisplayStatusLocked());
+ // Runs on the handler.
+ private void handleSendStatusChangeBroadcast() {
+ final Intent intent;
+ synchronized (getSyncRoot()) {
+ if (!mPendingStatusChangeBroadcast) {
+ return;
}
- // Send protected broadcast about wifi display status to registered receivers.
- getContext().sendBroadcast(intent);
+ mPendingStatusChangeBroadcast = false;
+ intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS,
+ getWifiDisplayStatusLocked());
+ }
+
+ // Send protected broadcast about wifi display status to registered receivers.
+ getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
+ }
+
+ // Runs on the handler.
+ private void handleUpdateNotification() {
+ final boolean isConnected;
+ synchronized (getSyncRoot()) {
+ if (!mPendingNotificationUpdate) {
+ return;
+ }
+
+ mPendingNotificationUpdate = false;
+ isConnected = (mDisplayDevice != null);
+ }
+
+ // Cancel the old notification if there is one.
+ mNotificationManager.cancelAsUser(null,
+ R.string.wifi_display_notification_title, UserHandle.ALL);
+
+ if (isConnected) {
+ Context context = getContext();
+
+ // Initialize pending intents for the notification outside of the lock because
+ // creating a pending intent requires a call into the activity manager.
+ if (mSettingsPendingIntent == null) {
+ Intent settingsIntent = new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS);
+ settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ mSettingsPendingIntent = PendingIntent.getActivityAsUser(
+ context, 0, settingsIntent, 0, null, UserHandle.CURRENT);
+ }
+
+ if (mDisconnectPendingIntent == null) {
+ Intent disconnectIntent = new Intent(ACTION_DISCONNECT);
+ mDisconnectPendingIntent = PendingIntent.getBroadcastAsUser(
+ context, 0, disconnectIntent, 0, UserHandle.CURRENT);
+ }
+
+ // Post the notification.
+ Resources r = context.getResources();
+ Notification notification = new Notification.Builder(context)
+ .setContentTitle(r.getString(
+ R.string.wifi_display_notification_title))
+ .setContentText(r.getString(
+ R.string.wifi_display_notification_message))
+ .setContentIntent(mSettingsPendingIntent)
+ .setSmallIcon(R.drawable.ic_notify_wifidisplay)
+ .setOngoing(true)
+ .addAction(android.R.drawable.ic_menu_close_clear_cancel,
+ r.getString(R.string.wifi_display_notification_disconnect),
+ mDisconnectPendingIntent)
+ .build();
+ mNotificationManager.notifyAsUser(null,
+ R.string.wifi_display_notification_title,
+ notification, UserHandle.ALL);
+ }
+ }
+
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(ACTION_DISCONNECT)) {
+ synchronized (getSyncRoot()) {
+ requestDisconnectLocked();
+ }
+ }
}
};
@@ -454,4 +560,23 @@
return mInfo;
}
}
+
+ private final class WifiDisplayHandler extends Handler {
+ public WifiDisplayHandler(Looper looper) {
+ super(looper, null, true /*async*/);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_SEND_STATUS_CHANGE_BROADCAST:
+ handleSendStatusChangeBroadcast();
+ break;
+
+ case MSG_UPDATE_NOTIFICATION:
+ handleUpdateNotification();
+ break;
+ }
+ }
+ }
}
diff --git a/services/java/com/android/server/dreams/DreamController.java b/services/java/com/android/server/dreams/DreamController.java
index bfb60bb..1ab6a77 100644
--- a/services/java/com/android/server/dreams/DreamController.java
+++ b/services/java/com/android/server/dreams/DreamController.java
@@ -25,6 +25,7 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.IBinder.DeathRecipient;
+import android.os.UserHandle;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamService;
import android.util.Slog;
@@ -83,8 +84,8 @@
public void startDream(Binder token, ComponentName name, boolean isTest, int userId) {
stopDream();
- // Close the notification shade
- mContext.sendBroadcast(mCloseNotificationShadeIntent);
+ // Close the notification shade. Don't need to send to all, but better to be explicit.
+ mContext.sendBroadcastAsUser(mCloseNotificationShadeIntent, UserHandle.ALL);
Slog.i(TAG, "Starting dream: name=" + name + ", isTest=" + isTest + ", userId=" + userId);
@@ -128,7 +129,7 @@
+ ", isTest=" + oldDream.mIsTest + ", userId=" + oldDream.mUserId);
if (oldDream.mSentStartBroadcast) {
- mContext.sendBroadcast(mDreamingStoppedIntent);
+ mContext.sendBroadcastAsUser(mDreamingStoppedIntent, UserHandle.ALL);
}
if (oldDream.mService != null) {
@@ -180,7 +181,7 @@
mCurrentDream.mService = service;
if (!mCurrentDream.mIsTest) {
- mContext.sendBroadcast(mDreamingStartedIntent);
+ mContext.sendBroadcastAsUser(mDreamingStartedIntent, UserHandle.ALL);
mCurrentDream.mSentStartBroadcast = true;
}
}
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index 8b1e80f..71a6a01 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -369,7 +369,7 @@
* @param nativeLibPath target native library path
* @return -1 on error
*/
- public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath) {
+ public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath, int userId) {
if (dataPath == null) {
Slog.e(TAG, "linkNativeLibraryDirectory dataPath is null");
return -1;
@@ -382,6 +382,8 @@
builder.append(dataPath);
builder.append(' ');
builder.append(nativeLibPath);
+ builder.append(' ');
+ builder.append(userId);
return execute(builder.toString());
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index f59e30d..4c6f589 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -2575,7 +2575,7 @@
@Override
public List<ResolveInfo> queryIntentActivities(Intent intent,
String resolvedType, int flags, int userId) {
- if (!sUserManager.exists(userId)) return null;
+ if (!sUserManager.exists(userId)) return Collections.emptyList();
enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "query intent activities");
ComponentName comp = intent.getComponent();
if (comp == null) {
@@ -2615,7 +2615,7 @@
public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
Intent[] specifics, String[] specificTypes, Intent intent,
String resolvedType, int flags, int userId) {
- if (!sUserManager.exists(userId)) return null;
+ if (!sUserManager.exists(userId)) return Collections.emptyList();
enforceCrossUserPermission(Binder.getCallingUid(), userId, false,
"query intent activity options");
final String resultsAction = intent.getAction();
@@ -2787,7 +2787,7 @@
@Override
public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags,
int userId) {
- if (!sUserManager.exists(userId)) return null;
+ if (!sUserManager.exists(userId)) return Collections.emptyList();
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
@@ -2838,7 +2838,7 @@
@Override
public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags,
int userId) {
- if (!sUserManager.exists(userId)) return null;
+ if (!sUserManager.exists(userId)) return Collections.emptyList();
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
@@ -4088,39 +4088,42 @@
Log.i(TAG, "removed obsolete native libraries for system package "
+ path);
}
- } else if (!isForwardLocked(pkg) && !isExternal(pkg)) {
- // Update native library dir if it starts with /data/data
- if (nativeLibraryDir.getPath().startsWith(dataPathString)) {
- setInternalAppNativeLibraryPath(pkg, pkgSetting);
- nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
- }
+ } else {
+ if (!isForwardLocked(pkg) && !isExternal(pkg)) {
+ /*
+ * Update native library dir if it starts with
+ * /data/data
+ */
+ if (nativeLibraryDir.getPath().startsWith(dataPathString)) {
+ setInternalAppNativeLibraryPath(pkg, pkgSetting);
+ nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
+ }
- try {
- if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) {
- Slog.e(TAG, "Unable to copy native libraries");
+ try {
+ if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) {
+ Slog.e(TAG, "Unable to copy native libraries");
+ mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+ return null;
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "Unable to copy native libraries", e);
mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
return null;
}
- } catch (IOException e) {
- Slog.e(TAG, "Unable to copy native libraries", e);
- mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
- return null;
}
- if (mInstaller.linkNativeLibraryDirectory(dataPathString,
- pkg.applicationInfo.nativeLibraryDir) == -1) {
- Slog.e(TAG, "Unable to link native library directory");
- mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
- return null;
- }
- } else {
Slog.i(TAG, "Linking native library dir for " + path);
- int ret = mInstaller.linkNativeLibraryDirectory(dataPathString,
- pkg.applicationInfo.nativeLibraryDir);
- if (ret < 0) {
- Slog.w(TAG, "Failed linking native library dir for " + path);
- mLastScanError = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
- return null;
+ final int[] userIds = sUserManager.getUserIds();
+ synchronized (mInstallLock) {
+ for (int userId : userIds) {
+ if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
+ pkg.applicationInfo.nativeLibraryDir, userId) < 0) {
+ Slog.w(TAG, "Failed linking native library dir (user=" + userId
+ + ")");
+ mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+ return null;
+ }
+ }
}
}
} catch (IOException ioe) {
@@ -6327,8 +6330,23 @@
if (packageFile != null) {
// Remote call to find out default install location
- pkgLite = mContainerService.getMinimalPackageInfo(
- packageFile.getAbsolutePath(), flags, lowThreshold);
+ final String packageFilePath = packageFile.getAbsolutePath();
+ pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath, flags,
+ lowThreshold);
+
+ /*
+ * If we have too little free space, try to free cache
+ * before giving up.
+ */
+ if (pkgLite.recommendedInstallLocation
+ == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
+ final long size = mContainerService.calculateInstalledSize(
+ packageFilePath, isForwardLocked());
+ if (mInstaller.freeCache(size + lowThreshold) >= 0) {
+ pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath,
+ flags, lowThreshold);
+ }
+ }
}
} finally {
mContext.revokeUriPermission(mPackageURI,
@@ -6350,12 +6368,12 @@
ret = PackageManager.INSTALL_FAILED_INVALID_URI;
} else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
- } else if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
- ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
} else {
// Override with defaults if needed.
loc = installLocationPolicy(pkgLite, flags);
- if (!onSd && !onInt) {
+ if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
+ ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
+ } else if (!onSd && !onInt) {
// Override install location with flags
if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
// Set the flag to install on external media.
@@ -9959,20 +9977,14 @@
final File newNativeDir = new File(newNativePath);
if (!isForwardLocked(pkg) && !isExternal(pkg)) {
- synchronized (mInstallLock) {
- if (mInstaller.linkNativeLibraryDirectory(
- pkg.applicationInfo.dataDir, newNativePath) < 0) {
- returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
- }
- }
- NativeLibraryHelper.copyNativeBinariesIfNeededLI(new File(
- newCodePath), newNativeDir);
- } else {
- synchronized (mInstallLock) {
- if (mInstaller.linkNativeLibraryDirectory(
- pkg.applicationInfo.dataDir, newNativePath) < 0) {
- returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
- }
+ NativeLibraryHelper.copyNativeBinariesIfNeededLI(
+ new File(newCodePath), newNativeDir);
+ }
+ final int[] users = sUserManager.getUserIds();
+ for (int user : users) {
+ if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
+ newNativePath, user) < 0) {
+ returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
}
}
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
index 4f9375a..fb93d05 100644
--- a/services/java/com/android/server/pm/UserManagerService.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -19,9 +19,11 @@
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
+import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.IStopUserCallback;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -62,6 +64,8 @@
private static final String LOG_TAG = "UserManagerService";
+ private static final boolean DBG = false;
+
private static final String TAG_NAME = "name";
private static final String ATTR_FLAGS = "flags";
private static final String ATTR_ICON_PATH = "icon";
@@ -97,6 +101,9 @@
private int[] mUserIds;
private boolean mGuestEnabled;
private int mNextSerialNumber;
+ // This resets on a reboot. Otherwise it keeps incrementing so that user ids are
+ // not reused in quick succession
+ private int mNextUserId = MIN_USER_ID;
private static UserManagerService sInstance;
@@ -149,7 +156,7 @@
-1, -1);
mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
readUserListLocked();
- // Prune out any partially created users.
+ // Prune out any partially created/partially removed users.
ArrayList<UserInfo> partials = new ArrayList<UserInfo>();
for (int i = 0; i < mUsers.size(); i++) {
UserInfo ui = mUsers.valueAt(i);
@@ -199,7 +206,8 @@
*/
private UserInfo getUserInfoLocked(int userId) {
UserInfo ui = mUsers.get(userId);
- if (ui != null && ui.partial) {
+ // If it is partial and not in the process of being removed, return as unknown user.
+ if (ui != null && ui.partial && !mRemovingUserIds.contains(userId)) {
Slog.w(LOG_TAG, "getUserInfo: unknown user #" + userId);
return null;
}
@@ -459,7 +467,7 @@
private void fallbackToSingleUserLocked() {
// Create the primary user
UserInfo primary = new UserInfo(0, "Primary", null,
- UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY);
+ UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY | UserInfo.FLAG_INITIALIZED);
mUsers.put(0, primary);
mNextSerialNumber = MIN_USER_ID;
updateUserIdsLocked();
@@ -668,6 +676,7 @@
long now = System.currentTimeMillis();
userInfo.creationTime = (now > EPOCH_PLUS_30_YEARS) ? now : 0;
userInfo.partial = true;
+ Environment.getUserSystemDirectory(userInfo.id).mkdirs();
mUsers.put(userId, userInfo);
writeUserListLocked();
writeUserLocked(userInfo);
@@ -703,8 +712,13 @@
return false;
}
mRemovingUserIds.add(userHandle);
+ // Set this to a partially created user, so that the user will be purged
+ // on next startup, in case the runtime stops now before stopping and
+ // removing the user completely.
+ user.partial = true;
+ writeUserLocked(user);
}
-
+ if (DBG) Slog.i(LOG_TAG, "Stopping user " + userHandle);
int res;
try {
res = ActivityManagerNative.getDefault().stopUser(userHandle,
@@ -724,20 +738,38 @@
return res == ActivityManager.USER_OP_SUCCESS;
}
- void finishRemoveUser(int userHandle) {
- synchronized (mInstallLock) {
- synchronized (mPackagesLock) {
- removeUserStateLocked(userHandle);
- }
- }
-
- // Let other services shutdown any activity
+ void finishRemoveUser(final int userHandle) {
+ if (DBG) Slog.i(LOG_TAG, "finishRemoveUser " + userHandle);
+ // Let other services shutdown any activity and clean up their state before completely
+ // wiping the user's system directory and removing from the user list
long ident = Binder.clearCallingIdentity();
try {
Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle);
- mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL,
- android.Manifest.permission.MANAGE_USERS);
+ mContext.sendOrderedBroadcastAsUser(addedIntent, UserHandle.ALL,
+ android.Manifest.permission.MANAGE_USERS,
+
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (DBG) {
+ Slog.i(LOG_TAG,
+ "USER_REMOVED broadcast sent, cleaning up user data "
+ + userHandle);
+ }
+ new Thread() {
+ public void run() {
+ synchronized (mInstallLock) {
+ synchronized (mPackagesLock) {
+ removeUserStateLocked(userHandle);
+ }
+ }
+ }
+ }.start();
+ }
+ },
+
+ null, Activity.RESULT_OK, null, null);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -799,10 +831,11 @@
num++;
}
}
- int[] newUsers = new int[num];
+ final int[] newUsers = new int[num];
+ int n = 0;
for (int i = 0; i < mUsers.size(); i++) {
if (!mUsers.valueAt(i).partial) {
- newUsers[i] = mUsers.keyAt(i);
+ newUsers[n++] = mUsers.keyAt(i);
}
}
mUserIds = newUsers;
@@ -835,13 +868,14 @@
*/
private int getNextAvailableIdLocked() {
synchronized (mPackagesLock) {
- int i = MIN_USER_ID;
+ int i = mNextUserId;
while (i < Integer.MAX_VALUE) {
if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.contains(i)) {
break;
}
i++;
}
+ mNextUserId = i + 1;
return i;
}
}
diff --git a/services/java/com/android/server/power/DisplayPowerController.java b/services/java/com/android/server/power/DisplayPowerController.java
index 1561dba..ba5a475 100644
--- a/services/java/com/android/server/power/DisplayPowerController.java
+++ b/services/java/com/android/server/power/DisplayPowerController.java
@@ -30,7 +30,6 @@
import android.hardware.SensorManager;
import android.hardware.SystemSensorManager;
import android.hardware.display.DisplayManager;
-import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -44,7 +43,6 @@
import android.view.Display;
import java.io.PrintWriter;
-import java.util.concurrent.Executor;
/**
* Controls the power state of the display.
@@ -128,37 +126,39 @@
private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
// Light sensor event rate in microseconds.
- private static final int LIGHT_SENSOR_RATE = 1000000;
+ private static final int LIGHT_SENSOR_RATE = 500 * 1000;
// Brightness animation ramp rate in brightness units per second.
private static final int BRIGHTNESS_RAMP_RATE_FAST = 200;
- private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40;
+ private static final int BRIGHTNESS_RAMP_RATE_SLOW = 30;
- // Filter time constant in milliseconds for computing a moving
- // average of light samples. Different constants are used
- // to calculate the average light level when adapting to brighter or
- // dimmer environments.
- // This parameter only controls the filtering of light samples.
- private static final long BRIGHTENING_LIGHT_TIME_CONSTANT = 600;
- private static final long DIMMING_LIGHT_TIME_CONSTANT = 4000;
+ // IIR filter time constants in milliseconds for computing two moving averages of
+ // the light samples. One is a long-term average and the other is a short-term average.
+ // We can use these filters to assess trends in ambient brightness.
+ // The short term average gives us a filtered but relatively low latency measurement.
+ // The long term average informs us about the overall trend.
+ private static final long SHORT_TERM_AVERAGE_LIGHT_TIME_CONSTANT = 1000;
+ private static final long LONG_TERM_AVERAGE_LIGHT_TIME_CONSTANT = 8000;
// Stability requirements in milliseconds for accepting a new brightness
// level. This is used for debouncing the light sensor. Different constants
- // are used to debounce the light sensor when adapting to brighter or dimmer
- // environments.
+ // are used to debounce the light sensor when adapting to brighter or darker environments.
// This parameter controls how quickly brightness changes occur in response to
- // an observed change in light level.
- private static final long BRIGHTENING_LIGHT_DEBOUNCE = 2500;
- private static final long DIMMING_LIGHT_DEBOUNCE = 10000;
+ // an observed change in light level following a previous change in the opposite direction.
+ private static final long BRIGHTENING_LIGHT_DEBOUNCE = 5000;
+ private static final long DARKENING_LIGHT_DEBOUNCE = 15000;
+
+ // Hysteresis constraints for brightening or darkening.
+ // The recent lux must have changed by at least this fraction relative to the
+ // current ambient lux before a change will be considered.
+ private static final float BRIGHTENING_LIGHT_HYSTERESIS = 0.10f;
+ private static final float DARKENING_LIGHT_HYSTERESIS = 0.20f;
private final Object mLock = new Object();
// Notifier for sending asynchronous notifications.
private final Notifier mNotifier;
- // A suspend blocker.
- private final SuspendBlocker mSuspendBlocker;
-
// The display blanker.
private final DisplayBlanker mDisplayBlanker;
@@ -284,39 +284,28 @@
// The time when the light sensor was enabled.
private long mLightSensorEnableTime;
- // The currently accepted average light sensor value.
- private float mLightMeasurement;
+ // The currently accepted nominal ambient light level.
+ private float mAmbientLux;
- // True if the light sensor measurement is valid.
- private boolean mLightMeasurementValid;
+ // True if mAmbientLux holds a valid value.
+ private boolean mAmbientLuxValid;
- // The number of light sensor samples that have been collected since the
- // last time a light sensor reading was accepted.
- private int mRecentLightSamples;
-
- // The moving average of recent light sensor values.
- private float mRecentLightAverage;
-
- // True if recent light samples are getting brighter than the previous
- // stable light measurement.
- private boolean mRecentLightBrightening;
-
- // The time constant to use for filtering based on whether the
- // light appears to be brightening or dimming.
- private long mRecentLightTimeConstant;
+ // The time when the ambient lux was last brightened or darkened.
+ private long mLastAmbientBrightenTime;
+ private long mLastAmbientDarkenTime;
// The most recent light sample.
- private float mLastLightSample;
+ private float mLastObservedLux;
// The time of the most light recent sample.
- private long mLastLightSampleTime;
+ private long mLastObservedLuxTime;
- // The time when we accumulated the first recent light sample into mRecentLightSamples.
- private long mFirstRecentLightSampleTime;
+ // The number of light samples collected since the light sensor was enabled.
+ private int mRecentLightSamples;
- // The upcoming debounce light sensor time.
- // This is only valid when mLightMeasurementValue && mRecentLightSamples >= 1.
- private long mPendingLightSensorDebounceTime;
+ // The long-term and short-term filtered light measurements.
+ private float mRecentShortTermAverageLux;
+ private float mRecentLongTermAverageLux;
// The screen brightness level that has been chosen by the auto-brightness
// algorithm. The actual brightness should ramp towards this value.
@@ -345,12 +334,11 @@
* Creates the display power controller.
*/
public DisplayPowerController(Looper looper, Context context, Notifier notifier,
- LightsService lights, TwilightService twilight, SuspendBlocker suspendBlocker,
+ LightsService lights, TwilightService twilight,
DisplayBlanker displayBlanker,
Callbacks callbacks, Handler callbackHandler) {
mHandler = new DisplayControllerHandler(looper);
mNotifier = notifier;
- mSuspendBlocker = suspendBlocker;
mDisplayBlanker = displayBlanker;
mCallbacks = callbacks;
mCallbackHandler = callbackHandler;
@@ -519,14 +507,10 @@
}
private void initialize() {
- final Executor executor = AsyncTask.THREAD_POOL_EXECUTOR;
Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
mPowerState = new DisplayPowerState(
- new ElectronBeam(display),
- new PhotonicModulator(executor,
- mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT),
- mSuspendBlocker),
- mDisplayBlanker);
+ new ElectronBeam(display), mDisplayBlanker,
+ mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT));
mElectronBeamOnAnimator = ObjectAnimator.ofFloat(
mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 0.0f, 1.0f);
@@ -873,7 +857,8 @@
} else {
if (mLightSensorEnabled) {
mLightSensorEnabled = false;
- mLightMeasurementValid = false;
+ mAmbientLuxValid = false;
+ mRecentLightSamples = 0;
mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
mSensorManager.unregisterListener(mLightSensorListener);
}
@@ -884,114 +869,99 @@
}
private void handleLightSensorEvent(long time, float lux) {
- // Take the first few readings during the warm-up period and apply them
- // immediately without debouncing.
- if (!mLightMeasurementValid
- || (time - mLightSensorEnableTime) < mLightSensorWarmUpTimeConfig) {
- mLightMeasurement = lux;
- mLightMeasurementValid = true;
- mRecentLightSamples = 0;
- updateAutoBrightness(true);
- }
-
- // Update our moving average.
- if (lux != mLightMeasurement && (mRecentLightSamples == 0
- || (lux < mLightMeasurement && mRecentLightBrightening)
- || (lux > mLightMeasurement && !mRecentLightBrightening))) {
- // If the newest light sample doesn't seem to be going in the
- // same general direction as recent samples, then start over.
- setRecentLight(time, lux, lux > mLightMeasurement);
- } else if (mRecentLightSamples >= 1) {
- // Add the newest light sample to the moving average.
- accumulateRecentLight(time, lux);
- }
- if (DEBUG) {
- Slog.d(TAG, "handleLightSensorEvent: lux=" + lux
- + ", mLightMeasurementValid=" + mLightMeasurementValid
- + ", mLightMeasurement=" + mLightMeasurement
- + ", mRecentLightSamples=" + mRecentLightSamples
- + ", mRecentLightAverage=" + mRecentLightAverage
- + ", mRecentLightBrightening=" + mRecentLightBrightening
- + ", mRecentLightTimeConstant=" + mRecentLightTimeConstant
- + ", mFirstRecentLightSampleTime="
- + TimeUtils.formatUptime(mFirstRecentLightSampleTime)
- + ", mPendingLightSensorDebounceTime="
- + TimeUtils.formatUptime(mPendingLightSensorDebounceTime));
- }
-
- // Debounce.
- mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
- debounceLightSensor();
- }
-
- private void setRecentLight(long time, float lux, boolean brightening) {
- mRecentLightBrightening = brightening;
- mRecentLightTimeConstant = brightening ?
- BRIGHTENING_LIGHT_TIME_CONSTANT : DIMMING_LIGHT_TIME_CONSTANT;
- mRecentLightSamples = 1;
- mRecentLightAverage = lux;
- mLastLightSample = lux;
- mLastLightSampleTime = time;
- mFirstRecentLightSampleTime = time;
- mPendingLightSensorDebounceTime = time + (brightening ?
- BRIGHTENING_LIGHT_DEBOUNCE : DIMMING_LIGHT_DEBOUNCE);
- }
-
- private void accumulateRecentLight(long time, float lux) {
- final long timeDelta = time - mLastLightSampleTime;
+ // Update our filters.
mRecentLightSamples += 1;
- mRecentLightAverage += (lux - mRecentLightAverage) *
- timeDelta / (mRecentLightTimeConstant + timeDelta);
- mLastLightSample = lux;
- mLastLightSampleTime = time;
+ if (mRecentLightSamples == 1) {
+ mRecentShortTermAverageLux = lux;
+ mRecentLongTermAverageLux = lux;
+ } else {
+ final long timeDelta = time - mLastObservedLuxTime;
+ mRecentShortTermAverageLux += (lux - mRecentShortTermAverageLux)
+ * timeDelta / (SHORT_TERM_AVERAGE_LIGHT_TIME_CONSTANT + timeDelta);
+ mRecentLongTermAverageLux += (lux - mRecentLongTermAverageLux)
+ * timeDelta / (LONG_TERM_AVERAGE_LIGHT_TIME_CONSTANT + timeDelta);
+ }
+
+ // Remember this sample value.
+ mLastObservedLux = lux;
+ mLastObservedLuxTime = time;
+
+ // Update the ambient lux level.
+ mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
+ updateAmbientLux(time);
}
- private void debounceLightSensor() {
- if (mLightMeasurementValid && mRecentLightSamples >= 1) {
- final long now = SystemClock.uptimeMillis();
- if (mPendingLightSensorDebounceTime <= now) {
- accumulateRecentLight(now, mLastLightSample);
- mLightMeasurement = mRecentLightAverage;
+ private void updateAmbientLux(long time) {
+ // If the light sensor was just turned on then immediately update our initial
+ // estimate of the current ambient light level.
+ if (!mAmbientLuxValid
+ || (time - mLightSensorEnableTime) < mLightSensorWarmUpTimeConfig) {
+ if (DEBUG) {
+ Slog.d(TAG, "updateAmbientLux: Initializing, "
+ + "mAmbientLux=" + (mAmbientLuxValid ? mAmbientLux : -1)
+ + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
+ + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux);
+ }
+ mAmbientLux = mRecentShortTermAverageLux;
+ mAmbientLuxValid = true;
+ mLastAmbientBrightenTime = time;
+ mLastAmbientDarkenTime = time;
+ updateAutoBrightness(true);
+ return;
+ }
+ // Determine whether the ambient environment appears to be brightening.
+ float minAmbientLux = mAmbientLux * (1.0f + BRIGHTENING_LIGHT_HYSTERESIS);
+ if (mRecentShortTermAverageLux > minAmbientLux
+ && mRecentLongTermAverageLux > minAmbientLux) {
+ long debounceTime = mLastAmbientDarkenTime + BRIGHTENING_LIGHT_DEBOUNCE;
+ if (time >= debounceTime) {
if (DEBUG) {
- Slog.d(TAG, "debounceLightSensor: Accepted new measurement "
- + mLightMeasurement + " after "
- + (now - mFirstRecentLightSampleTime) + " ms based on "
- + mRecentLightSamples + " recent samples.");
+ Slog.d(TAG, "updateAmbientLux: Brightened: "
+ + "mAmbientLux=" + mAmbientLux
+ + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
+ + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux);
}
-
+ mLastAmbientBrightenTime = time;
+ mAmbientLux = mRecentShortTermAverageLux;
updateAutoBrightness(true);
-
- // Now that we have debounced the light sensor data, we have the
- // option of either leaving the sensor in a debounced state or
- // restarting the debounce cycle by setting mRecentLightSamples to 0.
- //
- // If we leave the sensor debounced, then new average light measurements
- // may be accepted immediately as long as they are trending in the same
- // direction as they were before. If the measurements start
- // jittering or trending in the opposite direction then the debounce
- // cycle will automatically be restarted. The benefit is that the
- // auto-brightness control can be more responsive to changes over a
- // broad range.
- //
- // For now, we choose to be more responsive and leave the following line
- // commented out.
- //
- // mRecentLightSamples = 0;
} else {
- Message msg = mHandler.obtainMessage(MSG_LIGHT_SENSOR_DEBOUNCED);
- msg.setAsynchronous(true);
- mHandler.sendMessageAtTime(msg, mPendingLightSensorDebounceTime);
+ mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, debounceTime);
+ }
+ return;
+ }
+
+ // Determine whether the ambient environment appears to be darkening.
+ float maxAmbientLux = mAmbientLux * (1.0f - DARKENING_LIGHT_HYSTERESIS);
+ if (mRecentShortTermAverageLux < maxAmbientLux
+ && mRecentLongTermAverageLux < maxAmbientLux) {
+ long debounceTime = mLastAmbientBrightenTime + DARKENING_LIGHT_DEBOUNCE;
+ if (time >= debounceTime) {
+ if (DEBUG) {
+ Slog.d(TAG, "updateAmbientLux: Darkened: "
+ + "mAmbientLux=" + mAmbientLux
+ + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
+ + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux);
+ }
+ mLastAmbientDarkenTime = time;
+ mAmbientLux = mRecentShortTermAverageLux;
+ updateAutoBrightness(true);
+ } else {
+ mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, debounceTime);
}
}
}
+ private void debounceLightSensor() {
+ updateAmbientLux(SystemClock.uptimeMillis());
+ }
+
private void updateAutoBrightness(boolean sendUpdate) {
- if (!mLightMeasurementValid) {
+ if (!mAmbientLuxValid) {
return;
}
- float value = mScreenAutoBrightnessSpline.interpolate(mLightMeasurement);
+ float value = mScreenAutoBrightnessSpline.interpolate(mAmbientLux);
float gamma = 1.0f;
if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT
@@ -1031,7 +1001,7 @@
}
int newScreenAutoBrightness = clampScreenBrightness(
- (int)Math.round(value * PowerManager.BRIGHTNESS_ON));
+ Math.round(value * PowerManager.BRIGHTNESS_ON));
if (mScreenAutoBrightness != newScreenAutoBrightness) {
if (DEBUG) {
Slog.d(TAG, "updateAutoBrightness: mScreenAutoBrightness="
@@ -1152,19 +1122,18 @@
pw.println(" mLightSensorEnabled=" + mLightSensorEnabled);
pw.println(" mLightSensorEnableTime="
+ TimeUtils.formatUptime(mLightSensorEnableTime));
- pw.println(" mLightMeasurement=" + mLightMeasurement);
- pw.println(" mLightMeasurementValid=" + mLightMeasurementValid);
- pw.println(" mLastLightSample=" + mLastLightSample);
- pw.println(" mLastLightSampleTime="
- + TimeUtils.formatUptime(mLastLightSampleTime));
+ pw.println(" mAmbientLux=" + mAmbientLux);
+ pw.println(" mAmbientLuxValid=" + mAmbientLuxValid);
+ pw.println(" mLastAmbientBrightenTime="
+ + TimeUtils.formatUptime(mLastAmbientBrightenTime));
+ pw.println(" mLastAmbientDimTime="
+ + TimeUtils.formatUptime(mLastAmbientDarkenTime));
+ pw.println(" mLastObservedLux=" + mLastObservedLux);
+ pw.println(" mLastObservedLuxTime="
+ + TimeUtils.formatUptime(mLastObservedLuxTime));
pw.println(" mRecentLightSamples=" + mRecentLightSamples);
- pw.println(" mRecentLightAverage=" + mRecentLightAverage);
- pw.println(" mRecentLightBrightening=" + mRecentLightBrightening);
- pw.println(" mRecentLightTimeConstant=" + mRecentLightTimeConstant);
- pw.println(" mFirstRecentLightSampleTime="
- + TimeUtils.formatUptime(mFirstRecentLightSampleTime));
- pw.println(" mPendingLightSensorDebounceTime="
- + TimeUtils.formatUptime(mPendingLightSensorDebounceTime));
+ pw.println(" mRecentShortTermAverageLux=" + mRecentShortTermAverageLux);
+ pw.println(" mRecentLongTermAverageLux=" + mRecentLongTermAverageLux);
pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness);
pw.println(" mUsingScreenAutoBrightness=" + mUsingScreenAutoBrightness);
pw.println(" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma);
diff --git a/services/java/com/android/server/power/DisplayPowerState.java b/services/java/com/android/server/power/DisplayPowerState.java
index fdfcacc..6bb7ec5 100644
--- a/services/java/com/android/server/power/DisplayPowerState.java
+++ b/services/java/com/android/server/power/DisplayPowerState.java
@@ -16,6 +16,10 @@
package com.android.server.power;
+import com.android.server.LightsService;
+
+import android.os.AsyncTask;
+import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.util.FloatProperty;
@@ -26,47 +30,55 @@
import java.io.PrintWriter;
/**
- * Represents the current display power state and realizes it.
- *
+ * Controls the display power state.
+ * <p>
* This component is similar in nature to a {@link View} except that it describes
* the properties of a display. When properties are changed, the component
- * invalidates itself and posts a callback to the {@link Choreographer} to
- * apply the changes. This mechanism enables the display power state to be
- * animated smoothly by the animation framework.
- *
+ * invalidates itself and posts a callback to apply the changes in a consistent order.
+ * This mechanism enables multiple properties of the display power state to be animated
+ * together smoothly by the animation framework. Some of the work to blank or unblank
+ * the display is done on a separate thread to avoid blocking the looper.
+ * </p><p>
* This component must only be created or accessed by the {@link Looper} thread
* that belongs to the {@link DisplayPowerController}.
- *
+ * </p><p>
* We don't need to worry about holding a suspend blocker here because the
- * {@link DisplayPowerController} does that for us whenever there is a pending invalidate.
+ * {@link PowerManagerService} does that for us whenever there is a change
+ * in progress.
+ * </p>
*/
final class DisplayPowerState {
private static final String TAG = "DisplayPowerState";
private static boolean DEBUG = false;
- private static final int DIRTY_SCREEN_ON = 1 << 0;
- private static final int DIRTY_ELECTRON_BEAM = 1 << 1;
- private static final int DIRTY_BRIGHTNESS = 1 << 2;
-
+ private final Handler mHandler;
private final Choreographer mChoreographer;
private final ElectronBeam mElectronBeam;
- private final PhotonicModulator mPhotonicModulator;
private final DisplayBlanker mDisplayBlanker;
+ private final LightsService.Light mBacklight;
+ private final PhotonicModulator mPhotonicModulator;
- private int mDirty;
private boolean mScreenOn;
- private float mElectronBeamLevel;
private int mScreenBrightness;
+ private boolean mScreenReady;
+ private boolean mScreenUpdatePending;
+
+ private boolean mElectronBeamPrepared;
+ private float mElectronBeamLevel;
+ private boolean mElectronBeamReady;
+ private boolean mElectronBeamDrawPending;
private Runnable mCleanListener;
public DisplayPowerState(ElectronBeam electronBean,
- PhotonicModulator photonicModulator, DisplayBlanker displayBlanker) {
+ DisplayBlanker displayBlanker, LightsService.Light backlight) {
+ mHandler = new Handler(true /*async*/);
mChoreographer = Choreographer.getInstance();
mElectronBeam = electronBean;
- mPhotonicModulator = photonicModulator;
mDisplayBlanker = displayBlanker;
+ mBacklight = backlight;
+ mPhotonicModulator = new PhotonicModulator();
// At boot time, we know that the screen is on and the electron beam
// animation is not playing. We don't know the screen's brightness though,
@@ -75,9 +87,12 @@
// will reset the brightness to a new level immediately before the changes
// actually have a chance to be applied.
mScreenOn = true;
- mElectronBeamLevel = 1.0f;
mScreenBrightness = PowerManager.BRIGHTNESS_ON;
- invalidate(DIRTY_BRIGHTNESS);
+ scheduleScreenUpdate();
+
+ mElectronBeamPrepared = false;
+ mElectronBeamLevel = 1.0f;
+ mElectronBeamReady = true;
}
public static final FloatProperty<DisplayPowerState> ELECTRON_BEAM_LEVEL =
@@ -116,7 +131,8 @@
}
mScreenOn = on;
- invalidate(DIRTY_SCREEN_ON);
+ mScreenReady = false;
+ scheduleScreenUpdate();
}
}
@@ -128,6 +144,32 @@
}
/**
+ * Sets the display brightness.
+ *
+ * @param brightness The brightness, ranges from 0 (minimum / off) to 255 (brightest).
+ */
+ public void setScreenBrightness(int brightness) {
+ if (mScreenBrightness != brightness) {
+ if (DEBUG) {
+ Slog.d(TAG, "setScreenBrightness: brightness=" + brightness);
+ }
+
+ mScreenBrightness = brightness;
+ if (mScreenOn) {
+ mScreenReady = false;
+ scheduleScreenUpdate();
+ }
+ }
+ }
+
+ /**
+ * Gets the screen brightness.
+ */
+ public int getScreenBrightness() {
+ return mScreenBrightness;
+ }
+
+ /**
* Prepares the electron beam to turn on or off.
* This method should be called before starting an animation because it
* can take a fair amount of time to prepare the electron beam surface.
@@ -136,8 +178,16 @@
* @return True if the electron beam was prepared.
*/
public boolean prepareElectronBeam(int mode) {
- invalidate(DIRTY_ELECTRON_BEAM);
- return mElectronBeam.prepare(mode);
+ if (!mElectronBeam.prepare(mode)) {
+ mElectronBeamPrepared = false;
+ mElectronBeamReady = true;
+ return false;
+ }
+
+ mElectronBeamPrepared = true;
+ mElectronBeamReady = false;
+ scheduleElectronBeamDraw();
+ return true;
}
/**
@@ -145,6 +195,8 @@
*/
public void dismissElectronBeam() {
mElectronBeam.dismiss();
+ mElectronBeamPrepared = false;
+ mElectronBeamReady = true;
}
/**
@@ -167,7 +219,14 @@
}
mElectronBeamLevel = level;
- invalidate(DIRTY_ELECTRON_BEAM);
+ if (mScreenOn) {
+ mScreenReady = false;
+ scheduleScreenUpdate(); // update backlight brightness
+ }
+ if (mElectronBeamPrepared) {
+ mElectronBeamReady = false;
+ scheduleElectronBeamDraw();
+ }
}
}
@@ -179,36 +238,13 @@
}
/**
- * Sets the display brightness.
- *
- * @param brightness The brightness, ranges from 0 (minimum / off) to 255 (brightest).
- */
- public void setScreenBrightness(int brightness) {
- if (mScreenBrightness != brightness) {
- if (DEBUG) {
- Slog.d(TAG, "setScreenBrightness: brightness=" + brightness);
- }
-
- mScreenBrightness = brightness;
- invalidate(DIRTY_BRIGHTNESS);
- }
- }
-
- /**
- * Gets the screen brightness.
- */
- public int getScreenBrightness() {
- return mScreenBrightness;
- }
-
- /**
* Returns true if no properties have been invalidated.
* Otherwise, returns false and promises to invoke the specified listener
* when the properties have all been applied.
* The listener always overrides any previously set listener.
*/
public boolean waitUntilClean(Runnable listener) {
- if (mDirty != 0) {
+ if (!mScreenReady || !mElectronBeamReady) {
mCleanListener = listener;
return false;
} else {
@@ -220,58 +256,159 @@
public void dump(PrintWriter pw) {
pw.println();
pw.println("Display Power State:");
- pw.println(" mDirty=" + Integer.toHexString(mDirty));
pw.println(" mScreenOn=" + mScreenOn);
pw.println(" mScreenBrightness=" + mScreenBrightness);
+ pw.println(" mScreenReady=" + mScreenReady);
+ pw.println(" mScreenUpdatePending=" + mScreenUpdatePending);
+ pw.println(" mElectronBeamPrepared=" + mElectronBeamPrepared);
pw.println(" mElectronBeamLevel=" + mElectronBeamLevel);
+ pw.println(" mElectronBeamReady=" + mElectronBeamReady);
+ pw.println(" mElectronBeamDrawPending=" + mElectronBeamDrawPending);
+ mPhotonicModulator.dump(pw);
mElectronBeam.dump(pw);
}
- private void invalidate(int dirty) {
- if (mDirty == 0) {
+ private void scheduleScreenUpdate() {
+ if (!mScreenUpdatePending) {
+ mScreenUpdatePending = true;
+ postScreenUpdateThreadSafe();
+ }
+ }
+
+ private void postScreenUpdateThreadSafe() {
+ mHandler.removeCallbacks(mScreenUpdateRunnable);
+ mHandler.post(mScreenUpdateRunnable);
+ }
+
+ private void scheduleElectronBeamDraw() {
+ if (!mElectronBeamDrawPending) {
+ mElectronBeamDrawPending = true;
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL,
- mTraversalRunnable, null);
- }
-
- mDirty |= dirty;
- }
-
- private void apply() {
- if (mDirty != 0) {
- if ((mDirty & DIRTY_SCREEN_ON) != 0 && !mScreenOn) {
- mPhotonicModulator.setBrightness(0, true /*sync*/);
- mDisplayBlanker.blankAllDisplays();
- }
-
- if ((mDirty & DIRTY_ELECTRON_BEAM) != 0) {
- mElectronBeam.draw(mElectronBeamLevel);
- }
-
- if ((mDirty & DIRTY_SCREEN_ON) != 0 && mScreenOn) {
- mDisplayBlanker.unblankAllDisplays();
- }
-
- if ((mDirty & (DIRTY_BRIGHTNESS | DIRTY_SCREEN_ON | DIRTY_ELECTRON_BEAM)) != 0
- && mScreenOn) {
- mPhotonicModulator.setBrightness(
- (int)(mScreenBrightness * mElectronBeamLevel), false /*sync*/);
- }
-
- mDirty = 0;
-
- if (mCleanListener != null) {
- mCleanListener.run();
- }
+ mElectronBeamDrawRunnable, null);
}
}
- private final Runnable mTraversalRunnable = new Runnable() {
+ private void invokeCleanListenerIfNeeded() {
+ final Runnable listener = mCleanListener;
+ if (listener != null && mScreenReady && mElectronBeamReady) {
+ mCleanListener = null;
+ listener.run();
+ }
+ }
+
+ private final Runnable mScreenUpdateRunnable = new Runnable() {
@Override
public void run() {
- if (mDirty != 0) {
- apply();
+ mScreenUpdatePending = false;
+
+ if (mPhotonicModulator.setState(mScreenOn,
+ mScreenOn ? (int)(mScreenBrightness * mElectronBeamLevel) : 0)) {
+ mScreenReady = true;
+ invokeCleanListenerIfNeeded();
}
}
};
+
+ private final Runnable mElectronBeamDrawRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mElectronBeamDrawPending = false;
+
+ if (mElectronBeamPrepared) {
+ mElectronBeam.draw(mElectronBeamLevel);
+ }
+
+ mElectronBeamReady = true;
+ invokeCleanListenerIfNeeded();
+ }
+ };
+
+ /**
+ * Updates the state of the screen and backlight asynchronously on a separate thread.
+ */
+ private final class PhotonicModulator {
+ private static final boolean INITIAL_SCREEN_ON = false; // unknown, assume off
+ private static final int INITIAL_BACKLIGHT = -1; // unknown
+
+ private final Object mLock = new Object();
+
+ private boolean mPendingOn = INITIAL_SCREEN_ON;
+ private int mPendingBacklight = INITIAL_BACKLIGHT;
+ private boolean mActualOn = INITIAL_SCREEN_ON;
+ private int mActualBacklight = INITIAL_BACKLIGHT;
+ private boolean mChangeInProgress;
+
+ public boolean setState(boolean on, int backlight) {
+ synchronized (mLock) {
+ if (on != mPendingOn || backlight != mPendingBacklight) {
+ if (DEBUG) {
+ Slog.d(TAG, "Requesting new screen state: on=" + on
+ + ", backlight=" + backlight);
+ }
+
+ mPendingOn = on;
+ mPendingBacklight = backlight;
+
+ if (!mChangeInProgress) {
+ mChangeInProgress = true;
+ AsyncTask.THREAD_POOL_EXECUTOR.execute(mTask);
+ }
+ }
+ return mChangeInProgress;
+ }
+ }
+
+ public void dump(PrintWriter pw) {
+ pw.println();
+ pw.println("Photonic Modulator State:");
+ pw.println(" mPendingOn=" + mPendingOn);
+ pw.println(" mPendingBacklight=" + mPendingBacklight);
+ pw.println(" mActualOn=" + mActualOn);
+ pw.println(" mActualBacklight=" + mActualBacklight);
+ pw.println(" mChangeInProgress=" + mChangeInProgress);
+ }
+
+ private final Runnable mTask = new Runnable() {
+ @Override
+ public void run() {
+ // Apply pending changes until done.
+ for (;;) {
+ final boolean on;
+ final boolean onChanged;
+ final int backlight;
+ final boolean backlightChanged;
+ synchronized (mLock) {
+ on = mPendingOn;
+ onChanged = (on != mActualOn);
+ backlight = mPendingBacklight;
+ backlightChanged = (backlight != mActualBacklight);
+ if (!onChanged && !backlightChanged) {
+ mChangeInProgress = false;
+ break;
+ }
+ mActualOn = on;
+ mActualBacklight = backlight;
+ }
+
+ if (DEBUG) {
+ Slog.d(TAG, "Updating screen state: on=" + on
+ + ", backlight=" + backlight);
+ }
+ if (onChanged && on) {
+ mDisplayBlanker.unblankAllDisplays();
+ }
+ if (backlightChanged) {
+ mBacklight.setBrightness(backlight);
+ }
+ if (onChanged && !on) {
+ mDisplayBlanker.blankAllDisplays();
+ }
+ }
+
+ // Let the outer class know that all changes have been applied.
+ postScreenUpdateThreadSafe();
+ }
+ };
+ }
}
diff --git a/services/java/com/android/server/power/PhotonicModulator.java b/services/java/com/android/server/power/PhotonicModulator.java
deleted file mode 100644
index c9b5d90..0000000
--- a/services/java/com/android/server/power/PhotonicModulator.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.server.power;
-
-import com.android.server.LightsService;
-
-import java.util.concurrent.Executor;
-
-/**
- * Sets the value of a light asynchronously.
- *
- * This is done to avoid blocking the looper on devices for which
- * setting the backlight brightness is especially slow.
- */
-final class PhotonicModulator {
- private static final int UNKNOWN_LIGHT_VALUE = -1;
-
- private final Object mLock = new Object();
-
- private final LightsService.Light mLight;
- private final Executor mExecutor;
- private final SuspendBlocker mSuspendBlocker;
-
- private boolean mPendingChange;
- private int mPendingLightValue;
- private int mActualLightValue;
-
- public PhotonicModulator(Executor executor, LightsService.Light light,
- SuspendBlocker suspendBlocker) {
- mExecutor = executor;
- mLight = light;
- mSuspendBlocker = suspendBlocker;
- mPendingLightValue = UNKNOWN_LIGHT_VALUE;
- mActualLightValue = UNKNOWN_LIGHT_VALUE;
- }
-
- /**
- * Sets the backlight brightness, synchronously or asynchronously.
- *
- * @param lightValue The new light value, from 0 to 255.
- * @param sync If true, waits for the brightness change to complete before returning.
- */
- public void setBrightness(int lightValue, boolean sync) {
- synchronized (mLock) {
- if (lightValue != mPendingLightValue) {
- mPendingLightValue = lightValue;
- if (!mPendingChange) {
- mPendingChange = true;
- mSuspendBlocker.acquire();
- mExecutor.execute(mTask);
- }
- }
- if (sync) {
- while (mPendingChange) {
- try {
- mLock.wait();
- } catch (InterruptedException ex) {
- // ignore it
- }
- }
- }
- }
- }
-
- private final Runnable mTask = new Runnable() {
- @Override
- public void run() {
- for (;;) {
- final int newLightValue;
- synchronized (mLock) {
- newLightValue = mPendingLightValue;
- if (newLightValue == mActualLightValue) {
- mSuspendBlocker.release();
- mPendingChange = false;
- mLock.notifyAll();
- return;
- }
- mActualLightValue = newLightValue;
- }
- mLight.setBrightness(newLightValue);
- }
- }
- };
-}
diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java
index 4e692a2..8650192 100644
--- a/services/java/com/android/server/power/PowerManagerService.java
+++ b/services/java/com/android/server/power/PowerManagerService.java
@@ -107,6 +107,8 @@
private static final int DIRTY_PROXIMITY_POSITIVE = 1 << 9;
// Dirty bit: screen on blocker state became held or unheld
private static final int DIRTY_SCREEN_ON_BLOCKER_RELEASED = 1 << 10;
+ // Dirty bit: dock state changed
+ private static final int DIRTY_DOCK_STATE = 1 << 11;
// Wakefulness: The device is asleep and can only be awoken by a call to wakeUp().
// The screen should be off or in the process of being turned off by the display controller.
@@ -269,18 +271,33 @@
// draining faster than it is charging and the user activity timeout has expired.
private int mBatteryLevelWhenDreamStarted;
+ // The current dock state.
+ private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
+
// True if the device should wake up when plugged or unplugged.
private boolean mWakeUpWhenPluggedOrUnpluggedConfig;
// True if dreams are supported on this device.
private boolean mDreamsSupportedConfig;
+ // Default value for dreams enabled
+ private boolean mDreamsEnabledByDefaultConfig;
+
+ // Default value for dreams activate-on-sleep
+ private boolean mDreamsActivatedOnSleepByDefaultConfig;
+
+ // Default value for dreams activate-on-dock
+ private boolean mDreamsActivatedOnDockByDefaultConfig;
+
// True if dreams are enabled by the user.
private boolean mDreamsEnabledSetting;
// True if dreams should be activated on sleep.
private boolean mDreamsActivateOnSleepSetting;
+ // True if dreams should be activated on dock.
+ private boolean mDreamsActivateOnDockSetting;
+
// The screen off timeout setting value in milliseconds.
private int mScreenOffTimeoutSetting;
@@ -416,7 +433,6 @@
// own handler thread.
mDisplayPowerController = new DisplayPowerController(mHandler.getLooper(),
mContext, mNotifier, mLightsService, twilight,
- createSuspendBlockerLocked("PowerManagerService.Display"),
mDisplayBlanker, mDisplayPowerControllerCallbacks, mHandler);
mSettingsObserver = new SettingsObserver(mHandler);
@@ -440,6 +456,10 @@
filter.addAction(Intent.ACTION_USER_SWITCHED);
mContext.registerReceiver(new UserSwitchedReceiver(), filter, null, mHandler);
+ filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_DOCK_EVENT);
+ mContext.registerReceiver(new DockReceiver(), filter, null, mHandler);
+
// Register for settings changes.
final ContentResolver resolver = mContext.getContentResolver();
resolver.registerContentObserver(Settings.Secure.getUriFor(
@@ -448,6 +468,9 @@
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP),
false, mSettingsObserver, UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.Secure.getUriFor(
+ Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK),
+ false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.SCREEN_OFF_TIMEOUT),
false, mSettingsObserver, UserHandle.USER_ALL);
@@ -475,17 +498,29 @@
mWakeUpWhenPluggedOrUnpluggedConfig = resources.getBoolean(
com.android.internal.R.bool.config_unplugTurnsOnScreen);
mDreamsSupportedConfig = resources.getBoolean(
- com.android.internal.R.bool.config_enableDreams);
+ com.android.internal.R.bool.config_dreamsSupported);
+ mDreamsEnabledByDefaultConfig = resources.getBoolean(
+ com.android.internal.R.bool.config_dreamsEnabledByDefault);
+ mDreamsActivatedOnSleepByDefaultConfig = resources.getBoolean(
+ com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault);
+ mDreamsActivatedOnDockByDefaultConfig = resources.getBoolean(
+ com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
}
private void updateSettingsLocked() {
final ContentResolver resolver = mContext.getContentResolver();
mDreamsEnabledSetting = (Settings.Secure.getIntForUser(resolver,
- Settings.Secure.SCREENSAVER_ENABLED, 0,
+ Settings.Secure.SCREENSAVER_ENABLED,
+ mDreamsEnabledByDefaultConfig ? 1 : 0,
UserHandle.USER_CURRENT) != 0);
mDreamsActivateOnSleepSetting = (Settings.Secure.getIntForUser(resolver,
- Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 0,
+ Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
+ mDreamsActivatedOnSleepByDefaultConfig ? 1 : 0,
+ UserHandle.USER_CURRENT) != 0);
+ mDreamsActivateOnDockSetting = (Settings.Secure.getIntForUser(resolver,
+ Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
+ mDreamsActivatedOnDockByDefaultConfig ? 1 : 0,
UserHandle.USER_CURRENT) != 0);
mScreenOffTimeoutSetting = Settings.System.getIntForUser(resolver,
Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT,
@@ -1339,13 +1374,14 @@
private boolean updateWakefulnessLocked(int dirty) {
boolean changed = false;
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED
- | DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE)) != 0) {
+ | DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE
+ | DIRTY_DOCK_STATE)) != 0) {
if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakefulnessLocked: Bed time...");
}
final long time = SystemClock.uptimeMillis();
- if (mDreamsActivateOnSleepSetting) {
+ if (shouldNapAtBedTimeLocked()) {
changed = napNoUpdateLocked(time);
} else {
changed = goToSleepNoUpdateLocked(time,
@@ -1357,6 +1393,16 @@
}
/**
+ * Returns true if the device should automatically nap and start dreaming when the user
+ * activity timeout has expired and it's bedtime.
+ */
+ private boolean shouldNapAtBedTimeLocked() {
+ return mDreamsActivateOnSleepSetting
+ || (mDreamsActivateOnDockSetting
+ && mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED);
+ }
+
+ /**
* Returns true if the device should go to sleep now.
* Also used when exiting a dream to determine whether we should go back
* to being fully awake or else go to sleep for good.
@@ -2124,6 +2170,7 @@
pw.println(" mPlugType=" + mPlugType);
pw.println(" mBatteryLevel=" + mBatteryLevel);
pw.println(" mBatteryLevelWhenDreamStarted=" + mBatteryLevelWhenDreamStarted);
+ pw.println(" mDockState=" + mDockState);
pw.println(" mStayOn=" + mStayOn);
pw.println(" mProximityPositive=" + mProximityPositive);
pw.println(" mBootCompleted=" + mBootCompleted);
@@ -2149,6 +2196,7 @@
pw.println(" mDreamsSupportedConfig=" + mDreamsSupportedConfig);
pw.println(" mDreamsEnabledSetting=" + mDreamsEnabledSetting);
pw.println(" mDreamsActivateOnSleepSetting=" + mDreamsActivateOnSleepSetting);
+ pw.println(" mDreamsActivateOnDockSetting=" + mDreamsActivateOnDockSetting);
pw.println(" mScreenOffTimeoutSetting=" + mScreenOffTimeoutSetting);
pw.println(" mMaximumScreenOffTimeoutFromDeviceAdmin="
+ mMaximumScreenOffTimeoutFromDeviceAdmin + " (enforced="
@@ -2267,6 +2315,21 @@
}
}
+ private final class DockReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ synchronized (mLock) {
+ int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
+ Intent.EXTRA_DOCK_STATE_UNDOCKED);
+ if (mDockState != dockState) {
+ mDockState = dockState;
+ mDirty |= DIRTY_DOCK_STATE;
+ updatePowerStateLocked();
+ }
+ }
+ }
+ }
+
private final class SettingsObserver extends ContentObserver {
public SettingsObserver(Handler handler) {
super(handler);
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
index 3898ebc..68cdbfc 100644
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -66,14 +66,17 @@
int mBaseDisplayWidth = 0;
int mBaseDisplayHeight = 0;
int mBaseDisplayDensity = 0;
- final DisplayInfo mDisplayInfo = new DisplayInfo();
- final Display mDisplay;
+ private final DisplayInfo mDisplayInfo = new DisplayInfo();
+ private final Display mDisplay;
// Accessed directly by all users.
boolean layoutNeeded;
int pendingLayoutChanges;
final boolean isDefaultDisplay;
+ /**
+ * @param display May not be null.
+ */
DisplayContent(Display display) {
mDisplay = display;
mDisplayId = display.getDisplayId();
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
index 545fce5..72fc180 100644
--- a/services/java/com/android/server/wm/DragState.java
+++ b/services/java/com/android/server/wm/DragState.java
@@ -190,9 +190,11 @@
}
final WindowList windows = mService.getWindowListLocked(mDisplay);
- final int N = windows.size();
- for (int i = 0; i < N; i++) {
- sendDragStartedLw(windows.get(i), touchX, touchY, mDataDescription);
+ if (windows != null) {
+ final int N = windows.size();
+ for (int i = 0; i < N; i++) {
+ sendDragStartedLw(windows.get(i), touchX, touchY, mDataDescription);
+ }
}
}
@@ -393,6 +395,9 @@
final int y = (int) yf;
final WindowList windows = mService.getWindowListLocked(mDisplay);
+ if (windows == null) {
+ return null;
+ }
final int N = windows.size();
for (int i = N - 1; i >= 0; i--) {
WindowState child = windows.get(i);
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index fa450ae..1492b18 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -2092,6 +2092,11 @@
throw new IllegalStateException("Display has not been initialialized");
}
+ final DisplayContent displayContent = getDisplayContentLocked(displayId);
+ if (displayContent == null) {
+ return WindowManagerGlobal.ADD_INVALID_DISPLAY;
+ }
+
if (mWindowMap.containsKey(client.asBinder())) {
Slog.w(TAG, "Window " + client + " is already added");
return WindowManagerGlobal.ADD_DUPLICATE_ADD;
@@ -2174,7 +2179,6 @@
}
}
- final DisplayContent displayContent = getDisplayContentLocked(displayId);
win = new WindowState(this, session, client, token,
attachedWindow, seq, attrs, viewVisibility, displayContent);
if (win.mDeathRecipient == null) {
@@ -2240,6 +2244,14 @@
adjustWallpaperWindowsLocked();
} else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
adjustWallpaperWindowsLocked();
+ } else if (mWallpaperTarget != null
+ && mWallpaperTarget.mLayer >= win.mBaseLayer) {
+ // If there is currently a wallpaper being shown, and
+ // the base layer of the new window is below the current
+ // layer of the target window, then adjust the wallpaper.
+ // This is to avoid a new window being placed between the
+ // wallpaper and its target.
+ adjustWallpaperWindowsLocked();
}
}
@@ -2420,6 +2432,7 @@
final WindowList windows = win.getWindowList();
windows.remove(win);
mPendingRemove.remove(win);
+ mResizingWindows.remove(win);
mWindowsChanged = true;
if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
@@ -3384,8 +3397,15 @@
} else {
// Exiting app
if (scaleUp) {
- // noop animation
- a = new AlphaAnimation(1, 0);
+ if (transit == WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN) {
+ // Fade out while bringing up selected activity. This keeps the
+ // current activity from showing through a launching wallpaper
+ // activity.
+ a = new AlphaAnimation(1, 0);
+ } else {
+ // noop animation
+ a = new AlphaAnimation(1, 1);
+ }
a.setDuration(duration);
} else {
float scaleW = thumbWidth / displayInfo.appWidth;
@@ -5704,6 +5724,7 @@
* @param width the width of the target bitmap
* @param height the height of the target bitmap
*/
+ @Override
public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height) {
if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
"screenshotApplications()")) {
@@ -5723,6 +5744,9 @@
long ident = Binder.clearCallingIdentity();
final DisplayContent displayContent = getDisplayContentLocked(displayId);
+ if (displayContent == null) {
+ return null;
+ }
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
dw = displayInfo.logicalWidth;
dh = displayInfo.logicalHeight;
@@ -6465,6 +6489,7 @@
return success;
}
+ @Override
public void addDisplayContentChangeListener(int displayId,
IDisplayContentChangeListener listener) {
if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
@@ -6473,14 +6498,17 @@
}
synchronized(mWindowMap) {
DisplayContent displayContent = getDisplayContentLocked(displayId);
- if (displayContent.mDisplayContentChangeListeners == null) {
- displayContent.mDisplayContentChangeListeners =
- new RemoteCallbackList<IDisplayContentChangeListener>();
- displayContent.mDisplayContentChangeListeners.register(listener);
+ if (displayContent != null) {
+ if (displayContent.mDisplayContentChangeListeners == null) {
+ displayContent.mDisplayContentChangeListeners =
+ new RemoteCallbackList<IDisplayContentChangeListener>();
+ displayContent.mDisplayContentChangeListeners.register(listener);
+ }
}
}
}
+ @Override
public void removeDisplayContentChangeListener(int displayId,
IDisplayContentChangeListener listener) {
if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
@@ -6489,11 +6517,13 @@
}
synchronized(mWindowMap) {
DisplayContent displayContent = getDisplayContentLocked(displayId);
- if (displayContent.mDisplayContentChangeListeners != null) {
- displayContent.mDisplayContentChangeListeners.unregister(listener);
- if (displayContent.mDisplayContentChangeListeners
- .getRegisteredCallbackCount() == 0) {
- displayContent.mDisplayContentChangeListeners = null;
+ if (displayContent != null) {
+ if (displayContent.mDisplayContentChangeListeners != null) {
+ displayContent.mDisplayContentChangeListeners.unregister(listener);
+ if (displayContent.mDisplayContentChangeListeners
+ .getRegisteredCallbackCount() == 0) {
+ displayContent.mDisplayContentChangeListeners = null;
+ }
}
}
}
@@ -7149,7 +7179,6 @@
synchronized(mWindowMap) {
final DisplayContent displayContent = getDefaultDisplayContentLocked();
- final Display display = displayContent.getDisplay();
readForcedDisplaySizeAndDensityLocked(displayContent);
mDisplayReady = true;
@@ -7173,24 +7202,25 @@
}
}
- public void displayReady(int displayId) {
+ private void displayReady(int displayId) {
synchronized(mWindowMap) {
final DisplayContent displayContent = getDisplayContentLocked(displayId);
- final DisplayInfo displayInfo;
- mAnimator.addDisplayLocked(displayId);
- synchronized(displayContent.mDisplaySizeLock) {
- // Bootstrap the default logical display from the display manager.
- displayInfo = displayContent.getDisplayInfo();
- DisplayInfo newDisplayInfo = mDisplayManagerService.getDisplayInfo(displayId);
- if (newDisplayInfo != null) {
- displayInfo.copyFrom(newDisplayInfo);
+ if (displayContent != null) {
+ mAnimator.addDisplayLocked(displayId);
+ synchronized(displayContent.mDisplaySizeLock) {
+ // Bootstrap the default logical display from the display manager.
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+ DisplayInfo newDisplayInfo = mDisplayManagerService.getDisplayInfo(displayId);
+ if (newDisplayInfo != null) {
+ displayInfo.copyFrom(newDisplayInfo);
+ }
+ displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
+ displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
+ displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
+ displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
+ displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
+ displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
}
- displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
- displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
- displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
- displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
- displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
- displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
}
}
}
@@ -7831,12 +7861,15 @@
// TODO(cmautner): Access to DisplayContent should be locked on mWindowMap. Doing that
// could lead to deadlock since this is called from ActivityManager.
final DisplayContent displayContent = getDisplayContentLocked(displayId);
- synchronized(displayContent.mDisplaySizeLock) {
- size.x = displayContent.mInitialDisplayWidth;
- size.y = displayContent.mInitialDisplayHeight;
+ if (displayContent != null) {
+ synchronized(displayContent.mDisplaySizeLock) {
+ size.x = displayContent.mInitialDisplayWidth;
+ size.y = displayContent.mInitialDisplayHeight;
+ }
}
}
+ @Override
public void setForcedDisplaySize(int displayId, int width, int height) {
synchronized(mWindowMap) {
// Set some sort of reasonable bounds on the size of the display that we
@@ -7845,14 +7878,15 @@
final int MIN_HEIGHT = 200;
final int MAX_SCALE = 2;
final DisplayContent displayContent = getDisplayContentLocked(displayId);
-
- width = Math.min(Math.max(width, MIN_WIDTH),
- displayContent.mInitialDisplayWidth * MAX_SCALE);
- height = Math.min(Math.max(height, MIN_HEIGHT),
- displayContent.mInitialDisplayHeight * MAX_SCALE);
- setForcedDisplaySizeLocked(displayContent, width, height);
- Settings.Global.putString(mContext.getContentResolver(),
- Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
+ if (displayContent != null) {
+ width = Math.min(Math.max(width, MIN_WIDTH),
+ displayContent.mInitialDisplayWidth * MAX_SCALE);
+ height = Math.min(Math.max(height, MIN_HEIGHT),
+ displayContent.mInitialDisplayHeight * MAX_SCALE);
+ setForcedDisplaySizeLocked(displayContent, width, height);
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
+ }
}
}
@@ -7895,6 +7929,7 @@
}
}
+ // displayContent must not be null
private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
Slog.i(TAG, "Using new display size: " + width + "x" + height);
@@ -7905,25 +7940,32 @@
reconfigureDisplayLocked(displayContent);
}
+ @Override
public void clearForcedDisplaySize(int displayId) {
synchronized(mWindowMap) {
final DisplayContent displayContent = getDisplayContentLocked(displayId);
- setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
- displayContent.mInitialDisplayHeight);
- Settings.Global.putString(mContext.getContentResolver(),
- Settings.Global.DISPLAY_SIZE_FORCED, "");
+ if (displayContent != null) {
+ setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
+ displayContent.mInitialDisplayHeight);
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.DISPLAY_SIZE_FORCED, "");
+ }
}
}
+ @Override
public void setForcedDisplayDensity(int displayId, int density) {
synchronized(mWindowMap) {
final DisplayContent displayContent = getDisplayContentLocked(displayId);
- setForcedDisplayDensityLocked(displayContent, density);
- Settings.Global.putString(mContext.getContentResolver(),
- Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
+ if (displayContent != null) {
+ setForcedDisplayDensityLocked(displayContent, density);
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
+ }
}
}
+ // displayContent must not be null
private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
Slog.i(TAG, "Using new display density: " + density);
@@ -7933,15 +7975,19 @@
reconfigureDisplayLocked(displayContent);
}
+ @Override
public void clearForcedDisplayDensity(int displayId) {
synchronized(mWindowMap) {
final DisplayContent displayContent = getDisplayContentLocked(displayId);
- setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity);
- Settings.Global.putString(mContext.getContentResolver(),
- Settings.Global.DISPLAY_DENSITY_FORCED, "");
+ if (displayContent != null) {
+ setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity);
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.DISPLAY_DENSITY_FORCED, "");
+ }
}
}
+ // displayContent must not be null
private void reconfigureDisplayLocked(DisplayContent displayContent) {
// TODO: Multidisplay: for now only use with default display.
mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
@@ -8163,11 +8209,13 @@
}
private final void performLayoutAndPlaceSurfacesLocked() {
+ int loopCount = 6;
do {
mTraversalScheduled = false;
performLayoutAndPlaceSurfacesLockedLoop();
mH.removeMessages(H.DO_TRAVERSAL);
- } while (mTraversalScheduled);
+ loopCount--;
+ } while (mTraversalScheduled && loopCount > 0);
}
private boolean mInLayout = false;
@@ -9127,6 +9175,19 @@
final boolean committed =
winAnimator.commitFinishDrawingLocked(currentTime);
if (isDefaultDisplay && committed) {
+ if (w.mAttrs.type == TYPE_DREAM) {
+ // HACK: When a dream is shown, it may at that
+ // point hide the lock screen. So we need to
+ // redo the layout to let the phone window manager
+ // make this happen.
+ displayContent.pendingLayoutChanges |=
+ WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
+ if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+ debugLayoutRepeats(
+ "dream and commitFinishDrawingLocked true",
+ displayContent.pendingLayoutChanges);
+ }
+ }
if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
if (DEBUG_WALLPAPER) Slog.v(TAG,
"First draw done in potential wallpaper target " + w);
@@ -9711,7 +9772,9 @@
for (int i = 0; i < count; ++i) {
final DisplayContent displayContent =
getDisplayContentLocked(pendingLayouts.keyAt(i));
- displayContent.pendingLayoutChanges |= pendingLayouts.valueAt(i);
+ if (displayContent != null) {
+ displayContent.pendingLayoutChanges |= pendingLayouts.valueAt(i);
+ }
}
mWindowDetachedWallpaper = animToLayout.mWindowDetachedWallpaper;
@@ -10837,11 +10900,20 @@
mDisplayContents.put(display.getDisplayId(), displayContent);
}
+ /**
+ * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
+ * there is a Display for the displayId.
+ * @param displayId The display the caller is interested in.
+ * @return The DisplayContent associated with displayId or null if there is no Display for it.
+ */
public DisplayContent getDisplayContentLocked(final int displayId) {
DisplayContent displayContent = mDisplayContents.get(displayId);
if (displayContent == null) {
- displayContent = new DisplayContent(mDisplayManager.getDisplay(displayId));
- mDisplayContents.put(displayId, displayContent);
+ final Display display = mDisplayManager.getDisplay(displayId);
+ if (display != null) {
+ displayContent = new DisplayContent(display);
+ mDisplayContents.put(displayId, displayContent);
+ }
}
return displayContent;
}
@@ -10927,6 +10999,7 @@
}
}
+ // There is an inherent assumption that this will never return null.
public DisplayContent getDefaultDisplayContentLocked() {
return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
}
@@ -10939,8 +11012,14 @@
return getDefaultDisplayContentLocked().getDisplayInfo();
}
+ /**
+ * Return the list of WindowStates associated on the passed display.
+ * @param display The screen to return windows from.
+ * @return The list of WindowStates on the screen, or null if the there is no screen.
+ */
public WindowList getWindowListLocked(final Display display) {
- return getDisplayContentLocked(display.getDisplayId()).getWindowList();
+ final DisplayContent displayContent = getDisplayContentLocked(display.getDisplayId());
+ return displayContent != null ? displayContent.getWindowList() : null;
}
@Override
@@ -10949,8 +11028,11 @@
}
private void handleDisplayAddedLocked(int displayId) {
- createDisplayContentLocked(mDisplayManager.getDisplay(displayId));
- displayReady(displayId);
+ final Display display = mDisplayManager.getDisplay(displayId);
+ if (display != null) {
+ createDisplayContentLocked(display);
+ displayReady(displayId);
+ }
}
@Override
@@ -10960,11 +11042,13 @@
private void handleDisplayRemovedLocked(int displayId) {
final DisplayContent displayContent = getDisplayContentLocked(displayId);
- mDisplayContents.delete(displayId);
- WindowList windows = displayContent.getWindowList();
- while (!windows.isEmpty()) {
- final WindowState win = windows.get(windows.size() - 1);
- removeWindowLocked(win.mSession, win);
+ if (displayContent != null) {
+ mDisplayContents.delete(displayId);
+ WindowList windows = displayContent.getWindowList();
+ while (!windows.isEmpty()) {
+ final WindowState win = windows.get(windows.size() - 1);
+ removeWindowLocked(win.mSession, win);
+ }
}
mAnimator.removeDisplayLocked(displayId);
}
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index feb29b1..c195f45 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -1038,18 +1038,26 @@
}
boolean isHiddenFromUserLocked() {
- // Save some cycles by not calling getDisplayInfo unless it is an application
- // window intended for all users.
- if (mAttrs.type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
- && mAppToken != null && mAppToken.showWhenLocked) {
- final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
- if (isFullscreen(displayInfo.appWidth, displayInfo.appHeight)) {
+ // Attached windows are evaluated based on the window that they are attached to.
+ WindowState win = this;
+ while (win.mAttachedWindow != null) {
+ win = win.mAttachedWindow;
+ }
+ if (win.mAttrs.type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
+ && win.mAppToken != null && win.mAppToken.showWhenLocked) {
+ // Save some cycles by not calling getDisplayInfo unless it is an application
+ // window intended for all users.
+ final DisplayInfo displayInfo = win.mDisplayContent.getDisplayInfo();
+ if (win.mFrame.left <= 0 && win.mFrame.top <= 0
+ && win.mFrame.right >= displayInfo.appWidth
+ && win.mFrame.bottom >= displayInfo.appHeight) {
// Is a fullscreen window, like the clock alarm. Show to everyone.
return false;
}
}
- return mShowToOwnerOnly && UserHandle.getUserId(mOwnerUid) != mService.mCurrentUserId;
+ return win.mShowToOwnerOnly
+ && UserHandle.getUserId(win.mOwnerUid) != mService.mCurrentUserId;
}
private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 8aeb2af..7848b1d 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -34,7 +34,7 @@
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.MANAGE_USERS" />
- <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 59a86c2..1758d93 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -16,23 +16,37 @@
package com.android.server.pm;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.UserInfo;
import android.os.Debug;
import android.os.Environment;
import android.os.UserManager;
import android.test.AndroidTestCase;
+import java.util.ArrayList;
import java.util.List;
/** Test {@link UserManager} functionality. */
public class UserManagerTest extends AndroidTestCase {
UserManager mUserManager = null;
+ Object mUserLock = new Object();
@Override
public void setUp() throws Exception {
mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
+ IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
+ getContext().registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ synchronized (mUserLock) {
+ mUserLock.notifyAll();
+ }
+ }
+ }, filter);
}
public void testHasPrimary() throws Exception {
@@ -54,7 +68,7 @@
}
}
assertTrue(found);
- mUserManager.removeUser(userInfo.id);
+ removeUser(userInfo.id);
}
public void testAdd2Users() throws Exception {
@@ -67,14 +81,13 @@
assertTrue(findUser(0));
assertTrue(findUser(user1.id));
assertTrue(findUser(user2.id));
- mUserManager.removeUser(user1.id);
- mUserManager.removeUser(user2.id);
+ removeUser(user1.id);
+ removeUser(user2.id);
}
public void testRemoveUser() throws Exception {
UserInfo userInfo = mUserManager.createUser("Guest 1", UserInfo.FLAG_GUEST);
-
- mUserManager.removeUser(userInfo.id);
+ removeUser(userInfo.id);
assertFalse(findUser(userInfo.id));
}
@@ -95,12 +108,47 @@
int serialNumber1 = user1.serialNumber;
assertEquals(serialNumber1, mUserManager.getUserSerialNumber(user1.id));
assertEquals(user1.id, mUserManager.getUserHandle(serialNumber1));
- mUserManager.removeUser(user1.id);
+ removeUser(user1.id);
UserInfo user2 = mUserManager.createUser("User 2", UserInfo.FLAG_RESTRICTED);
int serialNumber2 = user2.serialNumber;
assertFalse(serialNumber1 == serialNumber2);
assertEquals(serialNumber2, mUserManager.getUserSerialNumber(user2.id));
assertEquals(user2.id, mUserManager.getUserHandle(serialNumber2));
- mUserManager.removeUser(user2.id);
+ removeUser(user2.id);
+ }
+
+ public void testMaxUsers() {
+ int N = UserManager.getMaxSupportedUsers();
+ int count = mUserManager.getUsers().size();
+ List<UserInfo> created = new ArrayList<UserInfo>();
+ // Create as many users as permitted and make sure creation passes
+ while (count < N) {
+ UserInfo ui = mUserManager.createUser("User " + count, 0);
+ assertNotNull(ui);
+ created.add(ui);
+ count++;
+ }
+ // Try to create one more user and make sure it fails
+ UserInfo extra = null;
+ assertNull(extra = mUserManager.createUser("One more", 0));
+ if (extra != null) {
+ removeUser(extra.id);
+ }
+ while (!created.isEmpty()) {
+ UserInfo user = created.remove(0);
+ removeUser(user.id);
+ }
+ }
+
+ private void removeUser(int userId) {
+ synchronized (mUserLock) {
+ mUserManager.removeUser(userId);
+ while (mUserManager.getUserInfo(userId) != null) {
+ try {
+ mUserLock.wait(1000);
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
}
}
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 4cb409d..9118aea 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -33,6 +33,15 @@
<meta-data android:name="android.graphics.renderThread" android:value="true" />
<activity
+ android:name="MipMapActivity"
+ android:label="_MipMap">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity
android:name="PathOffsetActivity"
android:label="_PathOffset">
<intent-filter>
diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/very_large_photo.jpg b/tests/HwAccelerationTest/res/drawable-nodpi/very_large_photo.jpg
new file mode 100644
index 0000000..7f047b1
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-nodpi/very_large_photo.jpg
Binary files differ
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MipMapActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MipMapActivity.java
new file mode 100644
index 0000000..1034649
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MipMapActivity.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2010 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.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.ScaleAnimation;
+import android.widget.FrameLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class MipMapActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final BitmapsView view = new BitmapsView(this);
+ setContentView(view);
+ }
+
+ static class BitmapsView extends View {
+ private Paint mBitmapPaint;
+ private final Bitmap mBitmap1;
+ private final Bitmap mBitmap2;
+
+ BitmapsView(Context c) {
+ super(c);
+
+ mBitmap1 = BitmapFactory.decodeResource(c.getResources(), R.drawable.very_large_photo);
+ mBitmap2 = BitmapFactory.decodeResource(c.getResources(), R.drawable.very_large_photo);
+
+ mBitmap1.setHasMipMap(true);
+
+ mBitmapPaint = new Paint();
+ mBitmapPaint.setFilterBitmap(true);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ canvas.save();
+ canvas.scale(0.3f, 0.3f);
+ canvas.drawBitmap(mBitmap1, 0, 0, mBitmapPaint);
+ canvas.restore();
+
+ canvas.save();
+ canvas.translate(mBitmap1.getWidth() * 0.3f + 96.0f, 0.0f);
+ canvas.scale(0.3f, 0.3f);
+ canvas.drawBitmap(mBitmap2, 0, 0, mBitmapPaint);
+ canvas.restore();
+ }
+ }
+}
diff --git a/tests/StatusBar/res/layout/notification_builder_test.xml b/tests/StatusBar/res/layout/notification_builder_test.xml
index 6c384f7..94fc089 100644
--- a/tests/StatusBar/res/layout/notification_builder_test.xml
+++ b/tests/StatusBar/res/layout/notification_builder_test.xml
@@ -371,6 +371,12 @@
android:tag="Oh my goodness. SOMETHING HAPPENED!!!!"
/>
<RadioButton
+ android:id="@+id/text_emoji"
+ style="@style/FieldContents"
+ android:text="emoji"
+ android:tag="_ Cactus _ Cactus _"
+ />
+ <RadioButton
android:id="@+id/text_haiku"
style="@style/FieldContents"
android:text="haiku"
@@ -572,6 +578,12 @@
android:tag="sholes final approach\nlanding gear punted to flan\nrunway foam glistens"
/>
<RadioButton
+ android:id="@+id/ticker_emoji"
+ style="@style/FieldContents"
+ android:text="emoji"
+ android:tag="_ Cactus _ Cactus _"
+ />
+ <RadioButton
android:id="@+id/ticker_custom"
style="@style/FieldContents.Disabled"
android:text="custom view"
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
index fefd890..2f0c173 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
@@ -32,6 +32,7 @@
import android.os.Environment;
import android.os.Vibrator;
import android.os.Handler;
+import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.util.Log;
import android.net.Uri;
@@ -187,6 +188,20 @@
mNM.notify(id, n);
}
+ private static CharSequence subst(CharSequence in, char ch, CharSequence sub) {
+ int i=0;
+ SpannableStringBuilder edit = new SpannableStringBuilder(in);
+ while (i<edit.length()) {
+ if (edit.charAt(i) == ch) {
+ edit.replace(i, i+1, sub);
+ i += sub.length();
+ } else {
+ i ++;
+ }
+ }
+ return edit;
+ }
+
private Notification buildNotification(int id) {
Notification.Builder b = new Notification.Builder(this);
@@ -223,19 +238,25 @@
}
// title
- final String title = getRadioTag(R.id.group_title);
+ final CharSequence title = getRadioTag(R.id.group_title);
if (!TextUtils.isEmpty(title)) {
b.setContentTitle(title);
}
// text
- final String text = getRadioTag(R.id.group_text);
+ final CharSequence text = getRadioTag(R.id.group_text);
if (!TextUtils.isEmpty(text)) {
- b.setContentText(text);
+ if (getRadioChecked(R.id.group_text) == R.id.text_emoji) {
+ // UTF-16 for +1F335
+ b.setContentText(subst(text,
+ '_', "\ud83c\udf35"));
+ } else {
+ b.setContentText(text);
+ }
}
// info
- final String info = getRadioTag(R.id.group_info);
+ final CharSequence info = getRadioTag(R.id.group_info);
if (!TextUtils.isEmpty(info)) {
b.setContentInfo(info);
}
@@ -272,6 +293,11 @@
case R.id.ticker_haiku:
b.setTicker(getRadioTag(R.id.group_ticker));
break;
+ case R.id.ticker_emoji:
+ // UTF-16 for +1F335
+ b.setTicker(subst(getRadioTag(R.id.group_ticker),
+ '_', "\ud83c\udf35"));
+ break;
case R.id.ticker_custom:
// TODO
break;
@@ -370,19 +396,19 @@
return g.getCheckedRadioButtonId();
}
- private String getRadioTag(int id) {
+ private CharSequence getRadioTag(int id) {
final RadioGroup g = (RadioGroup)findViewById(id);
final View v = findViewById(g.getCheckedRadioButtonId());
- return (String)v.getTag();
+ return (CharSequence) v.getTag();
}
private int getRadioInt(int id, int def) {
- String str = getRadioTag(id);
+ CharSequence str = getRadioTag(id);
if (TextUtils.isEmpty(str)) {
return def;
} else {
try {
- return Integer.parseInt(str);
+ return Integer.parseInt(str.toString());
} catch (NumberFormatException ex) {
return def;
}
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back.png
new file mode 100644
index 0000000..84e6bc8
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back_default.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back_default.png
deleted file mode 100644
index ac5a97b..0000000
--- a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back_default.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home.png
new file mode 100644
index 0000000..38e4f45
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home_default.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home_default.png
deleted file mode 100644
index a90dc9b..0000000
--- a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home_default.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent.png
new file mode 100644
index 0000000..bf9f300
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent_default.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent_default.png
deleted file mode 100644
index cb3c433..0000000
--- a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent_default.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back.png
new file mode 100644
index 0000000..a00bc5b
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png
deleted file mode 100644
index 5ab09f0..0000000
--- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home.png
new file mode 100644
index 0000000..dc3183b
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png
deleted file mode 100644
index 62ca427..0000000
--- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent.png
new file mode 100644
index 0000000..b07f611
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png
deleted file mode 100644
index ff698fb..0000000
--- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml b/tools/layoutlib/bridge/resources/bars/navigation_bar.xml
similarity index 76%
rename from tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml
rename to tools/layoutlib/bridge/resources/bars/navigation_bar.xml
index c5acddb..599ca08 100644
--- a/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml
+++ b/tools/layoutlib/bridge/resources/bars/navigation_bar.xml
@@ -1,5 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"/>
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
@@ -13,12 +17,4 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"/>
- <ImageView
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"/>
- <ImageView
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_marginLeft="3dip"
- android:layout_marginRight="15dip"/>
</merge>
diff --git a/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml b/tools/layoutlib/bridge/resources/bars/status_bar.xml
similarity index 100%
rename from tools/layoutlib/bridge/resources/bars/phone_system_bar.xml
rename to tools/layoutlib/bridge/resources/bars/status_bar.xml
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back.png
new file mode 100644
index 0000000..bd60cd6
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back_default.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back_default.png
deleted file mode 100644
index 4cb305d..0000000
--- a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back_default.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home.png
new file mode 100644
index 0000000..c5bc5c9
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home_default.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home_default.png
deleted file mode 100644
index 31d35c8..0000000
--- a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home_default.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent.png
new file mode 100644
index 0000000..f621d9c
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent_default.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent_default.png
deleted file mode 100644
index f0cc341d..0000000
--- a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent_default.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index daf520b..bf8658e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -210,7 +210,8 @@
Capability.PLAY_ANIMATION,
Capability.ANIMATED_VIEW_MANIPULATION,
Capability.ADAPTER_BINDING,
- Capability.EXTENDED_VIEWINFO);
+ Capability.EXTENDED_VIEWINFO,
+ Capability.FIXED_SCALABLE_NINE_PATCH);
BridgeAssetManager.initSystem();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
index 62c886b..ea9d8d9 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -60,11 +60,15 @@
protected abstract TextView getStyleableTextView();
- protected CustomBar(Context context, Density density, String layoutPath, String name)
- throws XmlPullParserException {
+ protected CustomBar(Context context, Density density, int orientation, String layoutPath,
+ String name) throws XmlPullParserException {
super(context);
- setOrientation(LinearLayout.HORIZONTAL);
- setGravity(Gravity.CENTER_VERTICAL);
+ setOrientation(orientation);
+ if (orientation == LinearLayout.HORIZONTAL) {
+ setGravity(Gravity.CENTER_VERTICAL);
+ } else {
+ setGravity(Gravity.CENTER_HORIZONTAL);
+ }
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java
index 68f5aba..226649d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java
@@ -21,6 +21,7 @@
import org.xmlpull.v1.XmlPullParserException;
import android.content.Context;
+import android.widget.LinearLayout;
import android.widget.TextView;
public class FakeActionBar extends CustomBar {
@@ -29,7 +30,7 @@
public FakeActionBar(Context context, Density density, String label, String icon)
throws XmlPullParserException {
- super(context, density, "/bars/action_bar.xml", "action_bar.xml");
+ super(context, density, LinearLayout.HORIZONTAL, "/bars/action_bar.xml", "action_bar.xml");
// Cannot access the inside items through id because no R.id values have been
// created for them.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
new file mode 100644
index 0000000..cc90d6b
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2011 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.layoutlib.bridge.bars;
+
+import com.android.resources.Density;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class NavigationBar extends CustomBar {
+
+ public NavigationBar(Context context, Density density, int orientation) throws XmlPullParserException {
+ super(context, density, orientation, "/bars/navigation_bar.xml", "navigation_bar.xml");
+
+ setBackgroundColor(0xFF000000);
+
+ // Cannot access the inside items through id because no R.id values have been
+ // created for them.
+ // We do know the order though.
+ // 0 is a spacer.
+ int back = 1;
+ int recent = 3;
+ if (orientation == LinearLayout.VERTICAL) {
+ back = 3;
+ recent = 1;
+ }
+
+ loadIcon(back, "ic_sysbar_back.png", density);
+ loadIcon(2, "ic_sysbar_home.png", density);
+ loadIcon(recent, "ic_sysbar_recent.png", density);
+ }
+
+ @Override
+ protected TextView getStyleableTextView() {
+ return null;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
similarity index 86%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
index 7521011..5c08412 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
@@ -25,12 +25,13 @@
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LevelListDrawable;
import android.view.Gravity;
+import android.widget.LinearLayout;
import android.widget.TextView;
-public class PhoneSystemBar extends CustomBar {
+public class StatusBar extends CustomBar {
- public PhoneSystemBar(Context context, Density density) throws XmlPullParserException {
- super(context, density, "/bars/phone_system_bar.xml", "phone_system_bar.xml");
+ public StatusBar(Context context, Density density) throws XmlPullParserException {
+ super(context, density, LinearLayout.HORIZONTAL, "/bars/status_bar.xml", "status_bar.xml");
// FIXME: use FILL_H?
setGravity(Gravity.START | Gravity.TOP | Gravity.RIGHT);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java
deleted file mode 100644
index 456ddb4..0000000
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2011 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.layoutlib.bridge.bars;
-
-import com.android.resources.Density;
-import com.android.resources.ResourceType;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LevelListDrawable;
-import android.widget.TextView;
-
-public class TabletSystemBar extends CustomBar {
-
- public TabletSystemBar(Context context, Density density) throws XmlPullParserException {
- super(context, density, "/bars/tablet_system_bar.xml", "tablet_system_bar.xml");
-
- setBackgroundColor(0xFF000000);
-
- // Cannot access the inside items through id because no R.id values have been
- // created for them.
- // We do know the order though.
- loadIcon(0, "ic_sysbar_back_default.png", density);
- loadIcon(1, "ic_sysbar_home_default.png", density);
- loadIcon(2, "ic_sysbar_recent_default.png", density);
- // 3 is the spacer
- loadIcon(4, "stat_sys_wifi_signal_4_fully.png", density);
- Drawable drawable = loadIcon(5, ResourceType.DRAWABLE, "stat_sys_battery_charge");
- if (drawable instanceof LevelListDrawable) {
- ((LevelListDrawable) drawable).setLevel(100);
- }
- }
-
- @Override
- protected TextView getStyleableTextView() {
- return null;
- }
-}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
index 5f5ebc4..c27859f 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
@@ -21,6 +21,7 @@
import org.xmlpull.v1.XmlPullParserException;
import android.content.Context;
+import android.widget.LinearLayout;
import android.widget.TextView;
public class TitleBar extends CustomBar {
@@ -29,7 +30,7 @@
public TitleBar(Context context, Density density, String label)
throws XmlPullParserException {
- super(context, density, "/bars/title_bar.xml", "title_bar.xml");
+ super(context, density, LinearLayout.HORIZONTAL, "/bars/title_bar.xml", "title_bar.xml");
// Cannot access the inside items through id because no R.id values have been
// created for them.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java
index a235ec3..803849f 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java
@@ -21,9 +21,12 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.IOException;
import java.io.InputStream;
/**
@@ -38,14 +41,21 @@
public static XmlPullParser create(File f)
throws XmlPullParserException, FileNotFoundException {
- KXmlParser parser = instantiateParser(f.getName());
- parser.setInput(new FileInputStream(f), ENCODING);
- return parser;
+ InputStream stream = new FileInputStream(f);
+ return create(stream, f.getName(), f.length());
}
public static XmlPullParser create(InputStream stream, String name)
+ throws XmlPullParserException {
+ return create(stream, name, -1);
+ }
+
+ private static XmlPullParser create(InputStream stream, String name, long size)
throws XmlPullParserException {
KXmlParser parser = instantiateParser(name);
+
+ stream = readAndClose(stream, name, size);
+
parser.setInput(stream, ENCODING);
return parser;
}
@@ -61,6 +71,61 @@
return parser;
}
+ private static InputStream readAndClose(InputStream stream, String name, long size)
+ throws XmlPullParserException {
+ // just a sanity check. It's doubtful we'll have such big files!
+ if (size > Integer.MAX_VALUE) {
+ throw new XmlPullParserException("File " + name + " is too big to be parsed");
+ }
+ int intSize = (int) size;
+
+ // create a buffered reader to facilitate reading.
+ BufferedInputStream bufferedStream = new BufferedInputStream(stream);
+ try {
+ int avail;
+ if (intSize != -1) {
+ avail = intSize;
+ } else {
+ // get the size to read.
+ avail = bufferedStream.available();
+ }
+
+ // create the initial buffer and read it.
+ byte[] buffer = new byte[avail];
+ int read = stream.read(buffer);
+
+ // this is the easy case.
+ if (read == intSize) {
+ return new ByteArrayInputStream(buffer);
+ }
+
+ // check if there is more to read (read() does not necessarily read all that
+ // available() returned!)
+ while ((avail = bufferedStream.available()) > 0) {
+ if (read + avail > buffer.length) {
+ // just allocate what is needed. We're mostly reading small files
+ // so it shouldn't be too problematic.
+ byte[] moreBuffer = new byte[read + avail];
+ System.arraycopy(buffer, 0, moreBuffer, 0, read);
+ buffer = moreBuffer;
+ }
+
+ read += stream.read(buffer, read, avail);
+ }
+
+ // return a new stream encapsulating this buffer.
+ return new ByteArrayInputStream(buffer);
+
+ } catch (IOException e) {
+ throw new XmlPullParserException("Failed to read " + name, null, e);
+ } finally {
+ try {
+ bufferedStream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
private static class CustomParser extends KXmlParser {
private final String mName;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
index de65fd4..f109e39 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
@@ -20,11 +20,12 @@
import static com.android.ide.common.rendering.api.Result.Status.ERROR_TIMEOUT;
import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
+import com.android.ide.common.rendering.api.HardwareConfig;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.RenderParams;
import com.android.ide.common.rendering.api.RenderResources;
-import com.android.ide.common.rendering.api.Result;
import com.android.ide.common.rendering.api.RenderResources.FrameworkResourceIdProvider;
+import com.android.ide.common.rendering.api.Result;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.resources.Density;
@@ -98,19 +99,22 @@
return result;
}
+ HardwareConfig hardwareConfig = mParams.getHardwareConfig();
+
// setup the display Metrics.
DisplayMetrics metrics = new DisplayMetrics();
- metrics.densityDpi = metrics.noncompatDensityDpi = mParams.getDensity().getDpiValue();
+ metrics.densityDpi = metrics.noncompatDensityDpi =
+ hardwareConfig.getDensity().getDpiValue();
metrics.density = metrics.noncompatDensity =
metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
metrics.scaledDensity = metrics.noncompatScaledDensity = metrics.density;
- metrics.widthPixels = metrics.noncompatWidthPixels = mParams.getScreenWidth();
- metrics.heightPixels = metrics.noncompatHeightPixels = mParams.getScreenHeight();
- metrics.xdpi = metrics.noncompatXdpi = mParams.getXdpi();
- metrics.ydpi = metrics.noncompatYdpi = mParams.getYdpi();
+ metrics.widthPixels = metrics.noncompatWidthPixels = hardwareConfig.getScreenWidth();
+ metrics.heightPixels = metrics.noncompatHeightPixels = hardwareConfig.getScreenHeight();
+ metrics.xdpi = metrics.noncompatXdpi = hardwareConfig.getXdpi();
+ metrics.ydpi = metrics.noncompatYdpi = hardwareConfig.getYdpi();
RenderResources resources = mParams.getResources();
@@ -305,7 +309,9 @@
private Configuration getConfiguration() {
Configuration config = new Configuration();
- ScreenSize screenSize = mParams.getConfigScreenSize();
+ HardwareConfig hardwareConfig = mParams.getHardwareConfig();
+
+ ScreenSize screenSize = hardwareConfig.getScreenSize();
if (screenSize != null) {
switch (screenSize) {
case SMALL:
@@ -323,13 +329,13 @@
}
}
- Density density = mParams.getDensity();
+ Density density = hardwareConfig.getDensity();
if (density == null) {
density = Density.MEDIUM;
}
- config.screenWidthDp = mParams.getScreenWidth() / density.getDpiValue();
- config.screenHeightDp = mParams.getScreenHeight() / density.getDpiValue();
+ config.screenWidthDp = hardwareConfig.getScreenWidth() / density.getDpiValue();
+ config.screenHeightDp = hardwareConfig.getScreenHeight() / density.getDpiValue();
if (config.screenHeightDp < config.screenWidthDp) {
config.smallestScreenWidthDp = config.screenHeightDp;
} else {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
index 8133210..b677131 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
@@ -19,6 +19,7 @@
import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN;
import com.android.ide.common.rendering.api.DrawableParams;
+import com.android.ide.common.rendering.api.HardwareConfig;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.rendering.api.Result;
import com.android.ide.common.rendering.api.Result.Status;
@@ -59,6 +60,7 @@
try {
// get the drawable resource value
DrawableParams params = getParams();
+ HardwareConfig hardwareConfig = params.getHardwareConfig();
ResourceValue drawableResource = params.getDrawable();
// resolve it
@@ -75,15 +77,15 @@
// get the actual Drawable object to draw
Drawable d = ResourceHelper.getDrawable(drawableResource, context);
- content.setBackgroundDrawable(d);
+ content.setBackground(d);
// set the AttachInfo on the root view.
AttachInfo_Accessor.setAttachInfo(content);
// measure
- int w = params.getScreenWidth();
- int h = params.getScreenHeight();
+ int w = hardwareConfig.getScreenWidth();
+ int h = hardwareConfig.getScreenHeight();
int w_spec = MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY);
int h_spec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY);
content.measure(w_spec, h_spec);
@@ -99,11 +101,11 @@
// create an Android bitmap around the BufferedImage
Bitmap bitmap = Bitmap_Delegate.createBitmap(image,
- true /*isMutable*/, params.getDensity());
+ true /*isMutable*/, hardwareConfig.getDensity());
// create a Canvas around the Android bitmap
Canvas canvas = new Canvas(bitmap);
- canvas.setDensity(params.getDensity().getDpiValue());
+ canvas.setDensity(hardwareConfig.getDensity().getDpiValue());
// and draw
content.draw(canvas);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index cc0f077..c14af4a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -24,6 +24,7 @@
import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
import com.android.ide.common.rendering.api.AdapterBinding;
+import com.android.ide.common.rendering.api.HardwareConfig;
import com.android.ide.common.rendering.api.IAnimationListener;
import com.android.ide.common.rendering.api.ILayoutPullParser;
import com.android.ide.common.rendering.api.IProjectCallback;
@@ -43,13 +44,13 @@
import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
import com.android.layoutlib.bridge.bars.FakeActionBar;
-import com.android.layoutlib.bridge.bars.PhoneSystemBar;
-import com.android.layoutlib.bridge.bars.TabletSystemBar;
+import com.android.layoutlib.bridge.bars.NavigationBar;
+import com.android.layoutlib.bridge.bars.StatusBar;
import com.android.layoutlib.bridge.bars.TitleBar;
import com.android.layoutlib.bridge.impl.binding.FakeAdapter;
import com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter;
import com.android.resources.ResourceType;
-import com.android.resources.ScreenSize;
+import com.android.resources.ScreenOrientation;
import com.android.util.Pair;
import org.xmlpull.v1.XmlPullParserException;
@@ -68,8 +69,8 @@
import android.util.TypedValue;
import android.view.AttachInfo_Accessor;
import android.view.BridgeInflater;
-import android.view.IWindowManagerImpl;
import android.view.IWindowManager;
+import android.view.IWindowManagerImpl;
import android.view.Surface;
import android.view.View;
import android.view.View.MeasureSpec;
@@ -124,7 +125,8 @@
private boolean mWindowIsFloating;
private int mStatusBarSize;
- private int mSystemBarSize;
+ private int mNavigationBarSize;
+ private int mNavigationBarOrientation = LinearLayout.HORIZONTAL;
private int mTitleBarSize;
private int mActionBarSize;
@@ -187,7 +189,7 @@
findBackground(resources);
findStatusBar(resources, metrics);
findActionBar(resources, metrics);
- findSystemBar(resources, metrics);
+ findNavigationBar(resources, metrics);
// FIXME: find those out, and possibly add them to the render params
boolean hasSystemNavBar = true;
@@ -221,19 +223,57 @@
try {
SessionParams params = getParams();
+ HardwareConfig hardwareConfig = params.getHardwareConfig();
BridgeContext context = getContext();
+
// the view group that receives the window background.
ViewGroup backgroundView = null;
if (mWindowIsFloating || params.isForceNoDecor()) {
backgroundView = mViewRoot = mContentRoot = new FrameLayout(context);
} else {
+ if (hasSoftwareButtons() && mNavigationBarOrientation == LinearLayout.VERTICAL) {
+ /*
+ * This is a special case where the navigation bar is on the right.
+ +-------------------------------------------------+---+
+ | Status bar (always) | |
+ +-------------------------------------------------+ |
+ | (Layout with background drawable) | |
+ | +---------------------------------------------+ | |
+ | | Title/Action bar (optional) | | |
+ | +---------------------------------------------+ | |
+ | | Content, vertical extending | | |
+ | | | | |
+ | +---------------------------------------------+ | |
+ +-------------------------------------------------+---+
+
+ So we create a horizontal layout, with the nav bar on the right,
+ and the left part is the normal layout below without the nav bar at
+ the bottom
+ */
+ LinearLayout topLayout = new LinearLayout(context);
+ mViewRoot = topLayout;
+ topLayout.setOrientation(LinearLayout.HORIZONTAL);
+
+ try {
+ NavigationBar navigationBar = new NavigationBar(context,
+ hardwareConfig.getDensity(), LinearLayout.VERTICAL);
+ navigationBar.setLayoutParams(
+ new LinearLayout.LayoutParams(
+ mNavigationBarSize,
+ LayoutParams.MATCH_PARENT));
+ topLayout.addView(navigationBar);
+ } catch (XmlPullParserException e) {
+
+ }
+ }
+
/*
* we're creating the following layout
*
+-------------------------------------------------+
- | System bar (only in phone UI) |
+ | Status bar (always) |
+-------------------------------------------------+
| (Layout with background drawable) |
| +---------------------------------------------+ |
@@ -243,20 +283,31 @@
| | | |
| +---------------------------------------------+ |
+-------------------------------------------------+
- | System bar (only in tablet UI) |
+ | Navigation bar for soft buttons, maybe see above|
+-------------------------------------------------+
*/
LinearLayout topLayout = new LinearLayout(context);
- mViewRoot = topLayout;
topLayout.setOrientation(LinearLayout.VERTICAL);
+ // if we don't already have a view root this is it
+ if (mViewRoot == null) {
+ mViewRoot = topLayout;
+ } else {
+ LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
+ LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
+ layoutParams.weight = 1;
+ topLayout.setLayoutParams(layoutParams);
+
+ // this is the case of soft buttons + vertical bar.
+ // this top layout is the first layout in the horizontal layout. see above)
+ mViewRoot.addView(topLayout, 0);
+ }
if (mStatusBarSize > 0) {
// system bar
try {
- PhoneSystemBar systemBar = new PhoneSystemBar(context,
- params.getDensity());
+ StatusBar systemBar = new StatusBar(context, hardwareConfig.getDensity());
systemBar.setLayoutParams(
new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, mStatusBarSize));
@@ -280,7 +331,7 @@
if (mActionBarSize > 0) {
try {
FakeActionBar actionBar = new FakeActionBar(context,
- params.getDensity(),
+ hardwareConfig.getDensity(),
params.getAppLabel(), params.getAppIcon());
actionBar.setLayoutParams(
new LinearLayout.LayoutParams(
@@ -292,7 +343,7 @@
} else if (mTitleBarSize > 0) {
try {
TitleBar titleBar = new TitleBar(context,
- params.getDensity(), params.getAppLabel());
+ hardwareConfig.getDensity(), params.getAppLabel());
titleBar.setLayoutParams(
new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, mTitleBarSize));
@@ -310,15 +361,16 @@
mContentRoot.setLayoutParams(layoutParams);
backgroundLayout.addView(mContentRoot);
- if (mSystemBarSize > 0) {
+ if (mNavigationBarOrientation == LinearLayout.HORIZONTAL &&
+ mNavigationBarSize > 0) {
// system bar
try {
- TabletSystemBar systemBar = new TabletSystemBar(context,
- params.getDensity());
- systemBar.setLayoutParams(
+ NavigationBar navigationBar = new NavigationBar(context,
+ hardwareConfig.getDensity(), LinearLayout.HORIZONTAL);
+ navigationBar.setLayoutParams(
new LinearLayout.LayoutParams(
- LayoutParams.MATCH_PARENT, mSystemBarSize));
- topLayout.addView(systemBar);
+ LayoutParams.MATCH_PARENT, mNavigationBarSize));
+ topLayout.addView(navigationBar);
} catch (XmlPullParserException e) {
}
@@ -346,7 +398,7 @@
// get the background drawable
if (mWindowBackground != null && backgroundView != null) {
Drawable d = ResourceHelper.getDrawable(mWindowBackground, context);
- backgroundView.setBackgroundDrawable(d);
+ backgroundView.setBackground(d);
}
return SUCCESS.createResult();
@@ -389,13 +441,14 @@
}
RenderingMode renderingMode = params.getRenderingMode();
+ HardwareConfig hardwareConfig = params.getHardwareConfig();
// only do the screen measure when needed.
boolean newRenderSize = false;
if (mMeasuredScreenWidth == -1) {
newRenderSize = true;
- mMeasuredScreenWidth = params.getScreenWidth();
- mMeasuredScreenHeight = params.getScreenHeight();
+ mMeasuredScreenWidth = hardwareConfig.getScreenWidth();
+ mMeasuredScreenHeight = hardwareConfig.getScreenHeight();
if (renderingMode != RenderingMode.NORMAL) {
int widthMeasureSpecMode = renderingMode.isHorizExpand() ?
@@ -495,11 +548,11 @@
// create an Android bitmap around the BufferedImage
Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
- true /*isMutable*/, params.getDensity());
+ true /*isMutable*/, hardwareConfig.getDensity());
// create a Canvas around the Android bitmap
mCanvas = new Canvas(bitmap);
- mCanvas.setDensity(params.getDensity().getDpiValue());
+ mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue());
}
if (freshRender && newImage == false) {
@@ -972,30 +1025,28 @@
}
}
- private boolean isTabletUi() {
- return getParams().getConfigScreenSize() == ScreenSize.XLARGE;
+ private boolean hasSoftwareButtons() {
+ return getParams().getHardwareConfig().hasSoftwareButtons();
}
private void findStatusBar(RenderResources resources, DisplayMetrics metrics) {
- if (isTabletUi() == false) {
- boolean windowFullscreen = getBooleanThemeValue(resources,
- "windowFullscreen", false /*defaultValue*/);
+ boolean windowFullscreen = getBooleanThemeValue(resources,
+ "windowFullscreen", false /*defaultValue*/);
- if (windowFullscreen == false && mWindowIsFloating == false) {
- // default value
- mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
+ if (windowFullscreen == false && mWindowIsFloating == false) {
+ // default value
+ mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
- // get the real value
- ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
- "status_bar_height");
+ // get the real value
+ ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
+ "status_bar_height");
- if (value != null) {
- TypedValue typedValue = ResourceHelper.getValue("status_bar_height",
- value.getValue(), true /*requireUnit*/);
- if (typedValue != null) {
- // compute the pixel value based on the display metrics
- mStatusBarSize = (int)typedValue.getDimension(metrics);
- }
+ if (value != null) {
+ TypedValue typedValue = ResourceHelper.getValue("status_bar_height",
+ value.getValue(), true /*requireUnit*/);
+ if (typedValue != null) {
+ // compute the pixel value based on the display metrics
+ mStatusBarSize = (int)typedValue.getDimension(metrics);
}
}
}
@@ -1062,22 +1113,48 @@
}
}
- private void findSystemBar(RenderResources resources, DisplayMetrics metrics) {
- if (isTabletUi() && mWindowIsFloating == false) {
+ private void findNavigationBar(RenderResources resources, DisplayMetrics metrics) {
+ if (hasSoftwareButtons() && mWindowIsFloating == false) {
// default value
- mSystemBarSize = 48; // ??
+ mNavigationBarSize = 48; // ??
+
+ HardwareConfig hardwareConfig = getParams().getHardwareConfig();
+
+ boolean barOnBottom = true;
+
+ if (hardwareConfig.getOrientation() == ScreenOrientation.LANDSCAPE) {
+ // compute the dp of the screen.
+ int shortSize = hardwareConfig.getScreenHeight();
+
+ // compute in dp
+ int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / hardwareConfig.getDensity().getDpiValue();
+
+ if (shortSizeDp < 600) {
+ // 0-599dp: "phone" UI with bar on the side
+ barOnBottom = false;
+ } else {
+ // 600+dp: "tablet" UI with bar on the bottom
+ barOnBottom = true;
+ }
+ }
+
+ if (barOnBottom) {
+ mNavigationBarOrientation = LinearLayout.HORIZONTAL;
+ } else {
+ mNavigationBarOrientation = LinearLayout.VERTICAL;
+ }
// get the real value
ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
- "status_bar_height");
+ barOnBottom ? "navigation_bar_height" : "navigation_bar_width");
if (value != null) {
- TypedValue typedValue = ResourceHelper.getValue("status_bar_height",
+ TypedValue typedValue = ResourceHelper.getValue("navigation_bar_height",
value.getValue(), true /*requireUnit*/);
if (typedValue != null) {
// compute the pixel value based on the display metrics
- mSystemBarSize = (int)typedValue.getDimension(metrics);
+ mNavigationBarSize = (int)typedValue.getDimension(metrics);
}
}
}
diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java
index 93ab4a4..0b0d7388e 100644
--- a/wifi/java/android/net/wifi/WifiMonitor.java
+++ b/wifi/java/android/net/wifi/WifiMonitor.java
@@ -178,6 +178,7 @@
private static final String P2P_GO_NEG_SUCCESS_STR = "P2P-GO-NEG-SUCCESS";
+ /* P2P-GO-NEG-FAILURE status=x */
private static final String P2P_GO_NEG_FAILURE_STR = "P2P-GO-NEG-FAILURE";
private static final String P2P_GROUP_FORMATION_SUCCESS_STR =
@@ -566,6 +567,26 @@
WifiManager.ERROR, 0));
}
+ /* <event> status=<err> and the special case of <event> reason=FREQ_CONFLICT */
+ private P2pStatus p2pError(String dataString) {
+ P2pStatus err = P2pStatus.UNKNOWN;
+ String[] tokens = dataString.split(" ");
+ if (tokens.length < 2) return err;
+ String[] nameValue = tokens[1].split("=");
+ if (nameValue.length != 2) return err;
+
+ /* Handle the special case of reason=FREQ+CONFLICT */
+ if (nameValue[1].equals("FREQ_CONFLICT")) {
+ return P2pStatus.NO_COMMON_CHANNEL;
+ }
+ try {
+ err = P2pStatus.valueOf(Integer.parseInt(nameValue[1]));
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
+ return err;
+ }
+
/**
* Handle p2p events
*/
@@ -582,11 +603,11 @@
} else if (dataString.startsWith(P2P_GO_NEG_SUCCESS_STR)) {
mStateMachine.sendMessage(P2P_GO_NEGOTIATION_SUCCESS_EVENT);
} else if (dataString.startsWith(P2P_GO_NEG_FAILURE_STR)) {
- mStateMachine.sendMessage(P2P_GO_NEGOTIATION_FAILURE_EVENT);
+ mStateMachine.sendMessage(P2P_GO_NEGOTIATION_FAILURE_EVENT, p2pError(dataString));
} else if (dataString.startsWith(P2P_GROUP_FORMATION_SUCCESS_STR)) {
mStateMachine.sendMessage(P2P_GROUP_FORMATION_SUCCESS_EVENT);
} else if (dataString.startsWith(P2P_GROUP_FORMATION_FAILURE_STR)) {
- mStateMachine.sendMessage(P2P_GROUP_FORMATION_FAILURE_EVENT);
+ mStateMachine.sendMessage(P2P_GROUP_FORMATION_FAILURE_EVENT, p2pError(dataString));
} else if (dataString.startsWith(P2P_GROUP_STARTED_STR)) {
mStateMachine.sendMessage(P2P_GROUP_STARTED_EVENT, new WifiP2pGroup(dataString));
} else if (dataString.startsWith(P2P_GROUP_REMOVED_STR)) {
@@ -595,17 +616,7 @@
mStateMachine.sendMessage(P2P_INVITATION_RECEIVED_EVENT,
new WifiP2pGroup(dataString));
} else if (dataString.startsWith(P2P_INVITATION_RESULT_STR)) {
- String[] tokens = dataString.split(" ");
- if (tokens.length != 2) return;
- String[] nameValue = tokens[1].split("=");
- if (nameValue.length != 2) return;
- P2pStatus err = P2pStatus.UNKNOWN;
- try {
- err = P2pStatus.valueOf(Integer.parseInt(nameValue[1]));
- } catch (NumberFormatException e) {
- e.printStackTrace();
- }
- mStateMachine.sendMessage(P2P_INVITATION_RESULT_EVENT, err);
+ mStateMachine.sendMessage(P2P_INVITATION_RESULT_EVENT, p2pError(dataString));
} else if (dataString.startsWith(P2P_PROV_DISC_PBC_REQ_STR)) {
mStateMachine.sendMessage(P2P_PROV_DISC_PBC_REQ_EVENT,
new WifiP2pProvDiscEvent(dataString));
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index db539e4..fd76fc8d 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -114,6 +114,7 @@
private final boolean mP2pSupported;
private final AtomicBoolean mP2pConnected = new AtomicBoolean(false);
+ private boolean mTemporarilyDisconnectWifi = false;
private final String mPrimaryDeviceType;
/* Scan results handling */
@@ -358,8 +359,12 @@
static final int CMD_RESET_SUPPLICANT_STATE = BASE + 111;
/* P2p commands */
+ /* We are ok with no response here since we wont do much with it anyway */
public static final int CMD_ENABLE_P2P = BASE + 131;
- public static final int CMD_DISABLE_P2P = BASE + 132;
+ /* In order to shut down supplicant cleanly, we wait till p2p has
+ * been disabled */
+ public static final int CMD_DISABLE_P2P_REQ = BASE + 132;
+ public static final int CMD_DISABLE_P2P_RSP = BASE + 133;
private static final int CONNECT_MODE = 1;
private static final int SCAN_ONLY_MODE = 2;
@@ -457,6 +462,11 @@
private State mDriverStartingState = new DriverStartingState();
/* Driver started */
private State mDriverStartedState = new DriverStartedState();
+ /* Wait until p2p is disabled
+ * This is a special state which is entered right after we exit out of DriverStartedState
+ * before transitioning to another state.
+ */
+ private State mWaitForP2pDisableState = new WaitForP2pDisableState();
/* Driver stopping */
private State mDriverStoppingState = new DriverStoppingState();
/* Driver stopped */
@@ -698,6 +708,7 @@
addState(mDisconnectingState, mConnectModeState);
addState(mDisconnectedState, mConnectModeState);
addState(mWpsRunningState, mConnectModeState);
+ addState(mWaitForP2pDisableState, mSupplicantStartedState);
addState(mDriverStoppingState, mSupplicantStartedState);
addState(mDriverStoppedState, mSupplicantStartedState);
addState(mSupplicantStoppingState, mDefaultState);
@@ -2017,6 +2028,10 @@
NetworkInfo info = (NetworkInfo) message.obj;
mP2pConnected.set(info.isConnected());
break;
+ case WifiP2pService.DISCONNECT_WIFI_REQUEST:
+ mTemporarilyDisconnectWifi = (message.arg1 == 1);
+ replyToMessage(message, WifiP2pService.DISCONNECT_WIFI_RESPONSE);
+ break;
default:
loge("Error! unhandled message" + message);
break;
@@ -2428,7 +2443,11 @@
WifiConfiguration config;
switch(message.what) {
case CMD_STOP_SUPPLICANT: /* Supplicant stopped by user */
- transitionTo(mSupplicantStoppingState);
+ if (mP2pSupported) {
+ transitionTo(mWaitForP2pDisableState);
+ } else {
+ transitionTo(mSupplicantStoppingState);
+ }
break;
case WifiMonitor.SUP_DISCONNECTION_EVENT: /* Supplicant connection lost */
loge("Connection lost, restart supplicant");
@@ -2438,7 +2457,11 @@
handleNetworkDisconnect();
sendSupplicantConnectionChangedBroadcast(false);
mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
- transitionTo(mDriverLoadedState);
+ if (mP2pSupported) {
+ transitionTo(mWaitForP2pDisableState);
+ } else {
+ transitionTo(mDriverLoadedState);
+ }
sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
break;
case WifiMonitor.SCAN_RESULTS_EVENT:
@@ -2833,8 +2856,12 @@
}
mWakeLock.acquire();
mWifiNative.stopDriver();
- transitionTo(mDriverStoppingState);
mWakeLock.release();
+ if (mP2pSupported) {
+ transitionTo(mWaitForP2pDisableState);
+ } else {
+ transitionTo(mDriverStoppingState);
+ }
break;
case CMD_START_PACKET_FILTERING:
if (message.arg1 == MULTICAST_V6) {
@@ -2880,8 +2907,63 @@
mIsRunning = false;
updateBatteryWorkSource(null);
mScanResults = new ArrayList<ScanResult>();
+ }
+ }
- if (mP2pSupported) mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P);
+ class WaitForP2pDisableState extends State {
+ private State mTransitionToState;
+ @Override
+ public void enter() {
+ if (DBG) log(getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+ switch (getCurrentMessage().what) {
+ case WifiMonitor.SUP_DISCONNECTION_EVENT:
+ mTransitionToState = mDriverLoadedState;
+ break;
+ case CMD_DELAYED_STOP_DRIVER:
+ mTransitionToState = mDriverStoppingState;
+ break;
+ case CMD_STOP_SUPPLICANT:
+ mTransitionToState = mSupplicantStoppingState;
+ break;
+ default:
+ mTransitionToState = mDriverStoppingState;
+ break;
+ }
+ mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_REQ);
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) log(getName() + message.toString() + "\n");
+ switch(message.what) {
+ case WifiStateMachine.CMD_DISABLE_P2P_RSP:
+ transitionTo(mTransitionToState);
+ break;
+ /* Defer wifi start/shut and driver commands */
+ case CMD_LOAD_DRIVER:
+ case CMD_UNLOAD_DRIVER:
+ case CMD_START_SUPPLICANT:
+ case CMD_STOP_SUPPLICANT:
+ case CMD_START_AP:
+ case CMD_STOP_AP:
+ case CMD_START_DRIVER:
+ case CMD_STOP_DRIVER:
+ case CMD_SET_SCAN_MODE:
+ case CMD_SET_SCAN_TYPE:
+ case CMD_SET_COUNTRY_CODE:
+ case CMD_SET_FREQUENCY_BAND:
+ case CMD_START_PACKET_FILTERING:
+ case CMD_STOP_PACKET_FILTERING:
+ case CMD_START_SCAN:
+ case CMD_DISCONNECT:
+ case CMD_REASSOCIATE:
+ case CMD_RECONNECT:
+ deferMessage(message);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return HANDLED;
}
}
@@ -3030,6 +3112,15 @@
transitionTo(mDisconnectedState);
}
break;
+ case WifiP2pService.DISCONNECT_WIFI_REQUEST:
+ if (message.arg1 == 1) {
+ mWifiNative.disconnect();
+ mTemporarilyDisconnectWifi = true;
+ } else {
+ mWifiNative.reconnect();
+ mTemporarilyDisconnectWifi = false;
+ }
+ break;
/* Do a redundant disconnect without transition */
case CMD_DISCONNECT:
mWifiNative.disconnect();
@@ -3159,6 +3250,13 @@
mWifiNative.disconnect();
transitionTo(mDisconnectingState);
break;
+ case WifiP2pService.DISCONNECT_WIFI_REQUEST:
+ if (message.arg1 == 1) {
+ mWifiNative.disconnect();
+ mTemporarilyDisconnectWifi = true;
+ transitionTo(mDisconnectingState);
+ }
+ break;
case CMD_SET_SCAN_MODE:
if (message.arg1 == SCAN_ONLY_MODE) {
sendMessage(CMD_DISCONNECT);
@@ -3465,6 +3563,13 @@
if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+ // We dont scan frequently if this is a temporary disconnect
+ // due to p2p
+ if (mTemporarilyDisconnectWifi) {
+ mWifiP2pChannel.sendMessage(WifiP2pService.DISCONNECT_WIFI_RESPONSE);
+ return;
+ }
+
mFrameworkScanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(),
Settings.Global.WIFI_FRAMEWORK_SCAN_INTERVAL_MS,
mDefaultFrameworkScanIntervalMs);
@@ -3579,6 +3684,12 @@
sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);
}
+ case CMD_RECONNECT:
+ case CMD_REASSOCIATE:
+ // Drop a third party reconnect/reassociate if we are
+ // tempoarily disconnected for p2p
+ if (mTemporarilyDisconnectWifi) ret = NOT_HANDLED;
+ break;
default:
ret = NOT_HANDLED;
}
diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
index 9c727f9..c8f0712 100644
--- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
@@ -556,8 +556,8 @@
mLinkProperties = (LinkProperties) intent.getParcelableExtra(
WifiManager.EXTRA_LINK_PROPERTIES);
if (mPoorNetworkDetectionEnabled) {
- if (mWifiInfo == null) {
- if (DBG) logd("Ignoring link verification, mWifiInfo is NULL");
+ if (mWifiInfo == null || mCurrentBssid == null) {
+ loge("Ignore, wifiinfo " + mWifiInfo +" bssid " + mCurrentBssid);
sendLinkStatusNotification(true);
} else {
transitionTo(mVerifyingLinkState);
@@ -726,7 +726,7 @@
}
private void handleRssiChange() {
- if (mCurrentSignalLevel <= LINK_MONITOR_LEVEL_THRESHOLD) {
+ if (mCurrentSignalLevel <= LINK_MONITOR_LEVEL_THRESHOLD && mCurrentBssid != null) {
transitionTo(mLinkMonitoringState);
} else {
// stay here
@@ -920,11 +920,15 @@
if (DBG) logd("########################################");
if (isGood) {
mWsmChannel.sendMessage(GOOD_LINK_DETECTED);
- mCurrentBssid.mLastTimeGood = SystemClock.elapsedRealtime();
- logd("Good link notification is sent");
+ if (mCurrentBssid != null) {
+ mCurrentBssid.mLastTimeGood = SystemClock.elapsedRealtime();
+ }
+ if (DBG) logd("Good link notification is sent");
} else {
mWsmChannel.sendMessage(POOR_LINK_DETECTED);
- mCurrentBssid.mLastTimePoor = SystemClock.elapsedRealtime();
+ if (mCurrentBssid != null) {
+ mCurrentBssid.mLastTimePoor = SystemClock.elapsedRealtime();
+ }
logd("Poor link notification is sent");
}
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 70baf13..f0aef92 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -134,6 +134,9 @@
private static final int GROUP_CREATING_WAIT_TIME_MS = 120 * 1000;
private static int mGroupCreatingTimeoutIndex = 0;
+ private static final int DISABLE_P2P_WAIT_TIME_MS = 5 * 1000;
+ private static int mDisableP2pTimeoutIndex = 0;
+
/* Set a two minute discover timeout to avoid STA scans from being blocked */
private static final int DISCOVER_TIMEOUT_S = 120;
@@ -149,9 +152,30 @@
private static final int PEER_CONNECTION_USER_ACCEPT = BASE + 2;
/* User rejected a peer request */
private static final int PEER_CONNECTION_USER_REJECT = BASE + 3;
+ /* User wants to disconnect wifi in favour of p2p */
+ private static final int DROP_WIFI_USER_ACCEPT = BASE + 4;
+ /* User wants to keep his wifi connection and drop p2p */
+ private static final int DROP_WIFI_USER_REJECT = BASE + 5;
+ /* Delayed message to timeout p2p disable */
+ public static final int DISABLE_P2P_TIMED_OUT = BASE + 6;
+
/* Commands to the WifiStateMachine */
- public static final int P2P_CONNECTION_CHANGED = BASE + 11;
+ public static final int P2P_CONNECTION_CHANGED = BASE + 11;
+
+ /* These commands are used to tempoarily disconnect wifi when we detect
+ * a frequency conflict which would make it impossible to have with p2p
+ * and wifi active at the same time.
+ *
+ * If the user chooses to disable wifi tempoarily, we keep wifi disconnected
+ * until the p2p connection is done and terminated at which point we will
+ * bring back wifi up
+ *
+ * DISCONNECT_WIFI_REQUEST
+ * msg.arg1 = 1 enables temporary disconnect and 0 disables it.
+ */
+ public static final int DISCONNECT_WIFI_REQUEST = BASE + 12;
+ public static final int DISCONNECT_WIFI_RESPONSE = BASE + 13;
private final boolean mP2pSupported;
@@ -172,6 +196,8 @@
private NetworkInfo mNetworkInfo;
+ private boolean mTempoarilyDisconnectedWifi = false;
+
/* The transaction Id of service discovery request */
private byte mServiceTransactionId = 0;
@@ -222,7 +248,7 @@
PREVIOUS_PROTOCOL_ERROR,
/* There is no common channels the both devices can use. */
- NO_COMMON_CHANNE,
+ NO_COMMON_CHANNEL,
/* Unknown p2p group. For example, Device A tries to invoke the previous persistent group,
* but device B has removed the specified credential already. */
@@ -257,7 +283,7 @@
case 6:
return PREVIOUS_PROTOCOL_ERROR;
case 7:
- return NO_COMMON_CHANNE;
+ return NO_COMMON_CHANNEL;
case 8:
return UNKNOWN_P2P_GROUP;
case 9:
@@ -346,6 +372,7 @@
= new UserAuthorizingInvitationState();
private ProvisionDiscoveryState mProvisionDiscoveryState = new ProvisionDiscoveryState();
private GroupNegotiationState mGroupNegotiationState = new GroupNegotiationState();
+ private FrequencyConflictState mFrequencyConflictState =new FrequencyConflictState();
private GroupCreatedState mGroupCreatedState = new GroupCreatedState();
private UserAuthorizingJoinState mUserAuthorizingJoinState = new UserAuthorizingJoinState();
@@ -400,6 +427,7 @@
addState(mUserAuthorizingInvitationState, mGroupCreatingState);
addState(mProvisionDiscoveryState, mGroupCreatingState);
addState(mGroupNegotiationState, mGroupCreatingState);
+ addState(mFrequencyConflictState, mGroupCreatingState);
addState(mGroupCreatedState, mP2pEnabledState);
addState(mUserAuthorizingJoinState, mGroupCreatedState);
addState(mOngoingGroupRemovalState, mGroupCreatedState);
@@ -551,16 +579,25 @@
case WifiMonitor.P2P_DEVICE_LOST_EVENT:
case WifiMonitor.P2P_FIND_STOPPED_EVENT:
case WifiMonitor.P2P_SERV_DISC_RESP_EVENT:
- case WifiStateMachine.CMD_ENABLE_P2P:
- case WifiStateMachine.CMD_DISABLE_P2P:
case PEER_CONNECTION_USER_ACCEPT:
case PEER_CONNECTION_USER_REJECT:
+ case DISCONNECT_WIFI_RESPONSE:
+ case DROP_WIFI_USER_ACCEPT:
+ case DROP_WIFI_USER_REJECT:
case GROUP_CREATING_TIMED_OUT:
+ case DISABLE_P2P_TIMED_OUT:
case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
case DhcpStateMachine.CMD_POST_DHCP_ACTION:
case DhcpStateMachine.CMD_ON_QUIT:
case WifiMonitor.P2P_PROV_DISC_FAILURE_EVENT:
break;
+ case WifiStateMachine.CMD_ENABLE_P2P:
+ // Enable is lazy and has no response
+ break;
+ case WifiStateMachine.CMD_DISABLE_P2P_REQ:
+ // If we end up handling in default, p2p is not enabled
+ mWifiChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_RSP);
+ break;
/* unexpected group created, remove */
case WifiMonitor.P2P_GROUP_STARTED_EVENT:
mGroup = (WifiP2pGroup) message.obj;
@@ -663,6 +700,13 @@
class P2pDisablingState extends State {
@Override
+ public void enter() {
+ if (DBG) logd(getName());
+ sendMessageDelayed(obtainMessage(DISABLE_P2P_TIMED_OUT,
+ ++mDisableP2pTimeoutIndex, 0), DISABLE_P2P_WAIT_TIME_MS);
+ }
+
+ @Override
public boolean processMessage(Message message) {
if (DBG) logd(getName() + message.toString());
switch (message.what) {
@@ -671,14 +715,25 @@
transitionTo(mP2pDisabledState);
break;
case WifiStateMachine.CMD_ENABLE_P2P:
- case WifiStateMachine.CMD_DISABLE_P2P:
+ case WifiStateMachine.CMD_DISABLE_P2P_REQ:
deferMessage(message);
break;
+ case DISABLE_P2P_TIMED_OUT:
+ if (mGroupCreatingTimeoutIndex == message.arg1) {
+ loge("P2p disable timed out");
+ transitionTo(mP2pDisabledState);
+ }
+ break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
+
+ @Override
+ public void exit() {
+ mWifiChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_RSP);
+ }
}
class P2pDisabledState extends State {
@@ -702,9 +757,6 @@
mWifiMonitor.startMonitoring();
transitionTo(mP2pEnablingState);
break;
- case WifiStateMachine.CMD_DISABLE_P2P:
- //Nothing to do
- break;
default:
return NOT_HANDLED;
}
@@ -731,7 +783,7 @@
transitionTo(mP2pDisabledState);
break;
case WifiStateMachine.CMD_ENABLE_P2P:
- case WifiStateMachine.CMD_DISABLE_P2P:
+ case WifiStateMachine.CMD_DISABLE_P2P_REQ:
deferMessage(message);
break;
default:
@@ -762,7 +814,7 @@
case WifiStateMachine.CMD_ENABLE_P2P:
//Nothing to do
break;
- case WifiStateMachine.CMD_DISABLE_P2P:
+ case WifiStateMachine.CMD_DISABLE_P2P_REQ:
if (mPeers.clear()) sendP2pPeersChangedBroadcast();
if (mGroups.clear()) sendP2pPersistentGroupsChangedBroadcast();
@@ -1027,20 +1079,7 @@
// remain at this state.
}
break;
- case WifiMonitor.P2P_GROUP_STARTED_EVENT:
- mGroup = (WifiP2pGroup) message.obj;
- if (DBG) logd(getName() + " group started");
-
- if (mGroup.getNetworkId() == WifiP2pGroup.PERSISTENT_NET_ID) {
- // This is an invocation case.
- mAutonomousGroup = false;
- deferMessage(message);
- transitionTo(mGroupNegotiationState);
- } else {
- return NOT_HANDLED;
- }
- break;
- default:
+ default:
return NOT_HANDLED;
}
return HANDLED;
@@ -1074,6 +1113,10 @@
// mSavedPeerConfig can be empty
if (mSavedPeerConfig != null &&
!mSavedPeerConfig.deviceAddress.equals(device.deviceAddress)) {
+ if (DBG) {
+ logd("mSavedPeerConfig " + mSavedPeerConfig.deviceAddress +
+ "device " + device.deviceAddress);
+ }
// Do the regular device lost handling
ret = NOT_HANDLED;
break;
@@ -1269,6 +1312,12 @@
transitionTo(mGroupCreatedState);
break;
case WifiMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT:
+ P2pStatus status = (P2pStatus) message.obj;
+ if (status == P2pStatus.NO_COMMON_CHANNEL) {
+ transitionTo(mFrequencyConflictState);
+ break;
+ }
+ /* continue with group removal handling */
case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
if (DBG) logd(getName() + " go failure");
handleGroupCreationFailure();
@@ -1278,9 +1327,14 @@
// a group removed event. Flushing things at group formation
// failure causes supplicant issues. Ignore right now.
case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT:
+ status = (P2pStatus) message.obj;
+ if (status == P2pStatus.NO_COMMON_CHANNEL) {
+ transitionTo(mFrequencyConflictState);
+ break;
+ }
break;
case WifiMonitor.P2P_INVITATION_RESULT_EVENT:
- P2pStatus status = (P2pStatus)message.obj;
+ status = (P2pStatus)message.obj;
if (status == P2pStatus.SUCCESS) {
// invocation was succeeded.
// wait P2P_GROUP_STARTED_EVENT.
@@ -1300,6 +1354,8 @@
handleGroupCreationFailure();
transitionTo(mInactiveState);
}
+ } else if (status == P2pStatus.NO_COMMON_CHANNEL) {
+ transitionTo(mFrequencyConflictState);
} else {
handleGroupCreationFailure();
transitionTo(mInactiveState);
@@ -1312,7 +1368,90 @@
}
}
+ class FrequencyConflictState extends State {
+ private AlertDialog mFrequencyConflictDialog;
+ @Override
+ public void enter() {
+ if (DBG) logd(getName());
+ notifyFrequencyConflict();
+ }
+ private void notifyFrequencyConflict() {
+ logd("Notify frequency conflict");
+ Resources r = Resources.getSystem();
+
+ AlertDialog dialog = new AlertDialog.Builder(mContext)
+ .setMessage(r.getString(R.string.wifi_p2p_frequency_conflict_message,
+ getDeviceName(mSavedPeerConfig.deviceAddress)))
+ .setPositiveButton(r.getString(R.string.dlg_ok), new OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ sendMessage(DROP_WIFI_USER_ACCEPT);
+ }
+ })
+ .setNegativeButton(r.getString(R.string.decline), new OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ sendMessage(DROP_WIFI_USER_REJECT);
+ }
+ })
+ .setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface arg0) {
+ sendMessage(DROP_WIFI_USER_REJECT);
+ }
+ })
+ .create();
+
+ dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ dialog.show();
+ mFrequencyConflictDialog = dialog;
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) logd(getName() + message.toString());
+ switch (message.what) {
+ case WifiMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT:
+ case WifiMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT:
+ loge(getName() + "group sucess during freq conflict!");
+ break;
+ case WifiMonitor.P2P_GROUP_STARTED_EVENT:
+ loge(getName() + "group started after freq conflict, handle anyway");
+ deferMessage(message);
+ transitionTo(mGroupNegotiationState);
+ break;
+ case WifiMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT:
+ case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
+ case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT:
+ // Ignore failures since we retry again
+ break;
+ case DROP_WIFI_USER_REJECT:
+ // User rejected dropping wifi in favour of p2p
+ handleGroupCreationFailure();
+ transitionTo(mInactiveState);
+ break;
+ case DROP_WIFI_USER_ACCEPT:
+ // User accepted dropping wifi in favour of p2p
+ mWifiChannel.sendMessage(WifiP2pService.DISCONNECT_WIFI_REQUEST, 1);
+ mTempoarilyDisconnectedWifi = true;
+ break;
+ case DISCONNECT_WIFI_RESPONSE:
+ // Got a response from wifistatemachine, retry p2p
+ if (DBG) logd(getName() + "Wifi disconnected, retry p2p");
+ transitionTo(mInactiveState);
+ sendMessage(WifiP2pManager.CONNECT, mSavedPeerConfig);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return HANDLED;
+ }
+
+ public void exit() {
+ if (mFrequencyConflictDialog != null) mFrequencyConflictDialog.dismiss();
+ }
+ }
class GroupCreatedState extends State {
@Override
@@ -1326,6 +1465,12 @@
if (mGroup.isGroupOwner()) {
setWifiP2pInfoOnGroupFormation(SERVER_ADDRESS);
}
+
+ // In case of a negotiation group, connection changed is sent
+ // after a client joins. For autonomous, send now
+ if (mAutonomousGroup) {
+ sendP2pConnectionChangedBroadcast();
+ }
}
@Override
@@ -1340,7 +1485,11 @@
deviceAddress.equals(mSavedProvDiscDevice.deviceAddress)) {
mSavedProvDiscDevice = null;
}
- mGroup.addClient(mPeers.get(deviceAddress));
+ if (mPeers.get(deviceAddress) != null) {
+ mGroup.addClient(mPeers.get(deviceAddress));
+ } else {
+ mGroup.addClient(deviceAddress);
+ }
mPeers.updateStatus(deviceAddress, WifiP2pDevice.CONNECTED);
if (DBG) logd(getName() + " ap sta connected");
sendP2pPeersChangedBroadcast();
@@ -1421,7 +1570,7 @@
}
// Do the regular device lost handling
return NOT_HANDLED;
- case WifiStateMachine.CMD_DISABLE_P2P:
+ case WifiStateMachine.CMD_DISABLE_P2P_REQ:
sendMessage(WifiP2pManager.REMOVE_GROUP);
deferMessage(message);
break;
@@ -2195,6 +2344,11 @@
mPeersLostDuringConnection.clear();
mServiceDiscReqId = null;
if (changed) sendP2pPeersChangedBroadcast();
+
+ if (mTempoarilyDisconnectedWifi) {
+ mWifiChannel.sendMessage(WifiP2pService.DISCONNECT_WIFI_REQUEST, 0);
+ mTempoarilyDisconnectedWifi = false;
+ }
}
//State machine initiated requests can have replyTo set to null indicating