Merge "Import translations. DO NOT MERGE" into jb-mr1-dev
diff --git a/Android.mk b/Android.mk
index be98487..d38150f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -429,6 +429,7 @@
-since ./frameworks/base/api/14.txt 14 \
-since ./frameworks/base/api/15.txt 15 \
-since ./frameworks/base/api/16.txt 16 \
+ -since ./frameworks/base/api/17.txt 17 \
-werror -hide 113 \
-overview $(LOCAL_PATH)/core/java/overview.html
@@ -539,7 +540,7 @@
## SDK version identifiers used in the published docs
# major[.minor] version for current SDK. (full releases only)
-framework_docs_SDK_VERSION:=4.1
+framework_docs_SDK_VERSION:=4.2
# release version (ie "Release x") (full releases only)
framework_docs_SDK_REL_ID:=1
diff --git a/api/current.txt b/api/current.txt
index e8f911b..1de68ed 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5777,6 +5777,8 @@
field public static final java.lang.String ACTION_DEVICE_STORAGE_OK = "android.intent.action.DEVICE_STORAGE_OK";
field public static final java.lang.String ACTION_DIAL = "android.intent.action.DIAL";
field public static final java.lang.String ACTION_DOCK_EVENT = "android.intent.action.DOCK_EVENT";
+ field public static final java.lang.String ACTION_DREAMING_STARTED = "android.intent.action.DREAMING_STARTED";
+ field public static final java.lang.String ACTION_DREAMING_STOPPED = "android.intent.action.DREAMING_STOPPED";
field public static final java.lang.String ACTION_EDIT = "android.intent.action.EDIT";
field public static final java.lang.String ACTION_EXTERNAL_APPLICATIONS_AVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE";
field public static final java.lang.String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE";
@@ -11750,6 +11752,7 @@
method public void removeUserRoute(android.media.MediaRouter.UserRouteInfo);
method public void selectRoute(int, android.media.MediaRouter.RouteInfo);
field public static final int ROUTE_TYPE_LIVE_AUDIO = 1; // 0x1
+ field public static final int ROUTE_TYPE_LIVE_VIDEO = 2; // 0x2
field public static final int ROUTE_TYPE_USER = 8388608; // 0x800000
}
@@ -11798,6 +11801,7 @@
method public int getVolume();
method public int getVolumeHandling();
method public int getVolumeMax();
+ method public boolean isEnabled();
method public void requestSetVolume(int);
method public void requestUpdateVolume(int);
method public void setTag(java.lang.Object);
@@ -20315,8 +20319,8 @@
package android.service.dreams {
- public class Dream extends android.app.Service implements android.view.Window.Callback {
- ctor public Dream();
+ public class DreamService extends android.app.Service implements android.view.Window.Callback {
+ ctor public DreamService();
method public void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
method public boolean dispatchKeyEvent(android.view.KeyEvent);
@@ -20356,10 +20360,8 @@
method public void setInteractive(boolean);
method public void setLowProfile(boolean);
method public void setScreenBright(boolean);
- field public static final java.lang.String ACTION_DREAMING_STARTED = "android.intent.action.DREAMING_STARTED";
- field public static final java.lang.String ACTION_DREAMING_STOPPED = "android.intent.action.DREAMING_STOPPED";
- field public static final java.lang.String CATEGORY_DREAM = "android.intent.category.DREAM";
field public static final java.lang.String DREAM_META_DATA = "android.service.dream";
+ field public static final java.lang.String SERVICE_INTERFACE = "android.service.dreams.DreamService";
}
}
@@ -25040,7 +25042,6 @@
method public boolean isInEditMode();
method public boolean isInTouchMode();
method public boolean isLayoutRequested();
- method public boolean isLayoutRtl();
method public boolean isLongClickable();
method public boolean isOpaque();
method protected boolean isPaddingOffsetRequired();
@@ -25678,7 +25679,6 @@
method public int getLayoutDirection();
method public int getMarginEnd();
method public int getMarginStart();
- method protected boolean isLayoutRtl();
method public boolean isMarginRelative();
method public void setLayoutDirection(int);
method public void setMarginEnd(int);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 396b32f..3df88bb 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -127,6 +127,8 @@
runSetDebugApp();
} else if (op.equals("clear-debug-app")) {
runClearDebugApp();
+ } else if (op.equals("bug-report")) {
+ runBugReport();
} else if (op.equals("monitor")) {
runMonitor();
} else if (op.equals("screen-compat")) {
@@ -844,6 +846,11 @@
mAm.setDebugApp(null, false, true);
}
+ private void runBugReport() throws Exception {
+ mAm.requestBugReport();
+ System.out.println("Your lovely bug report is being created; please be patient.");
+ }
+
private void runSwitchUser() throws Exception {
String user = nextArgRequired();
mAm.switchUser(Integer.parseInt(user));
@@ -1508,6 +1515,9 @@
"\n" +
"am clear-debug-app: clear the previously set-debug-app.\n" +
"\n" +
+ "am bug-report: request bug report generation; will launch UI\n" +
+ " when done to select where it should be delivered." +
+ "\n" +
"am monitor: start monitoring for crashes or ANRs.\n" +
" --gdb: start gdbserv on the given port at crash/ANR\n" +
"\n" +
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index a9945b7..396771f 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -447,6 +447,16 @@
}
}
+ /* add in size of any libraries */
+ if (!create_pkg_path_in_dir(path, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) {
+ d = opendir(path);
+ if (d != NULL) {
+ dfd = dirfd(d);
+ codesize += calculate_dir_size(dfd);
+ closedir(d);
+ }
+ }
+
/* compute asec size if it is given
*/
if (asecpath != NULL && asecpath[0] != '!') {
@@ -474,21 +484,33 @@
if (de->d_type == DT_DIR) {
int subfd;
+ int64_t statsize = 0;
+ int64_t dirsize = 0;
/* always skip "." and ".." */
if (name[0] == '.') {
if (name[1] == 0) continue;
if ((name[1] == '.') && (name[2] == 0)) continue;
}
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ statsize = stat_size(&s);
+ }
subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
if (subfd >= 0) {
- int64_t size = calculate_dir_size(subfd);
- if (!strcmp(name,"lib")) {
- codesize += size;
- } else if(!strcmp(name,"cache")) {
- cachesize += size;
- } else {
- datasize += size;
- }
+ dirsize = calculate_dir_size(subfd);
+ }
+ if(!strcmp(name,"lib")) {
+ codesize += dirsize + statsize;
+ } else if(!strcmp(name,"cache")) {
+ cachesize += dirsize + statsize;
+ } else {
+ datasize += dirsize + statsize;
+ }
+ } else if (de->d_type == DT_LNK && !strcmp(name,"lib")) {
+ // This is the symbolic link to the application's library
+ // code. We'll count this as code instead of data, since
+ // it is not something that the app creates.
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ codesize += stat_size(&s);
}
} else {
if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 5f898c2..c455b7d 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -924,7 +924,7 @@
PackageInstallObserver obs = new PackageInstallObserver();
try {
VerificationParams verificationParams = new VerificationParams(verificationURI,
- originatingURI, referrerURI, null);
+ originatingURI, referrerURI, VerificationParams.NO_UID, null);
mPm.installPackageWithVerificationAndEncryption(apkURI, obs, installFlags,
installerPackageName, verificationParams, encryptionParams);
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 9874b0b..83acb4d 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1783,6 +1783,12 @@
return true;
}
+ case REQUEST_BUG_REPORT_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ requestBugReport();
+ return true;
+ }
+
}
return super.onTransact(code, data, reply, flags);
@@ -4066,5 +4072,15 @@
reply.recycle();
}
+ public void requestBugReport() throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(REQUEST_BUG_REPORT_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 9454636..3124671 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -361,6 +361,8 @@
public void registerUserSwitchObserver(IUserSwitchObserver observer) throws RemoteException;
public void unregisterUserSwitchObserver(IUserSwitchObserver observer) throws RemoteException;
+ public void requestBugReport() throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -613,4 +615,5 @@
int REGISTER_USER_SWITCH_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+154;
int UNREGISTER_USER_SWITCH_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+155;
int GET_RUNNING_USER_IDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+156;
+ int REQUEST_BUG_REPORT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+157;
}
diff --git a/core/java/android/app/MediaRouteButton.java b/core/java/android/app/MediaRouteButton.java
index cfc8bbd..a9ccef0 100644
--- a/core/java/android/app/MediaRouteButton.java
+++ b/core/java/android/app/MediaRouteButton.java
@@ -221,21 +221,28 @@
void updateRouteCount() {
final int N = mRouter.getRouteCount();
int count = 0;
+ boolean hasVideoRoutes = false;
for (int i = 0; i < N; i++) {
final RouteInfo route = mRouter.getRouteAt(i);
- if ((route.getSupportedTypes() & mRouteTypes) != 0) {
+ final int routeTypes = route.getSupportedTypes();
+ if ((routeTypes & mRouteTypes) != 0) {
if (route instanceof RouteGroup) {
count += ((RouteGroup) route).getRouteCount();
} else {
count++;
}
+ if ((routeTypes & MediaRouter.ROUTE_TYPE_LIVE_VIDEO) != 0) {
+ hasVideoRoutes = true;
+ }
}
}
setEnabled(count != 0);
- // Only allow toggling if we have more than just user routes
- mToggleMode = count == 2 && (mRouteTypes & MediaRouter.ROUTE_TYPE_LIVE_AUDIO) != 0;
+ // Only allow toggling if we have more than just user routes.
+ // Don't toggle if we support video routes, we may have to let the dialog scan.
+ mToggleMode = count == 2 && (mRouteTypes & MediaRouter.ROUTE_TYPE_LIVE_AUDIO) != 0 &&
+ !hasVideoRoutes;
}
@Override
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 1e61e10..3d656c7 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -97,13 +97,13 @@
}
/**
- * Expand the notifications.
+ * Expand the notifications panel.
*/
- public void expandNotifications() {
+ public void expandNotificationsPanel() {
try {
final IStatusBarService svc = getService();
if (svc != null) {
- svc.expandNotifications();
+ svc.expandNotificationsPanel();
}
} catch (RemoteException ex) {
// system process is dead anyway.
@@ -112,13 +112,13 @@
}
/**
- * Collapse the notifications.
+ * Collapse the notifications and settings panels.
*/
- public void collapseNotifications() {
+ public void collapsePanels() {
try {
final IStatusBarService svc = getService();
if (svc != null) {
- svc.collapseNotifications();
+ svc.collapsePanels();
}
} catch (RemoteException ex) {
// system process is dead anyway.
@@ -127,28 +127,13 @@
}
/**
- * Expand the quick settings.
+ * Expand the settings panel.
*/
- public void expandQuickSettings() {
+ public void expandSettingsPanel() {
try {
final IStatusBarService svc = getService();
if (svc != null) {
- svc.expandQuickSettings();
- }
- } catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
- }
- }
-
- /**
- * Collapse the quick settings.
- */
- public void collapseQuickSettings() {
- try {
- final IStatusBarService svc = getService();
- if (svc != null) {
- svc.collapseQuickSettings();
+ svc.expandSettingsPanel();
}
} catch (RemoteException ex) {
// system process is dead anyway.
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index b9518b8..d4f6c06 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1305,6 +1305,14 @@
= "android.intent.extra.REFERRER";
/**
+ * Used as an int extra field with {@link #ACTION_INSTALL_PACKAGE} and
+ * {@link} #ACTION_VIEW} to indicate the uid of the package that initiated the install
+ * @hide
+ */
+ public static final String EXTRA_ORIGINATING_UID
+ = "android.intent.extra.ORIGINATING_UID";
+
+ /**
* Used as a boolean extra field with {@link #ACTION_INSTALL_PACKAGE} to install a
* package. Tells the installer UI to skip the confirmation with the user
* if the .apk is replacing an existing one.
@@ -1382,6 +1390,24 @@
public static final String ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON";
/**
+ * Broadcast Action: Sent after the system stops dreaming.
+ *
+ * <p class="note">This is a protected intent that can only be sent by the system.
+ * It is only sent to registered receivers.</p>
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_DREAMING_STOPPED = "android.intent.action.DREAMING_STOPPED";
+
+ /**
+ * Broadcast Action: Sent after the system starts dreaming.
+ *
+ * <p class="note">This is a protected intent that can only be sent by the system.
+ * It is only sent to registered receivers.</p>
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_DREAMING_STARTED = "android.intent.action.DREAMING_STARTED";
+
+ /**
* Broadcast Action: Sent when the user is present after device wakes up (e.g when the
* keyguard is gone).
*
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 0b320f0..b884b98 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -172,10 +172,16 @@
*/
public static final int FLAG_IMMERSIVE = 0x0400;
/**
+ * @hide Bit in {@link #flags}: If set, this component will only be seen
+ * by the primary user. Only works with broadcast receivers. Set from the
+ * {@link android.R.attr#primaryUserOnly} attribute.
+ */
+ public static final int FLAG_PRIMARY_USER_ONLY = 0x20000000;
+ /**
* Bit in {@link #flags}: If set, a single instance of the receiver will
* run for all users on the device. Set from the
* {@link android.R.attr#singleUser} attribute. Note that this flag is
- * only relevent for ActivityInfo structures that are describiner receiver
+ * only relevant for ActivityInfo structures that are describing receiver
* components; it is not applied to activities.
*/
public static final int FLAG_SINGLE_USER = 0x40000000;
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 0a22fca..c2b75f4 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2193,7 +2193,7 @@
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestActivity_singleUser,
false)) {
- a.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
+ a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
if (a.info.exported) {
Slog.w(TAG, "Activity exported request ignored due to singleUser: "
+ a.className + " at " + mArchiveSourcePath + " "
@@ -2202,6 +2202,11 @@
}
setExported = true;
}
+ if (sa.getBoolean(
+ com.android.internal.R.styleable.AndroidManifestActivity_primaryUserOnly,
+ false)) {
+ a.info.flags |= ActivityInfo.FLAG_PRIMARY_USER_ONLY;
+ }
}
sa.recycle();
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 3579977..7b3d8cd 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -34,6 +34,14 @@
public HashSet<String> enabledComponents;
public PackageUserState() {
+ this(true);
+ }
+
+ /** @hide */
+ public PackageUserState(boolean isSystem) {
+ if (!isSystem) {
+ stopped = notLaunched = true;
+ }
installed = true;
enabled = COMPONENT_ENABLED_STATE_DEFAULT;
}
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index ab32523..593f826 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -71,6 +71,9 @@
public long creationTime;
public long lastLoggedInTime;
+ /** User is only partially created. */
+ public boolean partial;
+
public UserInfo(int id, String name, int flags) {
this(id, name, null, flags);
}
@@ -105,6 +108,7 @@
serialNumber = orig.serialNumber;
creationTime = orig.creationTime;
lastLoggedInTime = orig.lastLoggedInTime;
+ partial = orig.partial;
}
public UserHandle getUserHandle() {
@@ -128,6 +132,7 @@
dest.writeInt(serialNumber);
dest.writeLong(creationTime);
dest.writeLong(lastLoggedInTime);
+ dest.writeInt(partial ? 1 : 0);
}
public static final Parcelable.Creator<UserInfo> CREATOR
@@ -148,5 +153,6 @@
serialNumber = source.readInt();
creationTime = source.readLong();
lastLoggedInTime = source.readLong();
+ partial = source.readInt() != 0;
}
}
diff --git a/core/java/android/content/pm/VerificationParams.java b/core/java/android/content/pm/VerificationParams.java
index 6454de0..22e1a85 100644
--- a/core/java/android/content/pm/VerificationParams.java
+++ b/core/java/android/content/pm/VerificationParams.java
@@ -27,6 +27,9 @@
* @hide
*/
public class VerificationParams implements Parcelable {
+ /** A constant used to indicate that a uid value is not present. */
+ public static final int NO_UID = -1;
+
/** What we print out first when toString() is called. */
private static final String TO_STRING_PREFIX = "VerificationParams{";
@@ -39,6 +42,9 @@
/** HTTP referrer URI associated with the originatingURI. */
private final Uri mReferrer;
+ /** UID of the application that the install request originated from. */
+ private final int mOriginatingUid;
+
/** UID of application requesting the install */
private int mInstallerUid;
@@ -57,16 +63,19 @@
* from. May be {@code null}.
* @param referrer HTTP referrer URI associated with the originatingURI.
* May be {@code null}.
+ * @param originatingUid UID of the application that the install request originated
+ * from, or NO_UID if not present
* @param manifestDigest an object that holds the digest of the package
* which can be used to verify ownership. May be {@code null}.
*/
public VerificationParams(Uri verificationURI, Uri originatingURI, Uri referrer,
- ManifestDigest manifestDigest) {
+ int originatingUid, ManifestDigest manifestDigest) {
mVerificationURI = verificationURI;
mOriginatingURI = originatingURI;
mReferrer = referrer;
+ mOriginatingUid = originatingUid;
mManifestDigest = manifestDigest;
- mInstallerUid = -1;
+ mInstallerUid = NO_UID;
}
public Uri getVerificationURI() {
@@ -81,11 +90,16 @@
return mReferrer;
}
+ /** return NO_UID if not available */
+ public int getOriginatingUid() {
+ return mOriginatingUid;
+ }
+
public ManifestDigest getManifestDigest() {
return mManifestDigest;
}
- /** @return -1 when not set */
+ /** @return NO_UID when not set */
public int getInstallerUid() {
return mInstallerUid;
}
@@ -111,31 +125,39 @@
final VerificationParams other = (VerificationParams) o;
- if (mVerificationURI == null && other.mVerificationURI != null) {
- return false;
- }
- if (!mVerificationURI.equals(other.mVerificationURI)) {
+ if (mVerificationURI == null) {
+ if (other.mVerificationURI != null) {
+ return false;
+ }
+ } else if (!mVerificationURI.equals(other.mVerificationURI)) {
return false;
}
- if (mOriginatingURI == null && other.mOriginatingURI != null) {
- return false;
- }
- if (!mOriginatingURI.equals(other.mOriginatingURI)) {
+ if (mOriginatingURI == null) {
+ if (other.mOriginatingURI != null) {
+ return false;
+ }
+ } else if (!mOriginatingURI.equals(other.mOriginatingURI)) {
return false;
}
- if (mReferrer == null && other.mReferrer != null) {
- return false;
- }
- if (!mReferrer.equals(other.mReferrer)) {
+ if (mReferrer == null) {
+ if (other.mReferrer != null) {
+ return false;
+ }
+ } else if (!mReferrer.equals(other.mReferrer)) {
return false;
}
- if (mManifestDigest == null && other.mManifestDigest != null) {
+ if (mOriginatingUid != other.mOriginatingUid) {
return false;
}
- if (mManifestDigest != null && !mManifestDigest.equals(other.mManifestDigest)) {
+
+ if (mManifestDigest == null) {
+ if (other.mManifestDigest != null) {
+ return false;
+ }
+ } else if (!mManifestDigest.equals(other.mManifestDigest)) {
return false;
}
@@ -150,11 +172,12 @@
public int hashCode() {
int hash = 3;
- hash += 5 * (mVerificationURI==null?1:mVerificationURI.hashCode());
- hash += 7 * (mOriginatingURI==null?1:mOriginatingURI.hashCode());
- hash += 11 * (mReferrer==null?1:mReferrer.hashCode());
- hash += 13 * (mManifestDigest==null?1:mManifestDigest.hashCode());
- hash += 17 * mInstallerUid;
+ hash += 5 * (mVerificationURI == null ? 1 : mVerificationURI.hashCode());
+ hash += 7 * (mOriginatingURI == null ? 1 : mOriginatingURI.hashCode());
+ hash += 11 * (mReferrer == null ? 1 : mReferrer.hashCode());
+ hash += 13 * mOriginatingUid;
+ hash += 17 * (mManifestDigest == null ? 1 : mManifestDigest.hashCode());
+ hash += 19 * mInstallerUid;
return hash;
}
@@ -169,6 +192,8 @@
sb.append(mOriginatingURI.toString());
sb.append(",mReferrer=");
sb.append(mReferrer.toString());
+ sb.append(",mOriginatingUid=");
+ sb.append(mOriginatingUid);
sb.append(",mManifestDigest=");
sb.append(mManifestDigest.toString());
sb.append(",mInstallerUid=");
@@ -183,6 +208,7 @@
dest.writeParcelable(mVerificationURI, 0);
dest.writeParcelable(mOriginatingURI, 0);
dest.writeParcelable(mReferrer, 0);
+ dest.writeInt(mOriginatingUid);
dest.writeParcelable(mManifestDigest, 0);
dest.writeInt(mInstallerUid);
}
@@ -192,6 +218,7 @@
mVerificationURI = source.readParcelable(Uri.class.getClassLoader());
mOriginatingURI = source.readParcelable(Uri.class.getClassLoader());
mReferrer = source.readParcelable(Uri.class.getClassLoader());
+ mOriginatingUid = source.readInt();
mManifestDigest = source.readParcelable(ManifestDigest.class.getClassLoader());
mInstallerUid = source.readInt();
}
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index eec19cb..8bfefd4 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -44,7 +44,6 @@
void setPokeLock(int pokey, IBinder lock, String tag);
void setStayOnSetting(int val);
void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs);
- void preventScreenOn(boolean prevent);
// temporarily overrides the screen brightness settings to allow the user to
// see the effect of a settings change without applying it immediately
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index b3ab385..5b49ba3 100755
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -7659,6 +7659,54 @@
public static final int MODE_LARGE = 3;
/**
+ * Constructs the QuickContacts intent with a view's rect.
+ * @hide
+ */
+ public static Intent composeQuickContactsIntent(Context context, View target, Uri lookupUri,
+ int mode, String[] excludeMimes) {
+ // Find location and bounds of target view, adjusting based on the
+ // assumed local density.
+ final float appScale = context.getResources().getCompatibilityInfo().applicationScale;
+ final int[] pos = new int[2];
+ target.getLocationOnScreen(pos);
+
+ final Rect rect = new Rect();
+ rect.left = (int) (pos[0] * appScale + 0.5f);
+ rect.top = (int) (pos[1] * appScale + 0.5f);
+ rect.right = (int) ((pos[0] + target.getWidth()) * appScale + 0.5f);
+ rect.bottom = (int) ((pos[1] + target.getHeight()) * appScale + 0.5f);
+
+ return composeQuickContactsIntent(context, rect, lookupUri, mode, excludeMimes);
+ }
+
+ /**
+ * Constructs the QuickContacts intent.
+ * @hide
+ */
+ public static Intent composeQuickContactsIntent(Context context, Rect target,
+ Uri lookupUri, int mode, String[] excludeMimes) {
+ // When launching from an Activiy, we don't want to start a new task, but otherwise
+ // we *must* start a new task. (Otherwise startActivity() would crash.)
+ Context actualContext = context;
+ while ((actualContext instanceof ContextWrapper)
+ && !(actualContext instanceof Activity)) {
+ actualContext = ((ContextWrapper) actualContext).getBaseContext();
+ }
+ final int intentFlags = (actualContext instanceof Activity)
+ ? Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
+ : Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK;
+
+ // Launch pivot dialog through intent for now
+ final Intent intent = new Intent(ACTION_QUICK_CONTACT).addFlags(intentFlags);
+
+ intent.setData(lookupUri);
+ intent.setSourceBounds(target);
+ intent.putExtra(EXTRA_MODE, mode);
+ intent.putExtra(EXTRA_EXCLUDE_MIMES, excludeMimes);
+ return intent;
+ }
+
+ /**
* Trigger a dialog that lists the various methods of interacting with
* the requested {@link Contacts} entry. This may be based on available
* {@link ContactsContract.Data} rows under that contact, and may also
@@ -7683,20 +7731,10 @@
*/
public static void showQuickContact(Context context, View target, Uri lookupUri, int mode,
String[] excludeMimes) {
- // Find location and bounds of target view, adjusting based on the
- // assumed local density.
- final float appScale = context.getResources().getCompatibilityInfo().applicationScale;
- final int[] pos = new int[2];
- target.getLocationOnScreen(pos);
-
- final Rect rect = new Rect();
- rect.left = (int) (pos[0] * appScale + 0.5f);
- rect.top = (int) (pos[1] * appScale + 0.5f);
- rect.right = (int) ((pos[0] + target.getWidth()) * appScale + 0.5f);
- rect.bottom = (int) ((pos[1] + target.getHeight()) * appScale + 0.5f);
-
// Trigger with obtained rectangle
- showQuickContact(context, rect, lookupUri, mode, excludeMimes);
+ Intent intent = composeQuickContactsIntent(context, target, lookupUri, mode,
+ excludeMimes);
+ context.startActivity(intent);
}
/**
@@ -7727,25 +7765,9 @@
*/
public static void showQuickContact(Context context, Rect target, Uri lookupUri, int mode,
String[] excludeMimes) {
- // When launching from an Activiy, we don't want to start a new task, but otherwise
- // we *must* start a new task. (Otherwise startActivity() would crash.)
- Context actualContext = context;
- while ((actualContext instanceof ContextWrapper)
- && !(actualContext instanceof Activity)) {
- actualContext = ((ContextWrapper) actualContext).getBaseContext();
- }
- final int intentFlags = (actualContext instanceof Activity)
- ? Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
- : Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK;
-
- // Launch pivot dialog through intent for now
- final Intent intent = new Intent(ACTION_QUICK_CONTACT).addFlags(intentFlags);
-
- intent.setData(lookupUri);
- intent.setSourceBounds(target);
- intent.putExtra(EXTRA_MODE, mode);
- intent.putExtra(EXTRA_EXCLUDE_MIMES, excludeMimes);
- context.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ Intent intent = composeQuickContactsIntent(context, target, lookupUri, mode,
+ excludeMimes);
+ context.startActivity(intent);
}
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 550713d..8825f58 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3141,6 +3141,12 @@
public static final String DEVICE_PROVISIONED = Global.DEVICE_PROVISIONED;
/**
+ * Whether the current user has been set up via setup wizard (0 = false, 1 = true)
+ * @hide
+ */
+ public static final String USER_SETUP_COMPLETE = "user_setup_complete";
+
+ /**
* List of input methods that are currently enabled. This is a string
* containing the IDs of all enabled input methods, each ID separated
* by ':'.
@@ -4619,13 +4625,6 @@
public static final String SMS_SHORT_CODE_RULE = "sms_short_code_rule";
/**
- * Prefix for SMS short code regex patterns (country code is appended).
- * @see com.android.internal.telephony.SmsUsageMonitor
- * @hide
- */
- public static final String SMS_SHORT_CODES_PREFIX = "sms_short_codes_";
-
- /**
* Used to disable Tethering on a device - defaults to true
* @hide
*/
diff --git a/core/java/android/service/dreams/Dream.java b/core/java/android/service/dreams/Dream.java
index 590acfa..4e8b05b 100644
--- a/core/java/android/service/dreams/Dream.java
+++ b/core/java/android/service/dreams/Dream.java
@@ -15,625 +15,9 @@
*/
package android.service.dreams;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.app.Service;
-import android.content.Intent;
-import android.graphics.drawable.ColorDrawable;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.ServiceManager;
-import android.util.Slog;
-import android.view.ActionMode;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
-import android.view.accessibility.AccessibilityEvent;
-
-import com.android.internal.policy.PolicyManager;
-
/**
- * Extend this class to implement a custom Dream.
- *
- * <p>Dreams are interactive screensavers launched when a charging device is idle, or docked in a
- * desk dock. Dreams provide another modality for apps to express themselves, tailored for
- * an exhibition/lean-back experience.</p>
- *
- * <p>Dreams should be declared in the manifest as follows:</p>
- * <pre>
- * {@code
- * <service
- * android:name=".MyDream"
- * android:exported="true"
- * android:icon="@drawable/my_icon"
- * android:label="@string/my_dream_label" >
- *
- * <intent-filter>
- * <action android:name="android.intent.action.MAIN" />
- * <category android:name="android.intent.category.DREAM" />
- * </intent-filter>
- *
- * <!-- Point to additional information for this dream (optional) -->
- * <meta-data
- * android:name="android.service.dream"
- * android:resource="@xml/my_dream" />
- * </service>
- * }
- * </pre>
+ * @hide
+ * Temporarily needed to not break existing apps.
*/
-public class Dream extends Service implements Window.Callback {
- private final static boolean DEBUG = true;
- private final String TAG = Dream.class.getSimpleName() + "[" + getClass().getSimpleName() + "]";
-
- /**
- * The name of the dream manager service.
- * @hide
- */
- public static final String DREAM_SERVICE = "dreams";
-
- /**
- * Used with {@link Intent#ACTION_MAIN} to declare the necessary intent-filter for a dream.
- *
- * @see Dream
- */
- @SdkConstant(SdkConstantType.INTENT_CATEGORY)
- public static final String CATEGORY_DREAM =
- "android.intent.category.DREAM";
-
- /**
- * Name under which a Dream publishes information about itself.
- * This meta-data must reference an XML resource containing
- * a <code><{@link android.R.styleable#Dream dream}></code>
- * tag.
- */
- public static final String DREAM_META_DATA = "android.service.dream";
-
- /**
- * Broadcast Action: Sent after the system starts dreaming.
- *
- * <p class="note">This is a protected intent that can only be sent by the system.
- * It is only sent to registered receivers.</p>
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_DREAMING_STARTED = "android.intent.action.DREAMING_STARTED";
-
- /**
- * Broadcast Action: Sent after the system stops dreaming.
- *
- * <p class="note">This is a protected intent that can only be sent by the system.
- * It is only sent to registered receivers.</p>
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_DREAMING_STOPPED = "android.intent.action.DREAMING_STOPPED";
-
- private final Handler mHandler = new Handler();
- private IBinder mWindowToken;
- private Window mWindow;
- private WindowManager mWindowManager;
- private IDreamManager mSandman;
- private boolean mInteractive = false;
- private boolean mLowProfile = true;
- private boolean mFullscreen = false;
- private boolean mScreenBright = false;
- private boolean mFinished;
-
- // begin Window.Callback methods
- /** {@inheritDoc} */
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- // TODO: create more flexible version of mInteractive that allows use of KEYCODE_BACK
- if (!mInteractive) {
- if (DEBUG) Slog.v(TAG, "Finishing on keyEvent");
- safelyFinish();
- return true;
- } else if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
- if (DEBUG) Slog.v(TAG, "Finishing on back key");
- safelyFinish();
- return true;
- }
- return mWindow.superDispatchKeyEvent(event);
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean dispatchKeyShortcutEvent(KeyEvent event) {
- if (!mInteractive) {
- if (DEBUG) Slog.v(TAG, "Finishing on keyShortcutEvent");
- safelyFinish();
- return true;
- }
- return mWindow.superDispatchKeyShortcutEvent(event);
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean dispatchTouchEvent(MotionEvent event) {
- // TODO: create more flexible version of mInteractive that allows clicks
- // but finish()es on any other kind of activity
- if (!mInteractive) {
- if (DEBUG) Slog.v(TAG, "Finishing on touchEvent");
- safelyFinish();
- return true;
- }
- return mWindow.superDispatchTouchEvent(event);
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean dispatchTrackballEvent(MotionEvent event) {
- if (!mInteractive) {
- if (DEBUG) Slog.v(TAG, "Finishing on trackballEvent");
- safelyFinish();
- return true;
- }
- return mWindow.superDispatchTrackballEvent(event);
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean dispatchGenericMotionEvent(MotionEvent event) {
- if (!mInteractive) {
- if (DEBUG) Slog.v(TAG, "Finishing on genericMotionEvent");
- safelyFinish();
- return true;
- }
- return mWindow.superDispatchGenericMotionEvent(event);
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override
- public View onCreatePanelView(int featureId) {
- return null;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean onCreatePanelMenu(int featureId, Menu menu) {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean onPreparePanel(int featureId, View view, Menu menu) {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean onMenuOpened(int featureId, Menu menu) {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean onMenuItemSelected(int featureId, MenuItem item) {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override
- public void onWindowAttributesChanged(LayoutParams attrs) {
- }
-
- /** {@inheritDoc} */
- @Override
- public void onContentChanged() {
- }
-
- /** {@inheritDoc} */
- @Override
- public void onWindowFocusChanged(boolean hasFocus) {
- }
-
- /** {@inheritDoc} */
- @Override
- public void onAttachedToWindow() {
- }
-
- /** {@inheritDoc} */
- @Override
- public void onDetachedFromWindow() {
- }
-
- /** {@inheritDoc} */
- @Override
- public void onPanelClosed(int featureId, Menu menu) {
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean onSearchRequested() {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override
- public ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback callback) {
- return null;
- }
-
- /** {@inheritDoc} */
- @Override
- public void onActionModeStarted(ActionMode mode) {
- }
-
- /** {@inheritDoc} */
- @Override
- public void onActionModeFinished(ActionMode mode) {
- }
- // end Window.Callback methods
-
- // begin public api
- /**
- * Retrieves the current {@link android.view.WindowManager} for the dream.
- * Behaves similarly to {@link android.app.Activity#getWindowManager()}.
- *
- * @return The current window manager, or null if the dream is not started.
- */
- public WindowManager getWindowManager() {
- return mWindowManager;
- }
-
- /**
- * Retrieves the current {@link android.view.Window} for the dream.
- * Behaves similarly to {@link android.app.Activity#getWindow()}.
- *
- * @return The current window, or null if the dream is not started.
- */
- public Window getWindow() {
- return mWindow;
- }
-
- /**
- * Inflates a layout resource and set it to be the content view for this Dream.
- * Behaves similarly to {@link android.app.Activity#setContentView(int)}.
- *
- * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
- *
- * @param layoutResID Resource ID to be inflated.
- *
- * @see #setContentView(android.view.View)
- * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
- */
- public void setContentView(int layoutResID) {
- getWindow().setContentView(layoutResID);
- }
-
- /**
- * Sets a view to be the content view for this Dream.
- * Behaves similarly to {@link android.app.Activity#setContentView(android.view.View)},
- * 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.
- *
- * @see #setContentView(int)
- * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
- */
- public void setContentView(View view) {
- getWindow().setContentView(view);
- }
-
- /**
- * 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)}.
- *
- * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
- *
- * @param view The desired content to display.
- * @param params Layout parameters for the view.
- *
- * @see #setContentView(android.view.View)
- * @see #setContentView(int)
- */
- public void setContentView(View view, ViewGroup.LayoutParams params) {
- getWindow().setContentView(view, params);
- }
-
- /**
- * Adds a view to the Dream's window, leaving other content views in place.
- *
- * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
- *
- * @param view The desired content to display.
- * @param params Layout parameters for the view.
- */
- public void addContentView(View view, ViewGroup.LayoutParams params) {
- getWindow().addContentView(view, params);
- }
-
- /**
- * Finds a view that was identified by the id attribute from the XML that
- * was processed in {@link #onCreate}.
- *
- * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
- *
- * @return The view if found or null otherwise.
- */
- public View findViewById(int id) {
- return getWindow().findViewById(id);
- }
-
- /**
- * Marks this dream as interactive to receive input events.
- *
- * <p>Non-interactive dreams (default) will dismiss on the first input event.</p>
- *
- * <p>Interactive dreams should call {@link #finish()} to dismiss themselves.</p>
- *
- * @param interactive True if this dream will handle input events.
- */
- public void setInteractive(boolean interactive) {
- mInteractive = interactive;
- }
-
- /**
- * Returns whether or not this dream is interactive. Defaults to false.
- *
- * @see #setInteractive(boolean)
- */
- public boolean isInteractive() {
- return mInteractive;
- }
-
- /**
- * Sets View.SYSTEM_UI_FLAG_LOW_PROFILE on the content view.
- *
- * @param lowProfile True to set View.SYSTEM_UI_FLAG_LOW_PROFILE
- */
- public void setLowProfile(boolean lowProfile) {
- mLowProfile = lowProfile;
- int flag = View.SYSTEM_UI_FLAG_LOW_PROFILE;
- applySystemUiVisibilityFlags(mLowProfile ? flag : 0, flag);
- }
-
- /**
- * Returns whether or not this dream is in low profile mode. Defaults to true.
- *
- * @see #setLowProfile(boolean)
- */
- public boolean isLowProfile() {
- return getSystemUiVisibilityFlagValue(View.SYSTEM_UI_FLAG_LOW_PROFILE, mLowProfile);
- }
-
- /**
- * Sets View.SYSTEM_UI_FLAG_FULLSCREEN on the content view.
- *
- * @param fullscreen True to set View.SYSTEM_UI_FLAG_FULLSCREEN
- */
- public void setFullscreen(boolean fullscreen) {
- mFullscreen = fullscreen;
- int flag = View.SYSTEM_UI_FLAG_FULLSCREEN;
- applySystemUiVisibilityFlags(mFullscreen ? flag : 0, flag);
- }
-
- /**
- * Returns whether or not this dream is in fullscreen mode. Defaults to false.
- *
- * @see #setFullscreen(boolean)
- */
- public boolean isFullscreen() {
- return getSystemUiVisibilityFlagValue(View.SYSTEM_UI_FLAG_FULLSCREEN, mFullscreen);
- }
-
- /**
- * Marks this dream as keeping the screen bright while dreaming.
- *
- * @param screenBright True to keep the screen bright while dreaming.
- */
- public void setScreenBright(boolean screenBright) {
- mScreenBright = screenBright;
- int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
- applyWindowFlags(mScreenBright ? flag : 0, flag);
- }
-
- /**
- * Returns whether or not this dream keeps the screen bright while dreaming. Defaults to false,
- * allowing the screen to dim if necessary.
- *
- * @see #setScreenBright(boolean)
- */
- public boolean isScreenBright() {
- return getWindowFlagValue(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, mScreenBright);
- }
-
- /**
- * Called when this Dream is constructed. Place your initialization here.
- *
- * <p>Subclasses must call through to the superclass implementation.</p>
- */
- @Override
- public void onCreate() {
- if (DEBUG) Slog.v(TAG, "onCreate() on thread " + Thread.currentThread().getId());
- super.onCreate();
- loadSandman();
- }
-
- /**
- * Called when this Dream is started. The window is created and visible at this point.
- */
- public void onStart() {
- if (DEBUG) Slog.v(TAG, "onStart()");
- // hook for subclasses
- }
-
- /** {@inheritDoc} */
- @Override
- public final IBinder onBind(Intent intent) {
- if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent);
- return new DreamServiceWrapper();
- }
-
- /**
- * Stops the dream, detaches from the window, and wakes up.
- *
- * <p>Subclasses must call through to the superclass implementation.</p>
- *
- * <p>After this method is called, the service will be stopped.</p>
- */
- public void finish() {
- if (DEBUG) Slog.v(TAG, "finish()");
- finishInternal();
- }
-
- /** {@inheritDoc} */
- @Override
- public void onDestroy() {
- if (DEBUG) Slog.v(TAG, "onDestroy()");
- super.onDestroy();
-
- if (DEBUG) Slog.v(TAG, "Removing window");
- try {
- mWindowManager.removeView(mWindow.getDecorView());
- } catch (Throwable t) {
- Slog.w(TAG, "Crashed removing window view", t);
- }
- }
- // end public api
-
- private void loadSandman() {
- mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
- }
-
- private final void attach(IBinder windowToken) {
- if (DEBUG) Slog.v(TAG, "Attached on thread " + Thread.currentThread().getId());
-
- if (mSandman == null) {
- Slog.w(TAG, "No dream manager found, super.onCreate may not have been called");
- loadSandman();
- }
- mWindowToken = windowToken;
- mWindow = PolicyManager.makeNewWindow(this);
- mWindow.setCallback(this);
- mWindow.requestFeature(Window.FEATURE_NO_TITLE);
- mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000));
-
- if (DEBUG) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s",
- windowToken, WindowManager.LayoutParams.TYPE_DREAM));
-
- WindowManager.LayoutParams lp = mWindow.getAttributes();
- lp.type = WindowManager.LayoutParams.TYPE_DREAM;
- lp.token = windowToken;
- lp.windowAnimations = com.android.internal.R.style.Animation_Dream;
- lp.flags |= ( WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
- | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
- | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
- | (mScreenBright ? WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON : 0)
- );
- mWindow.setAttributes(lp);
-
- if (DEBUG) Slog.v(TAG, "Created and attached window: " + mWindow);
-
- mWindow.setWindowManager(null, windowToken, "dream", true);
- mWindowManager = mWindow.getWindowManager();
-
- // now make it visible (on the ui thread)
- mHandler.post(new Runnable(){
- @Override
- public void run() {
- if (DEBUG) Slog.v(TAG, "Window added on thread " + Thread.currentThread().getId());
- try {
- applySystemUiVisibilityFlags(
- (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0)
- | (mFullscreen ? View.SYSTEM_UI_FLAG_FULLSCREEN : 0),
- View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN);
- getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
- } catch (Throwable t) {
- Slog.w("Crashed adding window view", t);
- safelyFinish();
- return;
- }
-
- // start it up
- try {
- onStart();
- } catch (Throwable t) {
- Slog.w("Crashed in onStart()", t);
- safelyFinish();
- }
- }});
- }
-
- private void safelyFinish() {
- if (DEBUG) Slog.v(TAG, "safelyFinish()");
- try {
- finish();
- } catch (Throwable t) {
- Slog.w(TAG, "Crashed in safelyFinish()", t);
- finishInternal();
- return;
- }
-
- if (!mFinished) {
- Slog.w(TAG, "Bad dream, did not call super.finish()");
- finishInternal();
- }
- }
-
- private void finishInternal() {
- if (DEBUG) Slog.v(TAG, "finishInternal() mFinished = " + mFinished);
- if (mFinished) return;
- try {
- mFinished = true;
-
- if (mSandman != null) {
- mSandman.finishSelf(mWindowToken);
- } else {
- Slog.w(TAG, "No dream manager found");
- }
- stopSelf(); // if launched via any other means
-
- } catch (Throwable t) {
- Slog.w(TAG, "Crashed in finishInternal()", t);
- }
- }
-
- private boolean getWindowFlagValue(int flag, boolean defaultValue) {
- return mWindow == null ? defaultValue : (mWindow.getAttributes().flags & flag) != 0;
- }
-
- private void applyWindowFlags(int flags, int mask) {
- if (mWindow != null) {
- WindowManager.LayoutParams lp = mWindow.getAttributes();
- lp.flags = applyFlags(lp.flags, flags, mask);
- mWindow.setAttributes(lp);
- mWindowManager.updateViewLayout(mWindow.getDecorView(), lp);
- }
- }
-
- private boolean getSystemUiVisibilityFlagValue(int flag, boolean defaultValue) {
- View v = mWindow == null ? null : mWindow.getDecorView();
- return v == null ? defaultValue : (v.getSystemUiVisibility() & flag) != 0;
- }
-
- private void applySystemUiVisibilityFlags(int flags, int mask) {
- View v = mWindow == null ? null : mWindow.getDecorView();
- if (v != null) {
- v.setSystemUiVisibility(applyFlags(v.getSystemUiVisibility(), flags, mask));
- }
- }
-
- private int applyFlags(int oldFlags, int flags, int mask) {
- return (oldFlags&~mask) | (flags&mask);
- }
-
- private class DreamServiceWrapper extends IDreamService.Stub {
- public void attach(IBinder windowToken) {
- Dream.this.attach(windowToken);
- }
- }
-
+public class Dream extends DreamService {
}
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
new file mode 100644
index 0000000..f97354f
--- /dev/null
+++ b/core/java/android/service/dreams/DreamService.java
@@ -0,0 +1,619 @@
+/**
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.service.dreams;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.app.Service;
+import android.content.Intent;
+import android.graphics.drawable.ColorDrawable;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.util.Slog;
+import android.view.ActionMode;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.view.accessibility.AccessibilityEvent;
+
+import com.android.internal.policy.PolicyManager;
+
+/**
+ * Extend this class to implement a custom Dream.
+ *
+ * <p>Dreams are interactive screensavers launched when a charging device is idle, or docked in a
+ * desk dock. Dreams provide another modality for apps to express themselves, tailored for
+ * an exhibition/lean-back experience.</p>
+ *
+ * <p>Dreams should be declared in the manifest as follows:</p>
+ * <pre>
+ * {@code
+ * <service
+ * android:name=".MyDream"
+ * android:exported="true"
+ * android:icon="@drawable/my_icon"
+ * android:label="@string/my_dream_label" >
+ *
+ * <intent-filter>
+ * <action android:name="android.intent.action.MAIN" />
+ * <category android:name="android.intent.category.DREAM" />
+ * </intent-filter>
+ *
+ * <!-- Point to additional information for this dream (optional) -->
+ * <meta-data
+ * android:name="android.service.dream"
+ * android:resource="@xml/my_dream" />
+ * </service>
+ * }
+ * </pre>
+ */
+public class DreamService extends Service implements Window.Callback {
+ private final static boolean DEBUG = true;
+ private final String TAG = DreamService.class.getSimpleName() + "[" + getClass().getSimpleName() + "]";
+
+ /**
+ * The name of the dream manager service.
+ * @hide
+ */
+ public static final String DREAM_SERVICE = "dreams";
+
+ /**
+ * The {@link Intent} that must be declared as handled by the service.
+ */
+ @SdkConstant(SdkConstantType.SERVICE_ACTION)
+ public static final String SERVICE_INTERFACE =
+ "android.service.dreams.DreamService";
+
+ /**
+ * Name under which a Dream publishes information about itself.
+ * This meta-data must reference an XML resource containing
+ * a <code><{@link android.R.styleable#Dream dream}></code>
+ * tag.
+ */
+ public static final String DREAM_META_DATA = "android.service.dream";
+
+ private final Handler mHandler = new Handler();
+ private IBinder mWindowToken;
+ private Window mWindow;
+ private WindowManager mWindowManager;
+ private IDreamManager mSandman;
+ private boolean mInteractive = false;
+ private boolean mLowProfile = true;
+ private boolean mFullscreen = false;
+ private boolean mScreenBright = false;
+ private boolean mFinished;
+
+ // begin Window.Callback methods
+ /** {@inheritDoc} */
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ // TODO: create more flexible version of mInteractive that allows use of KEYCODE_BACK
+ if (!mInteractive) {
+ if (DEBUG) Slog.v(TAG, "Finishing on keyEvent");
+ safelyFinish();
+ return true;
+ } else if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
+ if (DEBUG) Slog.v(TAG, "Finishing on back key");
+ safelyFinish();
+ return true;
+ }
+ return mWindow.superDispatchKeyEvent(event);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean dispatchKeyShortcutEvent(KeyEvent event) {
+ if (!mInteractive) {
+ if (DEBUG) Slog.v(TAG, "Finishing on keyShortcutEvent");
+ safelyFinish();
+ return true;
+ }
+ return mWindow.superDispatchKeyShortcutEvent(event);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent event) {
+ // TODO: create more flexible version of mInteractive that allows clicks
+ // but finish()es on any other kind of activity
+ if (!mInteractive) {
+ if (DEBUG) Slog.v(TAG, "Finishing on touchEvent");
+ safelyFinish();
+ return true;
+ }
+ return mWindow.superDispatchTouchEvent(event);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean dispatchTrackballEvent(MotionEvent event) {
+ if (!mInteractive) {
+ if (DEBUG) Slog.v(TAG, "Finishing on trackballEvent");
+ safelyFinish();
+ return true;
+ }
+ return mWindow.superDispatchTrackballEvent(event);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean dispatchGenericMotionEvent(MotionEvent event) {
+ if (!mInteractive) {
+ if (DEBUG) Slog.v(TAG, "Finishing on genericMotionEvent");
+ safelyFinish();
+ return true;
+ }
+ return mWindow.superDispatchGenericMotionEvent(event);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public View onCreatePanelView(int featureId) {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean onCreatePanelMenu(int featureId, Menu menu) {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean onPreparePanel(int featureId, View view, Menu menu) {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean onMenuOpened(int featureId, Menu menu) {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean onMenuItemSelected(int featureId, MenuItem item) {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void onWindowAttributesChanged(LayoutParams attrs) {
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void onContentChanged() {
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void onAttachedToWindow() {
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void onDetachedFromWindow() {
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void onPanelClosed(int featureId, Menu menu) {
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean onSearchRequested() {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback callback) {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void onActionModeStarted(ActionMode mode) {
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void onActionModeFinished(ActionMode mode) {
+ }
+ // end Window.Callback methods
+
+ // begin public api
+ /**
+ * Retrieves the current {@link android.view.WindowManager} for the dream.
+ * Behaves similarly to {@link android.app.Activity#getWindowManager()}.
+ *
+ * @return The current window manager, or null if the dream is not started.
+ */
+ public WindowManager getWindowManager() {
+ return mWindowManager;
+ }
+
+ /**
+ * Retrieves the current {@link android.view.Window} for the dream.
+ * Behaves similarly to {@link android.app.Activity#getWindow()}.
+ *
+ * @return The current window, or null if the dream is not started.
+ */
+ public Window getWindow() {
+ return mWindow;
+ }
+
+ /**
+ * Inflates a layout resource and set it to be the content view for this Dream.
+ * Behaves similarly to {@link android.app.Activity#setContentView(int)}.
+ *
+ * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
+ *
+ * @param layoutResID Resource ID to be inflated.
+ *
+ * @see #setContentView(android.view.View)
+ * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
+ */
+ public void setContentView(int layoutResID) {
+ getWindow().setContentView(layoutResID);
+ }
+
+ /**
+ * Sets a view to be the content view for this Dream.
+ * Behaves similarly to {@link android.app.Activity#setContentView(android.view.View)},
+ * 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.
+ *
+ * @see #setContentView(int)
+ * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
+ */
+ public void setContentView(View view) {
+ getWindow().setContentView(view);
+ }
+
+ /**
+ * 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)}.
+ *
+ * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
+ *
+ * @param view The desired content to display.
+ * @param params Layout parameters for the view.
+ *
+ * @see #setContentView(android.view.View)
+ * @see #setContentView(int)
+ */
+ public void setContentView(View view, ViewGroup.LayoutParams params) {
+ getWindow().setContentView(view, params);
+ }
+
+ /**
+ * Adds a view to the Dream's window, leaving other content views in place.
+ *
+ * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
+ *
+ * @param view The desired content to display.
+ * @param params Layout parameters for the view.
+ */
+ public void addContentView(View view, ViewGroup.LayoutParams params) {
+ getWindow().addContentView(view, params);
+ }
+
+ /**
+ * Finds a view that was identified by the id attribute from the XML that
+ * was processed in {@link #onCreate}.
+ *
+ * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
+ *
+ * @return The view if found or null otherwise.
+ */
+ public View findViewById(int id) {
+ return getWindow().findViewById(id);
+ }
+
+ /**
+ * Marks this dream as interactive to receive input events.
+ *
+ * <p>Non-interactive dreams (default) will dismiss on the first input event.</p>
+ *
+ * <p>Interactive dreams should call {@link #finish()} to dismiss themselves.</p>
+ *
+ * @param interactive True if this dream will handle input events.
+ */
+ public void setInteractive(boolean interactive) {
+ mInteractive = interactive;
+ }
+
+ /**
+ * Returns whether or not this dream is interactive. Defaults to false.
+ *
+ * @see #setInteractive(boolean)
+ */
+ public boolean isInteractive() {
+ return mInteractive;
+ }
+
+ /**
+ * Sets View.SYSTEM_UI_FLAG_LOW_PROFILE on the content view.
+ *
+ * @param lowProfile True to set View.SYSTEM_UI_FLAG_LOW_PROFILE
+ */
+ public void setLowProfile(boolean lowProfile) {
+ mLowProfile = lowProfile;
+ int flag = View.SYSTEM_UI_FLAG_LOW_PROFILE;
+ applySystemUiVisibilityFlags(mLowProfile ? flag : 0, flag);
+ }
+
+ /**
+ * Returns whether or not this dream is in low profile mode. Defaults to true.
+ *
+ * @see #setLowProfile(boolean)
+ */
+ public boolean isLowProfile() {
+ return getSystemUiVisibilityFlagValue(View.SYSTEM_UI_FLAG_LOW_PROFILE, mLowProfile);
+ }
+
+ /**
+ * Sets View.SYSTEM_UI_FLAG_FULLSCREEN on the content view.
+ *
+ * @param fullscreen True to set View.SYSTEM_UI_FLAG_FULLSCREEN
+ */
+ public void setFullscreen(boolean fullscreen) {
+ mFullscreen = fullscreen;
+ int flag = View.SYSTEM_UI_FLAG_FULLSCREEN;
+ applySystemUiVisibilityFlags(mFullscreen ? flag : 0, flag);
+ }
+
+ /**
+ * Returns whether or not this dream is in fullscreen mode. Defaults to false.
+ *
+ * @see #setFullscreen(boolean)
+ */
+ public boolean isFullscreen() {
+ return getSystemUiVisibilityFlagValue(View.SYSTEM_UI_FLAG_FULLSCREEN, mFullscreen);
+ }
+
+ /**
+ * Marks this dream as keeping the screen bright while dreaming.
+ *
+ * @param screenBright True to keep the screen bright while dreaming.
+ */
+ public void setScreenBright(boolean screenBright) {
+ mScreenBright = screenBright;
+ int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+ applyWindowFlags(mScreenBright ? flag : 0, flag);
+ }
+
+ /**
+ * Returns whether or not this dream keeps the screen bright while dreaming. Defaults to false,
+ * allowing the screen to dim if necessary.
+ *
+ * @see #setScreenBright(boolean)
+ */
+ public boolean isScreenBright() {
+ return getWindowFlagValue(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, mScreenBright);
+ }
+
+ /**
+ * Called when this Dream is constructed. Place your initialization here.
+ *
+ * <p>Subclasses must call through to the superclass implementation.</p>
+ */
+ @Override
+ public void onCreate() {
+ if (DEBUG) Slog.v(TAG, "onCreate() on thread " + Thread.currentThread().getId());
+ super.onCreate();
+ loadSandman();
+ }
+
+ /**
+ * Called when this Dream is started. The window is created and visible at this point.
+ */
+ public void onStart() {
+ if (DEBUG) Slog.v(TAG, "onStart()");
+ // hook for subclasses
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public final IBinder onBind(Intent intent) {
+ if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent);
+ return new DreamServiceWrapper();
+ }
+
+ /**
+ * Stops the dream, detaches from the window, and wakes up.
+ *
+ * <p>Subclasses must call through to the superclass implementation.</p>
+ *
+ * <p>After this method is called, the service will be stopped.</p>
+ */
+ public void finish() {
+ if (DEBUG) Slog.v(TAG, "finish()");
+ finishInternal();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void onDestroy() {
+ if (DEBUG) Slog.v(TAG, "onDestroy()");
+ super.onDestroy();
+
+ if (DEBUG) Slog.v(TAG, "Removing window");
+ try {
+ mWindowManager.removeView(mWindow.getDecorView());
+ } catch (Throwable t) {
+ Slog.w(TAG, "Crashed removing window view", t);
+ }
+ }
+ // end public api
+
+ private void loadSandman() {
+ mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
+ }
+
+ private final void attach(IBinder windowToken) {
+ if (DEBUG) Slog.v(TAG, "Attached on thread " + Thread.currentThread().getId());
+
+ if (mSandman == null) {
+ Slog.w(TAG, "No dream manager found, super.onCreate may not have been called");
+ loadSandman();
+ }
+ mWindowToken = windowToken;
+ mWindow = PolicyManager.makeNewWindow(this);
+ mWindow.setCallback(this);
+ mWindow.requestFeature(Window.FEATURE_NO_TITLE);
+ mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000));
+
+ if (DEBUG) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s",
+ windowToken, WindowManager.LayoutParams.TYPE_DREAM));
+
+ WindowManager.LayoutParams lp = mWindow.getAttributes();
+ lp.type = WindowManager.LayoutParams.TYPE_DREAM;
+ lp.token = windowToken;
+ lp.windowAnimations = com.android.internal.R.style.Animation_Dream;
+ lp.flags |= ( WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+ | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
+ | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
+ | (mScreenBright ? WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON : 0)
+ );
+ mWindow.setAttributes(lp);
+
+ if (DEBUG) Slog.v(TAG, "Created and attached window: " + mWindow);
+
+ mWindow.setWindowManager(null, windowToken, "dream", true);
+ mWindowManager = mWindow.getWindowManager();
+
+ // now make it visible (on the ui thread)
+ mHandler.post(new Runnable(){
+ @Override
+ public void run() {
+ if (DEBUG) Slog.v(TAG, "Window added on thread " + Thread.currentThread().getId());
+ try {
+ applySystemUiVisibilityFlags(
+ (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0)
+ | (mFullscreen ? View.SYSTEM_UI_FLAG_FULLSCREEN : 0),
+ View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN);
+ getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
+ } catch (Throwable t) {
+ Slog.w("Crashed adding window view", t);
+ safelyFinish();
+ return;
+ }
+
+ // start it up
+ try {
+ onStart();
+ } catch (Throwable t) {
+ Slog.w("Crashed in onStart()", t);
+ safelyFinish();
+ }
+ }});
+ }
+
+ private void safelyFinish() {
+ if (DEBUG) Slog.v(TAG, "safelyFinish()");
+ try {
+ finish();
+ } catch (Throwable t) {
+ Slog.w(TAG, "Crashed in safelyFinish()", t);
+ finishInternal();
+ return;
+ }
+
+ if (!mFinished) {
+ Slog.w(TAG, "Bad dream, did not call super.finish()");
+ finishInternal();
+ }
+ }
+
+ private void finishInternal() {
+ if (DEBUG) Slog.v(TAG, "finishInternal() mFinished = " + mFinished);
+ if (mFinished) return;
+ try {
+ mFinished = true;
+
+ if (mSandman != null) {
+ mSandman.finishSelf(mWindowToken);
+ } else {
+ Slog.w(TAG, "No dream manager found");
+ }
+ stopSelf(); // if launched via any other means
+
+ } catch (Throwable t) {
+ Slog.w(TAG, "Crashed in finishInternal()", t);
+ }
+ }
+
+ private boolean getWindowFlagValue(int flag, boolean defaultValue) {
+ return mWindow == null ? defaultValue : (mWindow.getAttributes().flags & flag) != 0;
+ }
+
+ private void applyWindowFlags(int flags, int mask) {
+ if (mWindow != null) {
+ WindowManager.LayoutParams lp = mWindow.getAttributes();
+ lp.flags = applyFlags(lp.flags, flags, mask);
+ mWindow.setAttributes(lp);
+ mWindowManager.updateViewLayout(mWindow.getDecorView(), lp);
+ }
+ }
+
+ private boolean getSystemUiVisibilityFlagValue(int flag, boolean defaultValue) {
+ View v = mWindow == null ? null : mWindow.getDecorView();
+ return v == null ? defaultValue : (v.getSystemUiVisibility() & flag) != 0;
+ }
+
+ private void applySystemUiVisibilityFlags(int flags, int mask) {
+ View v = mWindow == null ? null : mWindow.getDecorView();
+ if (v != null) {
+ v.setSystemUiVisibility(applyFlags(v.getSystemUiVisibility(), flags, mask));
+ }
+ }
+
+ private int applyFlags(int oldFlags, int flags, int mask) {
+ return (oldFlags&~mask) | (flags&mask);
+ }
+
+ private class DreamServiceWrapper extends IDreamService.Stub {
+ public void attach(IBinder windowToken) {
+ DreamService.this.attach(windowToken);
+ }
+ }
+
+}
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index b0a2711..4873860 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.os.SystemClock;
import android.util.FloatMath;
+import android.util.Log;
import java.util.Arrays;
@@ -223,10 +224,14 @@
* @param id pointer id to clear
* @see #addTouchHistory(MotionEvent)
*/
- private void removeTouchHistoryForId(int id) {
+ private boolean removeTouchHistoryForId(int id) {
+ if (id >= mTouchHistoryLastAccepted.length) {
+ return false;
+ }
mTouchHistoryLastAccepted[id] = Float.NaN;
mTouchHistoryDirection[id] = 0;
mTouchHistoryLastAcceptedTime[id] = 0;
+ return true;
}
/**
@@ -236,6 +241,11 @@
* @see #addTouchHistory(MotionEvent)
*/
private float getAdjustedTouchHistory(int id) {
+ if (id >= mTouchHistoryLastAccepted.length) {
+ Log.e(TAG, "Error retrieving adjusted touch history for id=" + id +
+ " - incomplete event stream?");
+ return 0;
+ }
return mTouchHistoryLastAccepted[id];
}
@@ -244,6 +254,10 @@
* @see #addTouchHistory(MotionEvent)
*/
private void clearTouchHistory() {
+ if (mTouchHistoryLastAccepted == null) {
+ // All three arrays will be null if this is the case; nothing to do.
+ return;
+ }
Arrays.fill(mTouchHistoryLastAccepted, Float.NaN);
Arrays.fill(mTouchHistoryDirection, 0);
Arrays.fill(mTouchHistoryLastAcceptedTime, 0);
@@ -333,7 +347,11 @@
final float focusY = sumY / div;
if (pointerUp) {
- removeTouchHistoryForId(event.getPointerId(event.getActionIndex()));
+ final int id = event.getPointerId(event.getActionIndex());
+ if (!removeTouchHistoryForId(id)) {
+ Log.e(TAG, "Got ACTION_POINTER_UP for previously unknown id=" + id +
+ " - incomplete event stream?");
+ }
} else {
addTouchHistory(event);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 111f959..1c12738 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5887,6 +5887,8 @@
* layout attribute and/or the inherited value from the parent
*
* @return true if the layout is right-to-left.
+ *
+ * @hide
*/
@ViewDebug.ExportedProperty(category = "layout")
public boolean isLayoutRtl() {
@@ -11628,9 +11630,11 @@
* Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
* that the parent directionality can and will be resolved before its children.
*
+ * @return true if resolution has been done, false otherwise.
+ *
* @hide
*/
- public void resolveLayoutDirection() {
+ public boolean resolveLayoutDirection() {
// Clear any previous layout direction resolution
mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
@@ -11641,15 +11645,13 @@
case LAYOUT_DIRECTION_INHERIT:
// We cannot resolve yet. LTR is by default and let the resolution happen again
// later to get the correct resolved value
- if (!canResolveLayoutDirection()) return;
+ if (!canResolveLayoutDirection()) return false;
- ViewGroup viewGroup = ((ViewGroup) mParent);
+ View parent = ((View) mParent);
+ // Parent has not yet resolved, LTR is still the default
+ if (!parent.isLayoutDirectionResolved()) return false;
- // We cannot resolve yet on the parent too. LTR is by default and let the
- // resolution happen again later
- if (!viewGroup.canResolveLayoutDirection()) return;
-
- if (viewGroup.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+ if (parent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
}
break;
@@ -11669,6 +11671,7 @@
// Set to resolved
mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
+ return true;
}
/**
@@ -11679,10 +11682,10 @@
* @hide
*/
public boolean canResolveLayoutDirection() {
- switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
- PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
+ switch (getRawLayoutDirection()) {
case LAYOUT_DIRECTION_INHERIT:
- return (mParent != null) && (mParent instanceof ViewGroup);
+ return (mParent != null) && (mParent instanceof ViewGroup) &&
+ ((ViewGroup) mParent).canResolveLayoutDirection();
default:
return true;
}
@@ -16640,9 +16643,11 @@
/**
* Resolve the text direction.
*
+ * @return true if resolution has been done, false otherwise.
+ *
* @hide
*/
- public void resolveTextDirection() {
+ public boolean resolveTextDirection() {
// Reset any previous text direction resolution
mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
@@ -16651,29 +16656,35 @@
final int textDirection = getRawTextDirection();
switch(textDirection) {
case TEXT_DIRECTION_INHERIT:
- if (canResolveTextDirection()) {
- ViewGroup viewGroup = ((ViewGroup) mParent);
-
- // Set current resolved direction to the same value as the parent's one
- final int parentResolvedDirection = viewGroup.getTextDirection();
- switch (parentResolvedDirection) {
- case TEXT_DIRECTION_FIRST_STRONG:
- case TEXT_DIRECTION_ANY_RTL:
- case TEXT_DIRECTION_LTR:
- case TEXT_DIRECTION_RTL:
- case TEXT_DIRECTION_LOCALE:
- mPrivateFlags2 |=
- (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
- break;
- default:
- // Default resolved direction is "first strong" heuristic
- mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
- }
- } else {
+ if (!canResolveTextDirection()) {
// We cannot do the resolution if there is no parent, so use the default one
mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
// Resolution will need to happen again later
- return;
+ return false;
+ }
+
+ View parent = ((View) mParent);
+ // Parent has not yet resolved, so we still return the default
+ if (!parent.isTextDirectionResolved()) {
+ mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
+ // Resolution will need to happen again later
+ return false;
+ }
+
+ // Set current resolved direction to the same value as the parent's one
+ final int parentResolvedDirection = parent.getTextDirection();
+ switch (parentResolvedDirection) {
+ case TEXT_DIRECTION_FIRST_STRONG:
+ case TEXT_DIRECTION_ANY_RTL:
+ case TEXT_DIRECTION_LTR:
+ case TEXT_DIRECTION_RTL:
+ case TEXT_DIRECTION_LOCALE:
+ mPrivateFlags2 |=
+ (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
+ break;
+ default:
+ // Default resolved direction is "first strong" heuristic
+ mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
}
break;
case TEXT_DIRECTION_FIRST_STRONG:
@@ -16695,6 +16706,7 @@
// Set to resolved
mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
+ return true;
}
/**
@@ -16705,7 +16717,8 @@
private boolean canResolveTextDirection() {
switch (getRawTextDirection()) {
case TEXT_DIRECTION_INHERIT:
- return (mParent != null) && (mParent instanceof ViewGroup);
+ return (mParent != null) && (mParent instanceof View) &&
+ ((View) mParent).canResolveTextDirection();
default:
return true;
}
@@ -16835,9 +16848,11 @@
/**
* Resolve the text alignment.
*
+ * @return true if resolution has been done, false otherwise.
+ *
* @hide
*/
- public void resolveTextAlignment() {
+ public boolean resolveTextAlignment() {
// Reset any previous text alignment resolution
mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
@@ -16847,32 +16862,37 @@
switch (textAlignment) {
case TEXT_ALIGNMENT_INHERIT:
// Check if we can resolve the text alignment
- if (canResolveTextAlignment() && mParent instanceof View) {
- View view = (View) mParent;
-
- final int parentResolvedTextAlignment = view.getTextAlignment();
- switch (parentResolvedTextAlignment) {
- case TEXT_ALIGNMENT_GRAVITY:
- case TEXT_ALIGNMENT_TEXT_START:
- case TEXT_ALIGNMENT_TEXT_END:
- case TEXT_ALIGNMENT_CENTER:
- case TEXT_ALIGNMENT_VIEW_START:
- case TEXT_ALIGNMENT_VIEW_END:
- // Resolved text alignment is the same as the parent resolved
- // text alignment
- mPrivateFlags2 |=
- (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
- break;
- default:
- // Use default resolved text alignment
- mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
- }
- }
- else {
+ if (!canResolveTextAlignment()) {
// We cannot do the resolution if there is no parent so use the default
mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
// Resolution will need to happen again later
- return;
+ return false;
+ }
+ View parent = (View) mParent;
+
+ // Parent has not yet resolved, so we still return the default
+ if (!parent.isTextAlignmentResolved()) {
+ mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+ // Resolution will need to happen again later
+ return false;
+ }
+
+ final int parentResolvedTextAlignment = parent.getTextAlignment();
+ switch (parentResolvedTextAlignment) {
+ case TEXT_ALIGNMENT_GRAVITY:
+ case TEXT_ALIGNMENT_TEXT_START:
+ case TEXT_ALIGNMENT_TEXT_END:
+ case TEXT_ALIGNMENT_CENTER:
+ case TEXT_ALIGNMENT_VIEW_START:
+ case TEXT_ALIGNMENT_VIEW_END:
+ // Resolved text alignment is the same as the parent resolved
+ // text alignment
+ mPrivateFlags2 |=
+ (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
+ break;
+ default:
+ // Use default resolved text alignment
+ mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
}
break;
case TEXT_ALIGNMENT_GRAVITY:
@@ -16895,6 +16915,7 @@
// Set the resolved
mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
+ return true;
}
/**
@@ -16905,7 +16926,8 @@
private boolean canResolveTextAlignment() {
switch (getRawTextAlignment()) {
case TEXT_DIRECTION_INHERIT:
- return (mParent != null);
+ return (mParent != null) && (mParent instanceof View) &&
+ ((View) mParent).canResolveTextAlignment();
default:
return true;
}
@@ -17186,7 +17208,7 @@
* @return the measure specification based on size and mode
*/
public static int makeMeasureSpec(int size, int mode) {
- return size + mode;
+ return (size & ~MODE_MASK) | (mode & MODE_MASK);
}
/**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 41890d6..db1c00a 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3382,6 +3382,11 @@
ai.mKeepScreenOn = lastKeepOn;
}
+ if (child.isLayoutDirectionInherited()) {
+ child.resetResolvedLayoutDirection();
+ child.resolveRtlPropertiesIfNeeded();
+ }
+
onViewAdded(child);
if ((child.mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE) {
@@ -5256,48 +5261,54 @@
* @hide
*/
@Override
- public void resolveLayoutDirection() {
- super.resolveLayoutDirection();
-
- int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (child.isLayoutDirectionInherited()) {
- child.resolveLayoutDirection();
+ public boolean resolveLayoutDirection() {
+ final boolean result = super.resolveLayoutDirection();
+ if (result) {
+ int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ if (child.isLayoutDirectionInherited()) {
+ child.resolveLayoutDirection();
+ }
}
}
+ return result;
}
/**
* @hide
*/
@Override
- public void resolveTextDirection() {
- super.resolveTextDirection();
-
- int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (child.isTextDirectionInherited()) {
- child.resolveTextDirection();
+ public boolean resolveTextDirection() {
+ final boolean result = super.resolveTextDirection();
+ if (result) {
+ int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ if (child.isTextDirectionInherited()) {
+ child.resolveTextDirection();
+ }
}
}
+ return result;
}
/**
* @hide
*/
@Override
- public void resolveTextAlignment() {
- super.resolveTextAlignment();
-
- int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (child.isTextAlignmentInherited()) {
- child.resolveTextAlignment();
+ public boolean resolveTextAlignment() {
+ final boolean result = super.resolveTextAlignment();
+ if (result) {
+ int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ if (child.isTextAlignmentInherited()) {
+ child.resolveTextAlignment();
+ }
}
}
+ return result;
}
/**
@@ -5893,7 +5904,10 @@
}
}
- protected boolean isLayoutRtl() {
+ /**
+ * @hide
+ */
+ public boolean isLayoutRtl() {
return (layoutDirection == View.LAYOUT_DIRECTION_RTL);
}
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index bc78adc..cea1fd5 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -46,6 +46,9 @@
private int mCheckMarkWidth;
private boolean mNeedRequestlayout;
+ private int initialPaddingLeft = -1;
+ private int initialPaddingRight = -1;
+
private static final int[] CHECKED_STATE_SET = {
R.attr.state_checked
};
@@ -176,10 +179,22 @@
protected void internalSetPadding(int left, int top, int right, int bottom) {
super.internalSetPadding(left, top, right, bottom);
setBasePadding(isLayoutRtl());
+ initialPaddingLeft = mPaddingLeft;
+ initialPaddingRight = mPaddingRight;
}
@Override
public void onPaddingChanged(int layoutDirection) {
+ updatePadding();
+ }
+
+ @Override
+ public void onRtlPropertiesChanged() {
+ super.onRtlPropertiesChanged();
+ updatePadding();
+ }
+
+ private void updatePadding() {
int newPadding = (mCheckMarkDrawable != null) ?
mCheckMarkWidth + mBasePadding : mBasePadding;
mNeedRequestlayout |= (mPaddingRight != newPadding);
@@ -193,7 +208,7 @@
mNeedRequestlayout = false;
}
}
-
+
@Override
public void setPadding(int left, int top, int right, int bottom) {
super.setPadding(left, top, right, bottom);
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index b72b8cb..e0c5bbd 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -182,6 +182,12 @@
*/
private boolean mIsRtl = true;
+ /**
+ * Offset between the center of the selected child view and the center of the Gallery.
+ * Used to reset position correctly during layout.
+ */
+ private int mSelectedCenterOffset;
+
public Gallery(Context context) {
this(context, null);
}
@@ -395,6 +401,14 @@
setSelectionToCenterChild();
+ final View selChild = mSelectedChild;
+ if (selChild != null) {
+ final int childLeft = selChild.getLeft();
+ final int childCenter = selChild.getWidth() / 2;
+ final int galleryCenter = getWidth() / 2;
+ mSelectedCenterOffset = childLeft + childCenter - galleryCenter;
+ }
+
onScrollChanged(0, 0, 0, 0); // dummy values, View's implementation does not use these.
invalidate();
@@ -537,6 +551,7 @@
// We haven't been callbacking during the fling, so do it now
super.selectionChanged();
}
+ mSelectedCenterOffset = 0;
invalidate();
}
@@ -650,7 +665,8 @@
View sel = makeAndAddView(mSelectedPosition, 0, 0, true);
// Put the selected child in the center
- int selectedOffset = childrenLeft + (childrenWidth / 2) - (sel.getWidth() / 2);
+ int selectedOffset = childrenLeft + (childrenWidth / 2) - (sel.getWidth() / 2) +
+ mSelectedCenterOffset;
sel.offsetLeftAndRight(selectedOffset);
fillToGalleryRight();
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 87396fb..1d465ce 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -789,6 +789,12 @@
if (resizeWidth) {
int newWidth = (int)(desiredAspect * (heightSize - ptop - pbottom)) +
pleft + pright;
+
+ // Allow the width to outgrow its original estimate if height is fixed.
+ if (!resizeHeight) {
+ widthSize = resolveAdjustedSize(newWidth, mMaxWidth, widthMeasureSpec);
+ }
+
if (newWidth <= widthSize) {
widthSize = newWidth;
done = true;
@@ -799,6 +805,13 @@
if (!done && resizeHeight) {
int newHeight = (int)((widthSize - pleft - pright) / desiredAspect) +
ptop + pbottom;
+
+ // Allow the height to outgrow its original estimate if width is fixed.
+ if (!resizeWidth) {
+ heightSize = resolveAdjustedSize(newHeight, mMaxHeight,
+ heightMeasureSpec);
+ }
+
if (newHeight <= heightSize) {
heightSize = newHeight;
}
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 704f6b6..4918e48 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1361,6 +1361,14 @@
// Allow text entry rather than strictly numeric entry.
mInputText.setRawInputType(InputType.TYPE_CLASS_TEXT
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
+ // Make sure the min, max, respect the size of the displayed
+ // values. This will take care of the current value as well.
+ if (getMinValue() >= displayedValues.length) {
+ setMinValue(0);
+ }
+ if (getMaxValue() >= displayedValues.length) {
+ setMaxValue(displayedValues.length - 1);
+ }
} else {
mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
}
diff --git a/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java b/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
index f010d7b..386f387 100644
--- a/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
+++ b/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
@@ -25,7 +25,7 @@
import android.app.MediaRouteButton;
import android.content.Context;
import android.graphics.drawable.Drawable;
-import android.media.AudioManager;
+import android.hardware.display.DisplayManager;
import android.media.MediaRouter;
import android.media.MediaRouter.RouteCategory;
import android.media.MediaRouter.RouteGroup;
@@ -70,6 +70,7 @@
};
MediaRouter mRouter;
+ DisplayManager mDisplayService;
private int mRouteTypes;
private LayoutInflater mInflater;
@@ -97,6 +98,7 @@
public void onAttach(Activity activity) {
super.onAttach(activity);
mRouter = (MediaRouter) activity.getSystemService(Context.MEDIA_ROUTER_SERVICE);
+ mDisplayService = (DisplayManager) activity.getSystemService(Context.DISPLAY_SERVICE);
}
@Override
@@ -119,6 +121,15 @@
public void setRouteTypes(int types) {
mRouteTypes = types;
+ if ((mRouteTypes & MediaRouter.ROUTE_TYPE_LIVE_VIDEO) != 0 && mDisplayService == null) {
+ final Context activity = getActivity();
+ if (activity != null) {
+ mDisplayService = (DisplayManager) activity.getSystemService(
+ Context.DISPLAY_SERVICE);
+ }
+ } else {
+ mDisplayService = null;
+ }
}
void updateVolume() {
@@ -194,6 +205,9 @@
@Override
public void onResume() {
super.onResume();
+ if (mDisplayService != null) {
+ mDisplayService.scanWifiDisplays();
+ }
}
private static class ViewHolder {
@@ -253,7 +267,9 @@
final RouteCategory cat = mRouter.getCategoryAt(i);
routes = cat.getRoutes(mCatRouteList);
- mItems.add(cat);
+ if (!cat.isSystem()) {
+ mItems.add(cat);
+ }
if (cat == mCategoryEditingGroups) {
addGroupEditingCategoryRoutes(routes);
@@ -370,6 +386,7 @@
public boolean isEnabled(int position) {
switch (getItemViewType(position)) {
case VIEW_ROUTE:
+ return ((RouteInfo) mItems.get(position)).isEnabled();
case VIEW_GROUPING_ROUTE:
case VIEW_GROUPING_DONE:
return true;
@@ -434,6 +451,7 @@
}
convertView.setActivated(position == mSelectedItemPosition);
+ convertView.setEnabled(isEnabled(position));
return convertView;
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 0737b52..780f5b3 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -28,10 +28,9 @@
void updateNotification(IBinder key, in StatusBarNotification notification);
void removeNotification(IBinder key);
void disable(int state);
- void animateExpandNotifications();
- void animateCollapseNotifications();
- void animateExpandQuickSettings();
- void animateCollapseQuickSettings();
+ void animateExpandNotificationsPanel();
+ void animateExpandSettingsPanel();
+ void animateCollapsePanels();
void setSystemUiVisibility(int vis, int mask);
void topAppWindowChanged(boolean menuVisible);
void setImeWindowStatus(in IBinder token, int vis, int backDisposition);
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 60e2b34..600c27a 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -24,16 +24,15 @@
/** @hide */
interface IStatusBarService
{
- void expandNotifications();
- void collapseNotifications();
- void expandQuickSettings();
- void collapseQuickSettings();
+ void expandNotificationsPanel();
+ void collapsePanels();
void disable(int what, IBinder token, String pkg);
void setIcon(String slot, String iconPackage, int iconId, int iconLevel, String contentDescription);
void setIconVisibility(String slot, boolean visible);
void removeIcon(String slot);
void topAppWindowChanged(boolean menuVisible);
void setImeWindowStatus(in IBinder token, int vis, int backDisposition);
+ void expandSettingsPanel();
// ---- Methods below are for use by the status bar policy services ----
// You need the STATUS_BAR_SERVICE permission
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 8032ed8..ba8cea4 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -686,23 +686,24 @@
i, HBFixedToFloat(mShaperItem.advances[i]));
}
#endif
- // Get Advances and their total
- jfloat currentAdvance = HBFixedToFloat(mShaperItem.advances[mShaperItem.log_clusters[0]]);
- jfloat totalFontRunAdvance = currentAdvance;
- outAdvances->replaceAt(currentAdvance, startScriptRun);
- for (size_t i = 1; i < countScriptRun; i++) {
- size_t clusterPrevious = mShaperItem.log_clusters[i - 1];
+ jfloat totalFontRunAdvance = 0;
+ size_t clusterStart = 0;
+ for (size_t i = 0; i < countScriptRun; i++) {
size_t cluster = mShaperItem.log_clusters[i];
- if (cluster != clusterPrevious) {
- currentAdvance = HBFixedToFloat(mShaperItem.advances[mShaperItem.log_clusters[i]]);
- outAdvances->replaceAt(currentAdvance, startScriptRun + i);
+ size_t clusterNext = i == countScriptRun - 1 ? mShaperItem.num_glyphs :
+ mShaperItem.log_clusters[i + 1];
+ if (cluster != clusterNext) {
+ jfloat advance = 0;
+ // The advance for the cluster is the sum of the advances of all glyphs within
+ // the cluster.
+ for (size_t j = cluster; j < clusterNext; j++) {
+ advance += HBFixedToFloat(mShaperItem.advances[j]);
+ }
+ totalFontRunAdvance += advance;
+ outAdvances->replaceAt(advance, startScriptRun + clusterStart);
+ clusterStart = i + 1;
}
}
- // TODO: can be removed and go back in the previous loop when Harfbuzz log clusters are fixed
- for (size_t i = 1; i < mShaperItem.num_glyphs; i++) {
- currentAdvance = HBFixedToFloat(mShaperItem.advances[i]);
- totalFontRunAdvance += currentAdvance;
- }
#if DEBUG_ADVANCES
ALOGD("Returned advances");
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 8dbaa26..c794c51 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2103,7 +2103,7 @@
<activity android:name="android.accounts.ChooseAccountTypeActivity"
android:excludeFromRecents="true"
- android:theme="@android:style/Theme.Holo.DialogWhenLarge.NoActionBar"
+ android:theme="@android:style/Theme.Holo.Dialog"
android:label="@string/choose_account_label"
android:process=":ui">
</activity>
@@ -2140,7 +2140,8 @@
android:process=":ui">
</activity>
- <receiver android:name="com.android.server.BootReceiver" >
+ <receiver android:name="com.android.server.BootReceiver"
+ android:primaryUserOnly="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
@@ -2152,6 +2153,12 @@
</intent-filter>
</receiver>
+ <receiver android:name="com.android.server.updates.SmsShortCodesInstallReceiver" >
+ <intent-filter>
+ <action android:name="android.intent.action.UPDATE_SMS_SHORT_CODES" />
+ </intent-filter>
+ </receiver>
+
<receiver android:name="com.android.server.MasterClearReceiver"
android:permission="android.permission.MASTER_CLEAR"
android:priority="100" >
diff --git a/core/res/res/drawable-hdpi/magnified_region_frame.9.png b/core/res/res/drawable-hdpi/magnified_region_frame.9.png
new file mode 100644
index 0000000..29bdc42
--- /dev/null
+++ b/core/res/res/drawable-hdpi/magnified_region_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/magnified_region_frame.9.png b/core/res/res/drawable-mdpi/magnified_region_frame.9.png
new file mode 100644
index 0000000..a61cbea
--- /dev/null
+++ b/core/res/res/drawable-mdpi/magnified_region_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/magnified_region_frame.9.png b/core/res/res/drawable-nodpi/magnified_region_frame.9.png
deleted file mode 100644
index 4cadefb..0000000
--- a/core/res/res/drawable-nodpi/magnified_region_frame.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/magnified_region_frame.9.png b/core/res/res/drawable-xhdpi/magnified_region_frame.9.png
new file mode 100644
index 0000000..424b3d9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/magnified_region_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable/kg_avatar_overlay.xml b/core/res/res/drawable/kg_avatar_overlay.xml
deleted file mode 100644
index 781c1df..0000000
--- a/core/res/res/drawable/kg_avatar_overlay.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_pressed="true"
- android:drawable="@drawable/activity_picker_bg_activated" />
-</selector>
\ No newline at end of file
diff --git a/core/res/res/layout/choose_account_type.xml b/core/res/res/layout/choose_account_type.xml
index 769d80b..87d1dde 100644
--- a/core/res/res/layout/choose_account_type.xml
+++ b/core/res/res/layout/choose_account_type.xml
@@ -20,20 +20,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical"
- android:paddingStart="16dip"
- android:paddingEnd="16dip">
-
- <TextView android:id="@+id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_gravity="start"
- android:text="@string/add_account_label"
- android:paddingTop="16dip"
- android:paddingBottom="16dip"
- android:textColor="@android:color/holo_blue_light"
- />
+ android:orientation="vertical">
<View android:layout_height="3dip"
android:layout_width="match_parent"
diff --git a/core/res/res/layout/keyguard_multi_user_avatar.xml b/core/res/res/layout/keyguard_multi_user_avatar.xml
index 23f9b6d..a3621c0 100644
--- a/core/res/res/layout/keyguard_multi_user_avatar.xml
+++ b/core/res/res/layout/keyguard_multi_user_avatar.xml
@@ -22,9 +22,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="125dp"
android:layout_height="125dp"
- android:background="#550000ff"
- android:gravity="center_horizontal"
- android:foreground="@drawable/kg_avatar_overlay">
+ android:gravity="center_horizontal">
<ImageView
android:id="@+id/keyguard_user_avatar"
android:scaleType="centerCrop"
diff --git a/core/res/res/layout/keyguard_navigation.xml b/core/res/res/layout/keyguard_navigation.xml
index d52bcb4..c29dc70 100644
--- a/core/res/res/layout/keyguard_navigation.xml
+++ b/core/res/res/layout/keyguard_navigation.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
**
-** Copyright 2008, The Android Open Source Project
+** 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.
diff --git a/core/res/res/layout/keyguard_password_view.xml b/core/res/res/layout/keyguard_password_view.xml
index e8ca98b..f7071d2 100644
--- a/core/res/res/layout/keyguard_password_view.xml
+++ b/core/res/res/layout/keyguard_password_view.xml
@@ -67,10 +67,10 @@
<ImageButton android:id="@+id/delete_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
android:src="@*android:drawable/ic_input_delete"
android:clickable="true"
android:padding="8dip"
- android:layout_gravity="center_vertical"
android:background="?android:attr/selectableItemBackground"
android:visibility="gone"
/>
diff --git a/core/res/res/layout/keyguard_sim_pin_view.xml b/core/res/res/layout/keyguard_sim_pin_view.xml
index 57c7ac6..91dd6d0 100644
--- a/core/res/res/layout/keyguard_sim_pin_view.xml
+++ b/core/res/res/layout/keyguard_sim_pin_view.xml
@@ -51,7 +51,7 @@
android:layout_marginEnd="4dip"
android:layout_marginStart="4dip"
android:gravity="center_vertical"
- android:background="@android:drawable/edit_text">
+ android:background="#70000000">
<!-- displays dots as user enters pin -->
<EditText android:id="@+id/sim_pin_entry"
@@ -60,19 +60,26 @@
android:layout_weight="1"
android:maxLines="1"
android:singleLine="true"
- android:textAppearance="?android:attr/textAppearanceLargeInverse"
- android:textColor="@*android:color/primary_text_holo_light"
- android:textStyle="bold"
+ android:gravity="center_horizontal"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="@*android:dimen/keyguard_lockscreen_pin_margin_left"
+ android:textStyle="normal"
android:inputType="textPassword"
+ android:textSize="36sp"
+ android:background="@null"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="#ffffffff"
android:imeOptions="flagForceAscii|actionDone"
/>
<ImageButton android:id="@+id/delete_button"
- android:src="@android:drawable/ic_input_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginEnd="-3dip"
- android:layout_marginBottom="-3dip"
+ android:layout_gravity="center_vertical"
+ android:src="@android:drawable/ic_input_delete"
+ android:clickable="true"
+ android:padding="8dip"
+ android:background="?android:attr/selectableItemBackground"
/>
</LinearLayout>
diff --git a/core/res/res/layout/keyguard_sim_puk_view.xml b/core/res/res/layout/keyguard_sim_puk_view.xml
index 8bb76c1..0c41a34 100644
--- a/core/res/res/layout/keyguard_sim_puk_view.xml
+++ b/core/res/res/layout/keyguard_sim_puk_view.xml
@@ -16,6 +16,8 @@
** limitations under the License.
*/
-->
+<!-- This is the SIM PUK view that allows the user to recover their device by entering the
+ carrier-provided PUK code and entering a new SIM PIN for it. -->
<com.android.internal.policy.impl.keyguard.KeyguardSimPukView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/keyguard_sim_puk_view"
@@ -24,98 +26,62 @@
android:orientation="vertical"
android:gravity="center_horizontal">
- <include layout="@layout/keyguard_navigation"/>
-
- <Space
- android:layout_width="match_parent"
+ <LinearLayout
android:layout_height="0dip"
- android:layout_weight="1"/>
+ android:layout_width="match_parent"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:gravity="center">
- <LinearLayout android:id="@+id/topDisplayGroup"
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_lockscreen_sim"/>
+
+ <include layout="@layout/keyguard_navigation"/>
+
+ </LinearLayout>
+
+ <!-- Password entry field -->
+ <!-- Note: the entire container is styled to look like the edit field,
+ since the backspace/IME switcher looks better inside -->
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:orientation="horizontal"
+ android:layout_marginEnd="4dip"
+ android:layout_marginStart="4dip"
+ android:gravity="center_vertical"
+ android:background="#70000000">
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
+ <!-- displays dots as user enters pin -->
+ <EditText android:id="@+id/sim_pin_entry"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:maxLines="1"
+ android:singleLine="true"
+ android:gravity="center_horizontal"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="@*android:dimen/keyguard_lockscreen_pin_margin_left"
+ android:textStyle="normal"
+ android:inputType="textPassword"
+ android:textSize="36sp"
+ android:background="@null"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="#ffffffff"
+ android:imeOptions="flagForceAscii|actionDone"
+ />
- <LinearLayout
- android:orientation="vertical"
- android:layout_width="wrap_content"
- android:layout_weight="1"
- android:layout_height="match_parent"
- android:paddingEnd="0dip"
- android:layout_marginEnd="10dip"
- android:layout_marginStart="10dip">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_marginEnd="6dip"
- android:layout_marginStart="6dip"
- android:gravity="center_vertical"
- android:background="@*android:drawable/edit_text">
-
- <!-- displays dots as user enters puk -->
- <EditText android:id="@+id/sim_puk_entry"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:maxLines="1"
- android:textStyle="bold"
- android:inputType="textPassword"
- android:textColor="#000"
- android:hint="@string/kg_puk_enter_puk_hint"
- />
-
- <ImageButton android:id="@+id/puk_delete_button"
- android:src="@*android:drawable/ic_input_delete"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginEnd="-3dip"
- android:layout_marginBottom="-3dip"
- />
-
- </LinearLayout>
-
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_marginEnd="6dip"
- android:layout_marginStart="6dip"
- android:gravity="center_vertical"
- android:background="@*android:drawable/edit_text">
-
- <!-- displays dots as user enters new pin -->
- <EditText android:id="@+id/sim_pin_entry"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:maxLines="1"
- android:textStyle="bold"
- android:inputType="textPassword"
- android:textColor="#000"
- android:hint="@string/kg_puk_enter_pin_hint"
- />
-
- <ImageButton android:id="@+id/pin_delete_button"
- android:src="@*android:drawable/ic_input_delete"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginEnd="-3dip"
- android:layout_marginBottom="-3dip"
- />
- </LinearLayout>
-
- </LinearLayout>
-
- </LinearLayout>
-
+ <ImageButton android:id="@+id/delete_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:src="@android:drawable/ic_input_delete"
+ android:clickable="true"
+ android:padding="8dip"
+ android:background="?android:attr/selectableItemBackground"
+ />
</LinearLayout>
<!-- Numeric keyboard -->
@@ -125,9 +91,14 @@
android:layout_marginEnd="4dip"
android:paddingTop="4dip"
android:paddingBottom="4dip"
- android:background="#80ffffff"
+ android:background="#40000000"
android:keyBackground="@*android:drawable/btn_keyboard_key_ics"
android:clickable="true"
/>
+ <Space
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/kg_secure_padding_height"
+ android:background="@drawable/lockscreen_protection_pattern" />
+
</com.android.internal.policy.impl.keyguard.KeyguardSimPukView>
diff --git a/core/res/res/layout/media_route_list_item.xml b/core/res/res/layout/media_route_list_item.xml
index 53d813e..423d544 100644
--- a/core/res/res/layout/media_route_list_item.xml
+++ b/core/res/res/layout/media_route_list_item.xml
@@ -24,7 +24,8 @@
android:layout_height="56dp"
android:scaleType="center"
android:id="@+id/icon"
- android:visibility="gone" />
+ android:visibility="gone"
+ android:duplicateParentState="true" />
<LinearLayout android:layout_width="0dp"
android:layout_height="match_parent"
@@ -32,21 +33,24 @@
android:orientation="vertical"
android:gravity="start|center_vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:duplicateParentState="true">
<TextView android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium" />
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:duplicateParentState="true" />
<TextView android:id="@android:id/text2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceSmall" />
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:duplicateParentState="true" />
</LinearLayout>
<ImageButton
@@ -56,6 +60,7 @@
android:background="?android:attr/selectableItemBackground"
android:src="@drawable/ic_media_group_expand"
android:scaleType="center"
- android:visibility="gone" />
+ android:visibility="gone"
+ android:duplicateParentState="true" />
</LinearLayout>
diff --git a/core/res/res/layout/sms_short_code_confirmation_dialog.xml b/core/res/res/layout/sms_short_code_confirmation_dialog.xml
index ed08375..ec39d97 100644
--- a/core/res/res/layout/sms_short_code_confirmation_dialog.xml
+++ b/core/res/res/layout/sms_short_code_confirmation_dialog.xml
@@ -33,29 +33,54 @@
android:paddingLeft="16dip"
android:paddingRight="16dip"
android:paddingTop="8dip"
- android:paddingBottom="8dip"/>
+ android:paddingBottom="16dip" />
- <LinearLayout android:id="@+id/sms_short_code_detail_layout"
- android:layout_width="match_parent"
+ <TableLayout android:id="@+id/sms_short_code_detail_layout"
+ android:shrinkColumns="1"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:gravity="center_vertical"
- android:minHeight="@dimen/alert_dialog_title_height"
- android:layout_marginLeft="16dip"
- android:layout_marginRight="16dip">
- <ImageView android:id="@+id/sms_short_code_coins_icon"
+ android:paddingLeft="16dip"
+ android:paddingRight="16dip">
+
+ <TableRow
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingRight="8dip"
- android:src="@null" />
- <TextView android:id="@+id/sms_short_code_detail_message"
- style="?android:attr/textAppearanceMedium"
+ android:layout_height="wrap_content" >
+
+ <ImageView android:id="@+id/sms_short_code_coins_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="8dip"
+ android:paddingRight="8dip"
+ android:src="@null" />
+ <TextView android:id="@+id/sms_short_code_detail_message"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
- </LinearLayout>
+ </TableRow>
- <CheckBox android:id="@+id/sms_short_code_remember_choice_checkbox"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/sms_short_code_remember_choice" />
+ <TableRow
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+
+ <CheckBox android:id="@+id/sms_short_code_remember_choice_checkbox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingRight="8dip" />
+ <TextView android:id="@+id/sms_short_code_remember_choice_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/sms_short_code_remember_choice" />
+ </TableRow>
+
+ <TableRow
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+
+ <Space android:layout_gravity="fill" />
+ <TextView android:id="@+id/sms_short_code_remember_undo_instruction"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </TableRow>
+
+ </TableLayout>
+
</LinearLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 9759bdc..7698624 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5307,9 +5307,9 @@
<!-- Use <code>dream</code> as the root tag of the XML resource that
describes an
- {@link android.service.dreams.Dream}, which is
+ {@link android.service.dreams.DreamService}, which is
referenced from its
- {@link android.service.dreams.Dream#DREAM_META_DATA}
+ {@link android.service.dreams.DreamService#DREAM_META_DATA}
meta-data entry. Described here are the attributes that can be
included in that tag. -->
<declare-styleable name="Dream">
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 0775040..58b6572 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1391,6 +1391,9 @@
<attr name="uiOptions" />
<attr name="parentActivityName" />
<attr name="singleUser" />
+ <!-- @hide This broacast receiver will only receive broadcasts for the
+ primary user. Can only be used with receivers. -->
+ <attr name="primaryUserOnly" format="boolean" />
</declare-styleable>
<!-- The <code>activity-alias</code> tag declares a new
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 02aa537..51dc0d2 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3107,15 +3107,18 @@
<!-- The message text for the SMS short code confirmation dialog. [CHAR LIMIT=NONE] -->
<string name="sms_short_code_confirm_message"><b><xliff:g id="app_name">%1$s</xliff:g></b> would like to send a message to <b><xliff:g id="dest_address">%2$s</xliff:g></b>.</string>
<!-- Message details for the SMS short code confirmation dialog (possible premium short code). [CHAR LIMIT=NONE] -->
- <string name="sms_short_code_details">This may cause charges on your mobile account.</string>
+ <string name="sms_short_code_details">This <font fgcolor="#ffffb060">may cause charges</font> on your mobile account.</string>
<!-- Message details for the SMS short code confirmation dialog (premium short code). [CHAR LIMIT=NONE] -->
- <string name="sms_premium_short_code_details">This will cause charges on your mobile account.</string>
+ <string name="sms_premium_short_code_details"><font fgcolor="#ffffb060">This will cause charges on your mobile account.</font></string>
<!-- Text of the approval button for the SMS short code confirmation dialog. [CHAR LIMIT=30] -->
<string name="sms_short_code_confirm_allow">Send</string>
<!-- Text of the cancel button for the SMS short code confirmation dialog. [CHAR LIMIT=30] -->
<string name="sms_short_code_confirm_deny">Cancel</string>
<!-- Text of the checkbox for the SMS short code confirmation dialog to remember the user's choice. [CHAR LIMIT=40] -->
<string name="sms_short_code_remember_choice">Remember my choice</string>
+ <!-- Text shown when remember checkbox is checked to inform the user how they may undo the setting. [CHAR LIMIT=40] -->
+ <string name="sms_short_code_remember_undo_instruction">You can change this later in Settings\u00A0>\u00A0Apps"</string>
+
<!-- Text of the approval button for the SMS short code confirmation dialog when checkbox is checked. [CHAR LIMIT=30] -->
<string name="sms_short_code_confirm_always_allow">Always Allow</string>
<!-- Text of the cancel button for the SMS short code confirmation dialog when checkbox is checked. [CHAR LIMIT=30] -->
@@ -3768,8 +3771,8 @@
<!-- Name of the default audio route when an audio dock is connected. [CHAR LIMIT=50] -->
<string name="default_audio_route_name_dock_speakers">Dock speakers</string>
- <!-- Name of the default audio route when HDMI is connected. [CHAR LIMIT=50] -->
- <string name="default_audio_route_name_hdmi">HDMI audio</string>
+ <!-- Name of the default media route when HDMI is connected. [CHAR LIMIT=50] -->
+ <string name="default_media_route_name_hdmi">HDMI</string>
<!-- Name of the default audio route category. [CHAR LIMIT=50] -->
<string name="default_audio_route_category_name">System</string>
@@ -3783,6 +3786,18 @@
<!-- Content description of a MediaRouteButton for accessibility support -->
<string name="media_route_button_content_description">Media output</string>
+ <!-- Status message for remote routes attempting to scan/determine availability -->
+ <string name="media_route_status_scanning">Scanning...</string>
+
+ <!-- Status message for a remote route attempting to connect -->
+ <string name="media_route_status_connecting">Connecting...</string>
+
+ <!-- Status message for a remote route that is confirmed to be available for connection -->
+ <string name="media_route_status_available">Available</string>
+
+ <!-- Status message for remote routes that are not available for connection right now -->
+ <string name="media_route_status_not_available">Not available</string>
+
<!-- Display manager service -->
<!-- Name of the built-in display. [CHAR LIMIT=50] -->
@@ -3818,10 +3833,12 @@
<string name="kg_pin_instructions">Enter PIN</string>
<!-- Instructions for using the password unlock screen -->
<string name="kg_password_instructions">Enter Password</string>
- <!-- Hint shown in the PUK unlock screen PUK TextView -->
- <string name="kg_puk_enter_puk_hint">PUK code</string>
+ <!-- Hint shown in the PUK screen that asks the user to enter the PUK code given to them by their provider -->
+ <string name="kg_puk_enter_puk_hint">SIM is now disabled. Enter PUK code to continue. Contact carrier for details.</string>
<!-- Hint shown in the PUK unlock screen PIN TextView -->
- <string name="kg_puk_enter_pin_hint">New PIN code</string>
+ <string name="kg_puk_enter_pin_hint">Enter desired PIN code</string>
+ <!-- Message shown when the user needs to confirm the PIN they just entered in the PUK screen -->
+ <string name="kg_enter_confirm_pin_hint">Confirm desired PIN code</string>
<!-- Message shown in dialog while the device is unlocking the SIM card -->
<string name="kg_sim_unlock_progress_dialog_message">Unlocking SIM card\u2026</string>
<!-- Message shown when the user enters the wrong PIN code -->
@@ -3829,11 +3846,11 @@
<!-- Message shown when the user enters an invalid SIM pin password in PUK screen -->
<string name="kg_invalid_sim_pin_hint">Type a PIN that is 4 to 8 numbers.</string>
<!-- Message shown when the user enters an invalid PUK code in the PUK screen -->
- <string name="kg_invalid_sim_puk_hint">Type a PUK that is 8 numbers or longer.</string>
- <!-- Instructions for PUK unlock screen -->
- <string name="kg_sim_puk_recovery_hint">Type PUK and new PIN code</string>
+ <string name="kg_invalid_sim_puk_hint">PUK code should be 8 numbers or more.</string>
<!-- Message shown when the user enters an invalid PUK code -->
- <string name="kg_invalid_puk">The PUK you typed isn\'t correct.</string>
+ <string name="kg_invalid_puk">Re-enter the correct PUK code. Repeated attempts will permanently disable the SIM.</string>
+ <!-- String shown in PUK screen when PIN codes don't match -->
+ <string name="kg_invalid_confirm_pin_hint" product="default">PIN codes does not match</string>
<!-- Message shown when the user exceeds the maximum number of pattern attempts -->
<string name="kg_login_too_many_attempts">Too many pattern attempts</string>
<!-- Instructions show in account unlock screen allowing user to enter their email password -->
@@ -3849,7 +3866,7 @@
<!-- Hint text shown when user has too many failed password attempts in account unlock screen of keyguard -->
<string name="kg_login_account_recovery_hint">Forgot your username or password\?\nVisit <b>google.com/accounts/recovery</b>.</string>
<!-- Message shown while device checks username/password in account unlock screen of keyguard -->
- <string name="kg_login_checking_password">Checking\u2026</string>
+ <string name="kg_login_checking_password">Unlocking SIM\u2026</string>
<!-- Message shown in dialog when max number of attempts are reached for PIN screen of keyguard -->
<string name="kg_too_many_failed_pin_attempts_dialog_message">
You have incorrectly typed your PIN <xliff:g id="number">%d</xliff:g> times.
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 9a4136b..160495c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -216,6 +216,7 @@
<java-symbol type="id" name="sms_short_code_detail_layout" />
<java-symbol type="id" name="sms_short_code_detail_message" />
<java-symbol type="id" name="sms_short_code_remember_choice_checkbox" />
+ <java-symbol type="id" name="sms_short_code_remember_undo_instruction" />
<java-symbol type="attr" name="actionModeShareDrawable" />
<java-symbol type="attr" name="alertDialogCenterButtons" />
@@ -758,6 +759,7 @@
<java-symbol type="string" name="sms_short_code_confirm_message" />
<java-symbol type="string" name="sms_short_code_details" />
<java-symbol type="string" name="sms_premium_short_code_details" />
+ <java-symbol type="string" name="sms_short_code_remember_undo_instruction" />
<java-symbol type="string" name="submit" />
<java-symbol type="string" name="sync_binding_label" />
<java-symbol type="string" name="sync_do_nothing" />
@@ -823,9 +825,13 @@
<java-symbol type="string" name="default_audio_route_name" />
<java-symbol type="string" name="default_audio_route_name_headphones" />
<java-symbol type="string" name="default_audio_route_name_dock_speakers" />
- <java-symbol type="string" name="default_audio_route_name_hdmi" />
+ <java-symbol type="string" name="default_media_route_name_hdmi" />
<java-symbol type="string" name="default_audio_route_category_name" />
<java-symbol type="string" name="safe_media_volume_warning" />
+ <java-symbol type="string" name="media_route_status_scanning" />
+ <java-symbol type="string" name="media_route_status_connecting" />
+ <java-symbol type="string" name="media_route_status_available" />
+ <java-symbol type="string" name="media_route_status_not_available" />
<java-symbol type="plurals" name="abbrev_in_num_days" />
<java-symbol type="plurals" name="abbrev_in_num_hours" />
@@ -1088,7 +1094,6 @@
<java-symbol type="xml" name="kg_password_kbd_numeric" />
<java-symbol type="xml" name="power_profile" />
<java-symbol type="xml" name="time_zones_by_country" />
- <java-symbol type="xml" name="sms_short_codes" />
<java-symbol type="raw" name="accessibility_gestures" />
<java-symbol type="raw" name="incognito_mode_start_page" />
@@ -1270,10 +1275,7 @@
<java-symbol type="id" name="glow_pad_view" />
<java-symbol type="id" name="sim_pin_entry" />
<java-symbol type="id" name="delete_button" />
- <java-symbol type="id" name="sim_puk_entry" />
<java-symbol type="id" name="sim_pin_entry" />
- <java-symbol type="id" name="puk_delete_button" />
- <java-symbol type="id" name="pin_delete_button" />
<java-symbol type="id" name="keyguard_user_avatar" />
<java-symbol type="id" name="keyguard_user_name" />
<java-symbol type="id" name="keyguard_transport_control" />
@@ -1404,6 +1406,8 @@
<java-symbol type="string" name="kg_failed_attempts_almost_at_wipe" />
<java-symbol type="string" name="kg_failed_attempts_now_wiping" />
<java-symbol type="string" name="kg_failed_attempts_almost_at_login" />
+ <java-symbol type="string" name="kg_enter_confirm_pin_hint" />
+ <java-symbol type="string" name="kg_invalid_confirm_pin_hint" />
<!-- From services -->
<java-symbol type="anim" name="screen_rotate_0_enter" />
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
deleted file mode 100644
index 8b395af..0000000
--- a/core/res/res/xml/sms_short_codes.xml
+++ /dev/null
@@ -1,189 +0,0 @@
-<?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.
-*/
--->
-
-<!-- Regex patterns for SMS short codes by country. -->
-<shortcodes>
-
- <!-- The country attribute is the ISO country code of the user's account (from SIM card or NV).
- The pattern attribute is a regex that matches all SMS short codes for the country.
- The premium attribute is a regex that matches premium rate SMS short codes.
- The free attribute matches short codes that we know will not cost the user, such as
- emergency numbers. The standard attribute matches short codes that are billed at the
- standard SMS rate. The user is warned when the destination phone number matches the
- "pattern" or "premium" regexes, and does not match the "free" or "standard" regexes. -->
-
- <!-- Harmonised European Short Codes are 6 digit numbers starting with 116 (free helplines).
- Premium patterns include short codes from: http://aonebill.com/coverage&tariffs
- and http://mobilcent.com/info-worldwide.asp and extracted from:
- http://smscoin.net/software/engine/WordPress/Paid+SMS-registration/ -->
-
- <!-- Albania: 5 digits, known short codes listed -->
- <shortcode country="al" pattern="\\d{5}" premium="15191|55[56]00" />
-
- <!-- Armenia: 3-4 digits, emergency numbers 10[123] -->
- <shortcode country="am" pattern="\\d{3,4}" premium="11[2456]1|3024" free="10[123]" />
-
- <!-- Austria: 10 digits, premium prefix 09xx, plus EU -->
- <shortcode country="at" pattern="11\\d{4}" premium="09.*" free="116\\d{3}" />
-
- <!-- Australia: 6 or 8 digits starting with "19" -->
- <shortcode country="au" pattern="19(?:\\d{4}|\\d{6})" premium="19998882" />
-
- <!-- Azerbaijan: 4-5 digits, known premium codes listed -->
- <shortcode country="az" pattern="\\d{4,5}" premium="330[12]|87744|901[234]|93(?:94|101)|9426|9525" />
-
- <!-- Belgium: 4 digits, plus EU: http://www.mobileweb.be/en/mobileweb/sms-numberplan.asp -->
- <shortcode country="be" premium="\\d{4}" free="8\\d{3}|116\\d{3}" />
-
- <!-- Bulgaria: 4-5 digits, plus EU -->
- <shortcode country="bg" pattern="\\d{4,5}" premium="18(?:16|423)|19(?:1[56]|35)" free="116\\d{3}" />
-
- <!-- Belarus: 4 digits -->
- <shortcode country="by" pattern="\\d{4}" premium="3336|4161|444[4689]|501[34]|7781" />
-
- <!-- Canada: 5-6 digits -->
- <shortcode country="ca" pattern="\\d{5,6}" premium="60999|88188" />
-
- <!-- Switzerland: 3-5 digits: http://www.swisscom.ch/fxres/kmu/thirdpartybusiness_code_of_conduct_en.pdf -->
- <shortcode country="ch" pattern="[2-9]\\d{2,4}" premium="543|83111" />
-
- <!-- China: premium shortcodes start with "1066", free shortcodes start with "1065":
- http://clients.txtnation.com/entries/197192-china-premium-sms-short-code-requirements -->
- <shortcode country="cn" premium="1066.*" free="1065.*" />
-
- <!-- Cyprus: 4-6 digits (not confirmed), known premium codes listed, plus EU -->
- <shortcode country="cy" pattern="\\d{4,6}" premium="7510" free="116\\d{3}" />
-
- <!-- Czech Republic: 7-8 digits, starting with 9, plus EU:
- http://www.o2.cz/osobni/en/services-by-alphabet/91670-premium_sms.html -->
- <shortcode country="cz" premium="9\\d{6,7}" free="116\\d{3}" />
-
- <!-- Germany: 4-5 digits plus 1232xxx (premium codes from http://www.vodafone.de/infofaxe/537.pdf and http://premiumdienste.eplus.de/pdf/kodex.pdf), plus EU. To keep the premium regex from being too large, it only includes payment processors that have been used by SMS malware, with the regular pattern matching the other premium short codes. -->
- <shortcode country="de" pattern="\\d{4,5}|1232\\d{3}" premium="11(?:111|833)|1232(?:013|021|060|075|286|358)|118(?:44|80|86)|20[25]00|220(?:21|22|88|99)|221(?:14|21)|223(?:44|53|77)|224[13]0|225(?:20|59|90)|226(?:06|10|20|26|30|40|56|70)|227(?:07|33|39|66|76|78|79|88|99)|228(?:08|11|66|77)|23300|30030|3[12347]000|330(?:33|55|66)|33(?:233|331|366|533)|34(?:34|567)|37000|40(?:040|123|444|[3568]00)|41(?:010|414)|44(?:000|044|344|44[24]|544)|50005|50100|50123|50555|51000|52(?:255|783)|54(?:100|2542)|55(?:077|[24]00|222|333|55|[12369]55)|56(?:789|886)|60800|6[13]000|66(?:[12348]66|566|766|777|88|999)|68888|70(?:07|123|777)|76766|77(?:007|070|222|444|[567]77)|80(?:008|123|888)|82(?:002|[378]00|323|444|472|474|488|727)|83(?:005|[169]00|333|830)|84(?:141|300|32[34]|343|488|499|777|888)|85888|86(?:188|566|640|644|650|677|868|888)|870[24]9|871(?:23|[49]9)|872(?:1[0-8]|49|99)|87499|875(?:49|55|99)|876(?:0[1367]|1[1245678]|54|99)|877(?:00|99)|878(?:15|25|3[567]|8[12])|87999|880(?:08|44|55|77|99)|88688|888(?:03|10|8|89)|8899|90(?:009|999)|99999" free="116\\d{3}" />
-
- <!-- Denmark: see http://iprs.webspacecommerce.com/Denmark-Premium-Rate-Numbers -->
- <shortcode country="dk" pattern="\\d{4,5}" premium="1\\d{3}" free="116\\d{3}" />
-
- <!-- Estonia: short codes 3-5 digits starting with 1, plus premium 7 digit numbers starting with 90, plus EU.
- http://www.tja.ee/public/documents/Elektrooniline_side/Oigusaktid/ENG/Estonian_Numbering_Plan_annex_06_09_2010.mht -->
- <shortcode country="ee" pattern="1\\d{2,4}" premium="90\\d{5}|15330|1701[0-3]" free="116\\d{3}" />
-
- <!-- Spain: 5-6 digits: 25xxx, 27xxx, 280xx, 35xxx, 37xxx, 795xxx, 797xxx, 995xxx, 997xxx, plus EU.
- http://www.legallink.es/?q=en/content/which-current-regulatory-status-premium-rate-services-spain -->
- <shortcode country="es" premium="[23][57]\\d{3}|280\\d{2}|[79]9[57]\\d{3}" free="116\\d{3}" />
-
- <!-- Finland: 5-6 digits, premium 0600, 0700: http://en.wikipedia.org/wiki/Telephone_numbers_in_Finland -->
- <shortcode country="fi" pattern="\\d{5,6}" premium="0600.*|0700.*|171(?:59|63)" free="116\\d{3}" />
-
- <!-- France: 5 digits, free: 3xxxx, premium [4-8]xxxx, plus EU:
- http://clients.txtnation.com/entries/161972-france-premium-sms-short-code-requirements -->
- <shortcode country="fr" premium="[4-8]\\d{4}" free="3\\d{4}|116\\d{3}" />
-
- <!-- United Kingdom (Great Britain): 4-6 digits, common codes [5-8]xxxx, plus EU:
- http://www.short-codes.com/media/Co-regulatoryCodeofPracticeforcommonshortcodes170206.pdf -->
- <shortcode country="gb" pattern="\\d{4,6}" premium="[5-8]\\d{4}" free="116\\d{3}" />
-
- <!-- Georgia: 4 digits, known premium codes listed -->
- <shortcode country="ge" pattern="\\d{4}" premium="801[234]|888[239]" />
-
- <!-- Greece: 5 digits (54xxx, 19yxx, x=0-9, y=0-5): http://www.cmtelecom.com/premium-sms/greece -->
- <shortcode country="gr" pattern="\\d{5}" premium="54\\d{3}|19[0-5]\\d{2}" free="116\\d{3}" />
-
- <!-- Hungary: 4 or 10 digits starting with 1 or 0, plus EU:
- http://clients.txtnation.com/entries/209633-hungary-premium-sms-short-code-regulations -->
- <shortcode country="hu" pattern="[01](?:\\d{3}|\\d{9})" premium="0691227910|1784" free="116\\d{3}" />
-
- <!-- Ireland: 5 digits, 5xxxx (50xxx=free, 5[12]xxx=standard), plus EU:
- http://www.comreg.ie/_fileupload/publications/ComReg1117.pdf -->
- <shortcode country="ie" pattern="\\d{5}" premium="5[3-9]\\d{3}" free="50\\d{3}|116\\d{3}" standard="5[12]\\d{3}" />
-
- <!-- Israel: 4 digits, known premium codes listed -->
- <shortcode country="il" pattern="\\d{4}" premium="4422|4545" />
-
- <!-- Italy: 5 digits (premium=4xxxx), plus EU:
- http://clients.txtnation.com/attachments/token/di5kfblvubttvlw/?name=Italy_CASP_EN.pdf -->
- <shortcode country="it" pattern="\\d{5}" premium="4\\d{4}" free="116\\d{3}" />
-
- <!-- Kyrgyzstan: 4 digits, known premium codes listed -->
- <shortcode country="kg" pattern="\\d{4}" premium="415[2367]|444[69]" />
-
- <!-- Kazakhstan: 4 digits, known premium codes listed: http://smscoin.net/info/pricing-kazakhstan/ -->
- <shortcode country="kz" pattern="\\d{4}" premium="335[02]|4161|444[469]|77[2359]0|8444|919[3-5]|968[2-5]" />
-
- <!-- Lithuania: 3-5 digits, known premium codes listed, plus EU -->
- <shortcode country="lt" pattern="\\d{3,5}" premium="13[89]1|1394|16[34]5" free="116\\d{3}" />
-
- <!-- Luxembourg: 5 digits, 6xxxx, plus EU:
- http://www.luxgsm.lu/assets/files/filepage/file_1253803400.pdf -->
- <shortcode country="lu" premium="6\\d{4}" free="116\\d{3}" />
-
- <!-- Latvia: 4 digits, known premium codes listed, plus EU -->
- <shortcode country="lv" pattern="\\d{4}" premium="18(?:19|63|7[1-4])" free="116\\d{3}" />
-
- <!-- Mexico: 4-5 digits (not confirmed), known premium codes listed -->
- <shortcode country="mx" pattern="\\d{4,5}" premium="53035|7766" />
-
- <!-- Malaysia: 5 digits: http://www.skmm.gov.my/attachment/Consumer_Regulation/Mobile_Content_Services_FAQs.pdf -->
- <shortcode country="my" pattern="\\d{5}" premium="32298|33776" />
-
- <!-- The Netherlands, 4 digits, known premium codes listed, plus EU -->
- <shortcode country="nl" pattern="\\d{4}" premium="4466|5040" free="116\\d{3}" />
-
- <!-- Norway: 4-5 digits (not confirmed), known premium codes listed -->
- <shortcode country="no" pattern="\\d{4,5}" premium="2201|222[67]" />
-
- <!-- New Zealand: 3-4 digits, known premium codes listed -->
- <shortcode country="nz" pattern="\\d{3,4}" premium="3903|8995" />
-
- <!-- Poland: 4-5 digits (not confirmed), known premium codes listed, plus EU -->
- <shortcode country="pl" pattern="\\d{4,5}" premium="74240|79(?:10|866)|92525" free="116\\d{3}" />
-
- <!-- Portugal: 5 digits, plus EU:
- http://clients.txtnation.com/entries/158326-portugal-premium-sms-short-code-regulations -->
- <shortcode country="pt" premium="6[1289]\\d{3}" free="116\\d{3}" />
-
- <!-- Romania: 4 digits, plus EU: http://www.simplus.ro/en/resources/glossary-of-terms/ -->
- <shortcode country="ro" pattern="\\d{4}" premium="12(?:63|66|88)|13(?:14|80)" free="116\\d{3}" />
-
- <!-- Russia: 4 digits, known premium codes listed: http://smscoin.net/info/pricing-russia/ -->
- <shortcode country="ru" pattern="\\d{4}" premium="1(?:1[56]1|899)|2(?:09[57]|322|47[46]|880|990)|3[589]33|4161|44(?:4[3-9]|81)|77(?:33|81)" />
-
- <!-- Sweden: 5 digits (72xxx), plus EU: http://www.viatel.se/en/premium-sms/ -->
- <shortcode country="se" premium="72\\d{3}" free="116\\d{3}" />
-
- <!-- Singapore: 5 digits: http://clients.txtnation.com/entries/306442-singapore-premium-sms-short-code-requirements
- Free government directory info at 74688: http://app.sgdi.gov.sg/sms_help.asp -->
- <shortcode country="sg" pattern="7\\d{4}" premium="73800" standard="74688" />
-
- <!-- Slovenia: 4 digits (premium=3xxx, 6xxx, 8xxx), plus EU: http://www.cmtelecom.com/premium-sms/slovenia -->
- <shortcode country="si" pattern="\\d{4}" premium="[368]\\d{3}" free="116\\d{3}" />
-
- <!-- Slovakia: 4 digits (premium), plus EU: http://www.cmtelecom.com/premium-sms/slovakia -->
- <shortcode country="sk" premium="\\d{4}" free="116\\d{3}" />
-
- <!-- Tajikistan: 4 digits, known premium codes listed -->
- <shortcode country="tj" pattern="\\d{4}" premium="11[3-7]1|4161|4333|444[689]" />
-
- <!-- Ukraine: 4 digits, known premium codes listed -->
- <shortcode country="ua" pattern="\\d{4}" premium="444[3-9]|70[579]4|7540" />
-
- <!-- USA: 5-6 digits (premium codes from https://www.premiumsmsrefunds.com/ShortCodes.htm) -->
- <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" />
-
-</shortcodes>
diff --git a/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java b/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java
index 105bcba..9b216cb 100644
--- a/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java
+++ b/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java
@@ -40,11 +40,13 @@
private final static Uri ORIGINATING_URI = Uri.parse(ORIGINATING_URI_STRING);
private final static Uri REFERRER = Uri.parse(REFERRER_STRING);
+ private final static int ORIGINATING_UID = 10042;
+
private final static ManifestDigest MANIFEST_DIGEST = new ManifestDigest(DIGEST_BYTES);
public void testParcel() throws Exception {
VerificationParams expected = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
- REFERRER, MANIFEST_DIGEST);
+ REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
Parcel parcel = Parcel.obtain();
expected.writeToParcel(parcel, 0);
@@ -58,71 +60,86 @@
assertEquals(REFERRER, actual.getReferrer());
+ assertEquals(ORIGINATING_UID, actual.getOriginatingUid());
+
assertEquals(MANIFEST_DIGEST, actual.getManifestDigest());
}
public void testEquals_Success() throws Exception {
VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
- REFERRER, MANIFEST_DIGEST);
+ REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
VerificationParams params2 = new VerificationParams(
Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
- Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+ Uri.parse(REFERRER_STRING), ORIGINATING_UID, new ManifestDigest(DIGEST_BYTES));
assertEquals(params1, params2);
}
public void testEquals_VerificationUri_Failure() throws Exception {
VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
- REFERRER, MANIFEST_DIGEST);
+ REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
VerificationParams params2 = new VerificationParams(
Uri.parse("http://a.different.uri/"), Uri.parse(ORIGINATING_URI_STRING),
- Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+ Uri.parse(REFERRER_STRING), ORIGINATING_UID, new ManifestDigest(DIGEST_BYTES));
assertFalse(params1.equals(params2));
}
public void testEquals_OriginatingUri_Failure() throws Exception {
VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
- REFERRER, MANIFEST_DIGEST);
+ REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
VerificationParams params2 = new VerificationParams(
Uri.parse(VERIFICATION_URI_STRING), Uri.parse("http://a.different.uri/"),
- Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+ Uri.parse(REFERRER_STRING), ORIGINATING_UID, new ManifestDigest(DIGEST_BYTES));
assertFalse(params1.equals(params2));
}
public void testEquals_Referrer_Failure() throws Exception {
VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
- REFERRER, MANIFEST_DIGEST);
+ REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
VerificationParams params2 = new VerificationParams(
Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
- Uri.parse("http://a.different.uri/"), new ManifestDigest(DIGEST_BYTES));
+ Uri.parse("http://a.different.uri/"), ORIGINATING_UID,
+ new ManifestDigest(DIGEST_BYTES));
+
+ assertFalse(params1.equals(params2));
+ }
+
+ public void testEquals_Originating_Uid_Failure() throws Exception {
+ VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+ REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
+
+ VerificationParams params2 = new VerificationParams(
+ Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+ Uri.parse(REFERRER_STRING), 12345, new ManifestDigest(DIGEST_BYTES));
assertFalse(params1.equals(params2));
}
public void testEquals_ManifestDigest_Failure() throws Exception {
VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
- REFERRER, MANIFEST_DIGEST);
+ REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
VerificationParams params2 = new VerificationParams(
Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
- Uri.parse(REFERRER_STRING), new ManifestDigest("a different digest".getBytes()));
+ Uri.parse(REFERRER_STRING), ORIGINATING_UID,
+ new ManifestDigest("a different digest".getBytes()));
assertFalse(params1.equals(params2));
}
public void testEquals_InstallerUid_Failure() throws Exception {
VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
- REFERRER, MANIFEST_DIGEST);
+ REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
VerificationParams params2 = new VerificationParams(
Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
- Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+ Uri.parse(REFERRER_STRING), ORIGINATING_UID, new ManifestDigest(DIGEST_BYTES));
params2.setInstallerUid(INSTALLER_UID);
assertFalse(params1.equals(params2));
@@ -130,65 +147,78 @@
public void testHashCode_Success() throws Exception {
VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
- REFERRER, MANIFEST_DIGEST);
+ REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
VerificationParams params2 = new VerificationParams(
Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
- Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+ Uri.parse(REFERRER_STRING), ORIGINATING_UID, new ManifestDigest(DIGEST_BYTES));
assertEquals(params1.hashCode(), params2.hashCode());
}
public void testHashCode_VerificationUri_Failure() throws Exception {
VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
- REFERRER, MANIFEST_DIGEST);
+ REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
VerificationParams params2 = new VerificationParams(null, Uri.parse(ORIGINATING_URI_STRING),
- Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+ Uri.parse(REFERRER_STRING), ORIGINATING_UID, new ManifestDigest(DIGEST_BYTES));
assertFalse(params1.hashCode() == params2.hashCode());
}
public void testHashCode_OriginatingUri_Failure() throws Exception {
VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
- REFERRER, MANIFEST_DIGEST);
+ REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
VerificationParams params2 = new VerificationParams(
Uri.parse(VERIFICATION_URI_STRING), Uri.parse("http://a.different.uri/"),
- Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+ Uri.parse(REFERRER_STRING), ORIGINATING_UID, new ManifestDigest(DIGEST_BYTES));
assertFalse(params1.hashCode() == params2.hashCode());
}
public void testHashCode_Referrer_Failure() throws Exception {
VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
- REFERRER, MANIFEST_DIGEST);
+ REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
VerificationParams params2 = new VerificationParams(
Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING), null,
- new ManifestDigest(DIGEST_BYTES));
+ ORIGINATING_UID, new ManifestDigest(DIGEST_BYTES));
+
+ assertFalse(params1.hashCode() == params2.hashCode());
+ }
+
+ public void testHashCode_Originating_Uid_Failure() throws Exception {
+ VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+ REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
+
+ VerificationParams params2 = new VerificationParams(
+ Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+ Uri.parse(REFERRER_STRING), 12345, new ManifestDigest(DIGEST_BYTES));
assertFalse(params1.hashCode() == params2.hashCode());
}
public void testHashCode_ManifestDigest_Failure() throws Exception {
VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
- REFERRER, MANIFEST_DIGEST);
+ REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
VerificationParams params2 = new VerificationParams(
Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
- Uri.parse(REFERRER_STRING), new ManifestDigest("a different digest".getBytes()));
+ Uri.parse(REFERRER_STRING), ORIGINATING_UID,
+ new ManifestDigest("a different digest".getBytes()));
assertFalse(params1.hashCode() == params2.hashCode());
}
public void testHashCode_InstallerUid_Failure() throws Exception {
VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
- REFERRER, MANIFEST_DIGEST);
+ REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
VerificationParams params2 = new VerificationParams(
Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
- Uri.parse(REFERRER_STRING), new ManifestDigest("a different digest".getBytes()));
+ Uri.parse(REFERRER_STRING), ORIGINATING_UID,
+ new ManifestDigest("a different digest".getBytes()));
params2.setInstallerUid(INSTALLER_UID);
assertFalse(params1.hashCode() == params2.hashCode());
diff --git a/docs/html/distribute/distribute_toc.cs b/docs/html/distribute/distribute_toc.cs
index 76073fb..84103b9 100644
--- a/docs/html/distribute/distribute_toc.cs
+++ b/docs/html/distribute/distribute_toc.cs
@@ -75,7 +75,7 @@
<li><a href="<?cs var:toroot ?>distribute/promote/device-art.html">
<span class="en">Device Art Generator</a></li>
<li><a href="<?cs var:toroot ?>distribute/googleplay/promote/brand.html">
- <span class="en">Brand Assets and Guidelines</a></li>
+ <span class="en">Brand Guidelines</a></li>
</ul>
</li>
diff --git a/docs/html/distribute/googleplay/promote/badges.jd b/docs/html/distribute/googleplay/promote/badges.jd
index 7b64be3..d6f15fb 100644
--- a/docs/html/distribute/googleplay/promote/badges.jd
+++ b/docs/html/distribute/googleplay/promote/badges.jd
@@ -13,7 +13,7 @@
wraps your screenshots in real device artwork.</p>
<p>For guidelines when using the Google Play badge and other brand assets,
-see the <a href="{@docRoot}distribute/googleplay/promote/brand.html">Brand Assets and
+see the <a href="{@docRoot}distribute/googleplay/promote/brand.html">Brand
Guidelines</a>.</p>
<style type="text/css">
diff --git a/docs/html/distribute/googleplay/promote/brand.jd b/docs/html/distribute/googleplay/promote/brand.jd
index 4051553..875794a 100644
--- a/docs/html/distribute/googleplay/promote/brand.jd
+++ b/docs/html/distribute/googleplay/promote/brand.jd
@@ -1,151 +1,172 @@
-page.title=Brand Assets, Icons, and Guidelines
+page.title=Brand Guidelines
@jd:body
-<p>We encourage you to use the Android and Google Play brands in your
-promotional materials. You can use the icons and other assets on this page in
-any way you want, provided that you follow the guidelines described below.</p>
-<h2 id="brand-android">Android Brand</h2>
-<div>
- <div style="float:right;width:50%;padding:1.5em;">
- <img alt="" src="{@docRoot}images/brand/droid.gif">
+<p>We encourage you to use the Android and Google Play brands with your Android app
+promotional materials. You can use the icons and other assets on this page
+provided that you follow the guidelines described below.</p>
+
+<h2 id="brand-android">Android</h2>
+
+ <p>The following are guidelines for the Android brand
+ and related assets.</p>
+
+
+ <h4 style="clear:right">Android in text</h4>
+
+ <div style="float:right;clear:right;width:200px;margin:0 0 20px 30px">
+ <img alt="" src="{@docRoot}images/brand/mediaplayer.png">
+ </div>
+ <ul>
+ <li>Android™ should have a trademark symbol the first time it appears in a creative.</li>
+ <li>Android should always be capitalized and is never plural or possessive.</li>
+ <li>"Android" by itself cannot be used in the name of an application name or accessory product.
+Instead use "for Android."
+ <ul>
+ <li><span style="color:red">Incorrect</span>: "Android MediaPlayer"</li>
+ <li><span style="color:green">Correct</span>: "MediaPlayer for Android"</li>
+ </ul>
+ <p>If used with your logo, "for Android" needs to be smaller in size than your logo.
+ First instance of this use should be followed by a TM symbol, "for Android™".</p>
+ </li>
+ <li>Android may be used as a descriptor, as long as it is followed by a proper generic term.
+ <ul>
+ <li><span style="color:red">Incorrect</span>: "Android MediaPlayer" or "Android XYZ app"</li>
+ <li><span style="color:green">Correct</span>: "Android features" or "Android applications"</li>
+ </ul>
+ </li>
+ </ul>
+
+ <p>Any use of the Android name needs to include this
+ attribution in your communication:</p>
+ <blockquote><em>Android is a trademark of Google Inc.</em></blockquote></p>
+
+
+ <h4>Android robot</h4>
+
+ <div style="float:right;width:200px;margin-left:30px">
+ <img alt="" src="{@docRoot}images/brand/Android_Robot_100.png"
+ style="margin-left:50px">
+ <p style="text-align:center">
+ <a href="{@docRoot}images/brand/Android_Robot_100.png">100x118</a> |
+ <a href="{@docRoot}images/brand/Android_Robot_200.png">200x237</a><br>
+ <a href="{@docRoot}images/brand/Android_Robot_outlined.ai">Illustrator (.ai)</a></p>
</div>
- <div style="width:45%;">
- <h4>01/ Android Robot</h4>
-
- <p> Can be used, reproduced, and modified freely in marketing
- communications. Our standard color value for print is PMS 376C. Our online hex
- color is <span id= "android-green">#A4C639</span>.</p>
+ <p>The Android robot can be used, reproduced, and modified freely in marketing
+ communications. The color value for print is PMS 376C and the online hex
+ color is <span style="color:#A4C639">#A4C639</span>.</p>
<p>When using the Android Robot or any modification of it, proper attribution is
- required under the terms of the Creative Commons Attribution license. For more
- details on proper attribution, please see the <a
- href="{@docRoot}license.html#attribution">Content License</a> document. </p>
+ required under the terms of the <a href="http://creativecommons.org/licenses/by/3.0/">Creative
+Commons Attribution</a> license:</p>
+
+ <blockquote><em>The Android robot is reproduced or modified from work created and shared by Google and
+used according to terms described in the Creative Commons 3.0 Attribution License.</em></blockquote>
+
+ <p>You may not file trademark applications incorporating the Android robot logo or
+derivatives thereof. We want to ensure that the Android robot remains available
+for all to use.</p>
+
+
+<h4 style="clear:right">Android logo</h4>
+
+<div style="float:right;width:210px;margin-left:30px;margin-top:-10px">
+ <img alt="" src="{@docRoot}images/brand/android_logo_no.png">
+</div>
+
+<p>The Android logo may not be used. Nor can this be used with the Android robot.</p>
+<p>The custom typeface may not be used.</p>
+
+
+
+
+<h2 id="brand-google_play">Google Play</h2>
+
+
+ <p>The following are guidelines for the Google Play brand
+ and related assets.</p>
+
+<h4>Google Play in text</h4>
+
+<p>Always include a TM symbol on the first or most prominent instance of Google Play™
+in text.</p>
+
+<p>When referring to the mobile experience, use "Google Play" unless the text is clearly
+instructional for the user. For example, a marketing headline might read "Download our
+games on Google Play™," but instructional text woud read "Download our games using the Google
+Play™ Store app."
+
+ <p>Any use of the Google Play name or icon needs to include this
+ attribution in your communication:</p>
+
+<blockquote><em>Google Play is a trademark of Google Inc.</em></blockquote>
+
+
+ <div style="float:right;width:96px;margin-left:30px;margin-top:-20px">
+ <img src="{@docRoot}images/brand/Google_Play_Store_96.png" alt="">
+ <p style="text-align:center">
+ <a href="{@docRoot}images/brand/Google_Play_Store_48.png">48x48</a> |
+ <a href="{@docRoot}images/brand/Google_Play_Store_96.png">96x96</a><br>
+ <a href="{@docRoot}images/brand/Google_Play_Store.ai">Illustrator (.ai)</a>
+ </p>
</div>
-<div>
+
+<h4>Google Play Store icon</h4>
-<div style="clear:both">
- <div style="float:right;width:50%;padding:1.5em;">
- <img alt="" src="{@docRoot}images/brand/logo_android.gif">
- </div>
+<p>You may use the Google Play Store icon, but you may not modify it.</p>
- <div style="width:45%;">
- <h4>02/ Android Logo</h4>
+<p>When labeling or referring to the icon, the name can be either the full app
+name, Google Play Store, or the app display name, Play Store.</p>
- <p>The Android logo may not be used.</p>
- </div>
-<div>
-
-<div style="clear:both">
- <div style="float:right;width:50%;padding:1.5em;">
- <img alt="" src="{@docRoot}images/brand/norad.gif">
- </div>
-
- <div style="width:45%;">
- <h4>03/ Android Custom Typeface</h4>
-
- <p>The custom typeface may not be used.</p>
- </div>
-<div>
-
-<div style="clear:both">
- <div style="float:right;width:50%;padding:1.5em;">
- <img alt="" src="{@docRoot}images/brand/mediaplayer.gif">
- </div>
-
- <div style="width:45%;">
- <h4>04/ Android in Official Names</h4>
-<p>Any name with 'Android' alone may not be used in a name without permission. Any name
- with 'Droid' alone may not be used in a name.</p>
-
- <p>The word 'Android' may be used only as a descriptor, 'for Android'. If used with your
- logo, 'for Android' needs to be smaller in size than your logo. First instance of this
- use should be followed by a TM symbol, 'for Android™'.</p>
-
- <p>If you are not sure you meet these criteria, <a href=
- "http://services.google.com/permissions/application">please contact us</a>. </p>
- </div>
-<div>
-
-<div style="clear:both">
- <div style="float:right;width:50%;padding:1.5em;">
- <img alt="" src="{@docRoot}images/brand/learnmore.gif">
- </div>
-
- <div style="width:45%;">
- <h4>05/ Android in Messaging</h4>
- <p>
- May be used in text as a descriptor, as long as it is followed by a proper generic term
- (e.g. "Android™ application"). First instance of this use should be followed by a TM
- symbol.
- </p>
- </div>
-<div>
- <p class="caution"><strong>Note: Any usage of #04 or #05 needs to include footer attribution in your
- communication:</strong><br /><span style="margin-left:1.5em">
- "Android is a trademark of Google Inc."</span>
- </p>
-
-
-<h2 id="brand-google_play">Google Play Brand</h2>
-
- <img alt="" src="http://www.android.com/images/brand/google_play_logo_450.png"
- style="float:right;">
-
- <img alt="Android app on Google Play badge, large"
- src="{@docRoot}images/brand/en_app_rgb_wo_60.png"
- style="float:right;clear:right;">
-
- <img alt="Android app on Google Play badge, small"
- src="{@docRoot}images/brand/en_app_rgb_wo_45.png"
- style="float:right;margin:0 30px 30px">
-
- <img alt="Get it on Google Play badge, large"
- src="{@docRoot}images/brand/en_generic_rgb_wo_60.png"
- style="float:right;clear:right;">
-
- <img alt="Get it on Google Play badge, small"
- src="{@docRoot}images/brand/en_generic_rgb_wo_45.png"
- style="float:right;margin:0 30px 30px;">
- <h4>06/ <em>Get it on Google Play</em> Badge
- </h4>
- <p>
- The "Get it on Google Play" and "Android App on Google Play" logos are badges that you
- can use on your web site and promotional materials, to point to your products on Google
- Play.
- </p>
- <p>
- Guidelines for usage:
- </p>
- <ul>
- <li>Do not modify the color, proportions, spacing or any other aspect of the badge image.
- </li>
- <li>When used alongside logos for other application marketplaces, the Google Play logo
- should be of equal or greater size.</li>
- <li>When used online, the badge should link to either:
- <ul>
- <li>A list of products published by you, for example:<br />
- <span style="margin-left:1em;">http://play.google.com/store/search?q=<em>publisherName</em></span>
- </li>
- <li>A specific app product details page within Google Play, for example:<br />
- <span style="margin-left:1em;">http://play.google.com/store/apps/details?id=<em>packageName</em></span>
- </li>
- </ul>
- </li>
+<h4>Google Play badge</h4>
+
+ <div style="float:right;clear:right;width:172px;margin-left:30px">
+ <img src="{@docRoot}images/brand/en_app_rgb_wo_60.png" alt="">
+ <p style="text-align:center">
+ <a href="{@docRoot}images/brand/en_app_rgb_wo_45.png">129x45</a> |
+ <a href="{@docRoot}images/brand/en_app_rgb_wo_60.png">172x60</a><br>
+ <a href="{@docRoot}images/brand/en_app_rgb_wo.ai">Illustrator (.ai)</a></p>
+ </div>
+
+ <div style="float:right;clear:right;width:172px;margin-left:30px">
+ <img src="{@docRoot}images/brand/en_generic_rgb_wo_60.png" alt="">
+ <p style="text-align:center">
+ <a href="{@docRoot}images/brand/en_generic_rgb_wo_45.png">129x45</a> |
+ <a href="{@docRoot}images/brand/en_generic_rgb_wo_60.png">172x60</a><br>
+ <a href="{@docRoot}images/brand/en_generic_rgb_wo.ai">Illustrator (.ai)</a></p>
+ </div>
+
+ <p>The "Get it on Google Play" and "Android App on Google Play" logos are badges that you
+ can use on your web site and promotional materials, to point to your products on Google
+ Play.</p>
+
+ <ul>
+ <li>Do not modify the color, proportions, spacing or any other aspect of the badge image.
+ </li>
+ <li>When used alongside logos for other application marketplaces, the Google Play logo
+ should be of equal or greater size.</li>
+ <li>When used online, the badge should link to either:
+ <ul>
+ <li>A list of products published by you, for example:<br />
+ <span style="margin-left:1em;">http://play.google.com/store/search?q=<em>publisherName</em></span>
+ </li>
+ <li>A specific app product details page within Google Play, for example:<br />
+ <span style="margin-left:1em;">http://play.google.com/store/apps/details?id=<em>packageName</em></span>
+ </li>
+ </ul>
+ </li>
</ul>
- <p>For your convenience, you can use the
- <a href="{@docRoot}distribute/googleplay/promote/badges.html">Googe Play badge generator</a>
- to create badges that link to your apps on Google Play.</p>
-
- <p>For details on all the ways that you can link to your product details page in Google Play,
- see <a href="{@docRoot}distribute/googleplay/promote/linking.html">Linking to your products</a></p>
+ <p>For your convenience, you can use the
+ <a href="{@docRoot}distribute/googleplay/promote/badges.html">Googe Play badge generator</a>
+ to create badges that link to your apps on Google Play.</p>
+
+ <p>For details on all the ways that you can link to your product details page in Google Play,
+ see <a href="{@docRoot}distribute/googleplay/promote/linking.html">Linking to your products</a></p>
-<h2>Other Brands</h2>
-<p>Any other brands or icons depicted on this site are <em>not</em> are the property of their
-respective owners and usage is reserved. You must seek the developer for appropriate permission to use them.</p>
-
+<p>If you are not sure you meet these criteria, <a href=
+ "http://services.google.com/permissions/application">please contact us</a>. </p>
diff --git a/docs/html/distribute/googleplay/promote/linking.jd b/docs/html/distribute/googleplay/promote/linking.jd
index 4a1b198..2d3bd05 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="http://www.android.com/images/brand/get_it_on_play_logo_small.png" />
+ src="{@docRoot}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/images/brand/Android_Robot_100.png b/docs/html/images/brand/Android_Robot_100.png
new file mode 100644
index 0000000..946ee3a
--- /dev/null
+++ b/docs/html/images/brand/Android_Robot_100.png
Binary files differ
diff --git a/docs/html/images/brand/Android_Robot_200.png b/docs/html/images/brand/Android_Robot_200.png
new file mode 100644
index 0000000..40bf934
--- /dev/null
+++ b/docs/html/images/brand/Android_Robot_200.png
Binary files differ
diff --git a/docs/html/images/brand/Android_Robot_500.png b/docs/html/images/brand/Android_Robot_500.png
new file mode 100644
index 0000000..1fbfc51
--- /dev/null
+++ b/docs/html/images/brand/Android_Robot_500.png
Binary files differ
diff --git a/docs/html/images/brand/Android_Robot_outlined.ai b/docs/html/images/brand/Android_Robot_outlined.ai
new file mode 100644
index 0000000..9105cba
--- /dev/null
+++ b/docs/html/images/brand/Android_Robot_outlined.ai
Binary files differ
diff --git a/docs/html/images/brand/Google_Play_Store.ai b/docs/html/images/brand/Google_Play_Store.ai
new file mode 100644
index 0000000..51f07c6
--- /dev/null
+++ b/docs/html/images/brand/Google_Play_Store.ai
Binary files differ
diff --git a/docs/html/images/brand/Google_Play_Store_48.png b/docs/html/images/brand/Google_Play_Store_48.png
new file mode 100644
index 0000000..2f0cfe0
--- /dev/null
+++ b/docs/html/images/brand/Google_Play_Store_48.png
Binary files differ
diff --git a/docs/html/images/brand/Google_Play_Store_96.png b/docs/html/images/brand/Google_Play_Store_96.png
new file mode 100644
index 0000000..6e2c835
--- /dev/null
+++ b/docs/html/images/brand/Google_Play_Store_96.png
Binary files differ
diff --git a/docs/html/images/brand/android_logo_no.png b/docs/html/images/brand/android_logo_no.png
new file mode 100644
index 0000000..8de22d8
--- /dev/null
+++ b/docs/html/images/brand/android_logo_no.png
Binary files differ
diff --git a/docs/html/images/brand/droid.gif b/docs/html/images/brand/droid.gif
deleted file mode 100644
index 7c7b941..0000000
--- a/docs/html/images/brand/droid.gif
+++ /dev/null
Binary files differ
diff --git a/docs/html/images/brand/en_app_rgb_wo.ai b/docs/html/images/brand/en_app_rgb_wo.ai
new file mode 100644
index 0000000..db27314
--- /dev/null
+++ b/docs/html/images/brand/en_app_rgb_wo.ai
Binary files differ
diff --git a/docs/html/images/brand/en_generic_rgb_wo.ai b/docs/html/images/brand/en_generic_rgb_wo.ai
new file mode 100644
index 0000000..57c1e47
--- /dev/null
+++ b/docs/html/images/brand/en_generic_rgb_wo.ai
Binary files differ
diff --git a/docs/html/images/brand/google_play_logo_450.png b/docs/html/images/brand/google_play_logo_450.png
deleted file mode 100644
index 59a1fcf..0000000
--- a/docs/html/images/brand/google_play_logo_450.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/images/brand/learnmore.gif b/docs/html/images/brand/learnmore.gif
deleted file mode 100644
index 70a8e6b..0000000
--- a/docs/html/images/brand/learnmore.gif
+++ /dev/null
Binary files differ
diff --git a/docs/html/images/brand/logo_android.gif b/docs/html/images/brand/logo_android.gif
deleted file mode 100644
index 169c764..0000000
--- a/docs/html/images/brand/logo_android.gif
+++ /dev/null
Binary files differ
diff --git a/docs/html/images/brand/mediaplayer.gif b/docs/html/images/brand/mediaplayer.gif
deleted file mode 100644
index 860d110..0000000
--- a/docs/html/images/brand/mediaplayer.gif
+++ /dev/null
Binary files differ
diff --git a/docs/html/images/brand/mediaplayer.png b/docs/html/images/brand/mediaplayer.png
new file mode 100644
index 0000000..f857d5f
--- /dev/null
+++ b/docs/html/images/brand/mediaplayer.png
Binary files differ
diff --git a/docs/html/images/brand/norad.gif b/docs/html/images/brand/norad.gif
deleted file mode 100644
index d8707bd..0000000
--- a/docs/html/images/brand/norad.gif
+++ /dev/null
Binary files differ
diff --git a/docs/html/legal.jd b/docs/html/legal.jd
index 3206503..1698af0f 100644
--- a/docs/html/legal.jd
+++ b/docs/html/legal.jd
@@ -39,7 +39,7 @@
use of it must be attributed as such.</p>
<p>For more information about Android brands, see the <a
-href="{@docRoot}distribute/googleplay/promote/brand.html">Android Branding Guidelines</a>.</p>
+href="{@docRoot}distribute/googleplay/promote/brand.html">Brand Guidelines</a>.</p>
<p>All other trademarks are the property of their respective owners.</p>
diff --git a/libs/diskusage/dirsize.c b/libs/diskusage/dirsize.c
index 45e7b2a..6703783 100644
--- a/libs/diskusage/dirsize.c
+++ b/libs/diskusage/dirsize.c
@@ -49,6 +49,9 @@
while ((de = readdir(d))) {
const char *name = de->d_name;
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ size += stat_size(&s);
+ }
if (de->d_type == DT_DIR) {
int subfd;
@@ -64,10 +67,6 @@
if (subfd >= 0) {
size += calculate_dir_size(subfd);
}
- } else {
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- size += stat_size(&s);
- }
}
}
closedir(d);
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 6ca70a4..f84c847 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -1573,7 +1573,8 @@
}
status_t DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint) {
- const bool reject = quickReject(left, top, left + bitmap->width(), top + bitmap->height());
+ const bool reject = quickRejectNoScissor(left, top,
+ left + bitmap->width(), top + bitmap->height());
uint32_t* location = addOp(DisplayList::DrawBitmap, reject);
addBitmap(bitmap);
addPoint(left, top);
@@ -1587,7 +1588,7 @@
const mat4 transform(*matrix);
transform.mapRect(r);
- const bool reject = quickReject(r.left, r.top, r.right, r.bottom);
+ const bool reject = quickRejectNoScissor(r.left, r.top, r.right, r.bottom);
uint32_t* location = addOp(DisplayList::DrawBitmapMatrix, reject);
addBitmap(bitmap);
addMatrix(matrix);
@@ -1599,7 +1600,7 @@
status_t DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop,
float dstRight, float dstBottom, SkPaint* paint) {
- const bool reject = quickReject(dstLeft, dstTop, dstRight, dstBottom);
+ const bool reject = quickRejectNoScissor(dstLeft, dstTop, dstRight, dstBottom);
uint32_t* location = addOp(DisplayList::DrawBitmapRect, reject);
addBitmap(bitmap);
addBounds(srcLeft, srcTop, srcRight, srcBottom);
@@ -1611,7 +1612,8 @@
status_t DisplayListRenderer::drawBitmapData(SkBitmap* bitmap, float left, float top,
SkPaint* paint) {
- const bool reject = quickReject(left, top, left + bitmap->width(), top + bitmap->height());
+ const bool reject = quickRejectNoScissor(left, top,
+ left + bitmap->width(), top + bitmap->height());
uint32_t* location = addOp(DisplayList::DrawBitmapData, reject);
addBitmapData(bitmap);
addPoint(left, top);
@@ -1644,7 +1646,7 @@
SkXfermode::Mode mode;
OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
- const bool reject = quickReject(left, top, right, bottom);
+ const bool reject = quickRejectNoScissor(left, top, right, bottom);
uint32_t* location = addOp(DisplayList::DrawPatch, reject);
addBitmap(bitmap);
addInts(xDivs, width);
@@ -1667,7 +1669,7 @@
status_t DisplayListRenderer::drawRect(float left, float top, float right, float bottom,
SkPaint* paint) {
const bool reject = paint->getStyle() == SkPaint::kFill_Style &&
- quickReject(left, top, right, bottom);
+ quickRejectNoScissor(left, top, right, bottom);
uint32_t* location = addOp(DisplayList::DrawRect, reject);
addBounds(left, top, right, bottom);
addPaint(paint);
@@ -1678,7 +1680,7 @@
status_t DisplayListRenderer::drawRoundRect(float left, float top, float right, float bottom,
float rx, float ry, SkPaint* paint) {
const bool reject = paint->getStyle() == SkPaint::kFill_Style &&
- quickReject(left, top, right, bottom);
+ quickRejectNoScissor(left, top, right, bottom);
uint32_t* location = addOp(DisplayList::DrawRoundRect, reject);
addBounds(left, top, right, bottom);
addPoint(rx, ry);
@@ -1721,7 +1723,7 @@
left -= offset;
top -= offset;
- const bool reject = quickReject(left, top, left + width, top + height);
+ const bool reject = quickRejectNoScissor(left, top, left + width, top + height);
uint32_t* location = addOp(DisplayList::DrawPath, reject);
addPath(path);
addPaint(paint);
@@ -1791,7 +1793,7 @@
if (CC_LIKELY(paint->getTextAlign() == SkPaint::kLeft_Align)) {
SkPaint::FontMetrics metrics;
paint->getFontMetrics(&metrics, 0.0f);
- reject = quickReject(x, y + metrics.fTop, x + length, y + metrics.fBottom);
+ reject = quickRejectNoScissor(x, y + metrics.fTop, x + length, y + metrics.fBottom);
}
uint32_t* location = addOp(DisplayList::DrawText, reject);
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index 87add17..a924362 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -73,6 +73,11 @@
return mIsIdentity;
}
+bool Matrix4::isPerspective() const {
+ return data[kPerspective0] != 0.0f || data[kPerspective1] != 0.0f ||
+ data[kPerspective2] != 1.0f;
+}
+
void Matrix4::load(const float* v) {
memcpy(data, v, sizeof(data));
// TODO: Do something smarter here
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index 02b781e..f86823d 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -115,6 +115,7 @@
bool isPureTranslate() const;
bool isSimple() const;
bool isIdentity() const;
+ bool isPerspective() const;
bool changesBounds() const;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 684d5e1..c015077 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2647,20 +2647,21 @@
setupDrawShaderUniforms(pureTranslate);
setupDrawTextGammaUniforms();
- const Rect* clip = pureTranslate ? mSnapshot->clipRect : &mSnapshot->getLocalClip();
+ const Rect* clip = pureTranslate ? mSnapshot->clipRect :
+ (mSnapshot->hasPerspectiveTransform() ? NULL : &mSnapshot->getLocalClip());
Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
const bool hasActiveLayer = hasLayer();
bool status;
- if (paint->getTextAlign() != SkPaint::kLeft_Align) {
+ if (CC_UNLIKELY(paint->getTextAlign() != SkPaint::kLeft_Align)) {
SkPaint paintCopy(*paint);
paintCopy.setTextAlign(SkPaint::kLeft_Align);
status = fontRenderer.renderPosText(&paintCopy, clip, text, 0, bytesCount, count, x, y,
- positions, hasActiveLayer ? &bounds : NULL);
+ positions, hasActiveLayer ? &bounds : NULL);
} else {
status = fontRenderer.renderPosText(paint, clip, text, 0, bytesCount, count, x, y,
- positions, hasActiveLayer ? &bounds : NULL);
+ positions, hasActiveLayer ? &bounds : NULL);
}
if (status && hasActiveLayer) {
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index 4484676..fbc8455 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -178,6 +178,10 @@
flags |= Snapshot::kFlagClipSet;
}
+bool Snapshot::hasPerspectiveTransform() const {
+ return transform->isPerspective();
+}
+
const Rect& Snapshot::getLocalClip() {
mat4 inverse;
inverse.loadInverse(*transform);
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index a89b740..9c612ff 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -121,6 +121,11 @@
bool isIgnored() const;
/**
+ * Indicates whether the current transform has perspective components.
+ */
+ bool hasPerspectiveTransform() const;
+
+ /**
* Dirty flags.
*/
int flags;
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index 6e205b8..7bfa63d 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define LOG_TAG "OpenGLRenderer"
+
#include <cutils/compiler.h>
#include <SkUtils.h>
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index a256079..36c9c70 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -22,12 +22,17 @@
import android.content.IntentFilter;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.WifiDisplay;
+import android.hardware.display.WifiDisplayStatus;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.text.TextUtils;
import android.util.Log;
+import android.view.Display;
+import android.view.DisplayInfo;
import java.util.ArrayList;
import java.util.HashMap;
@@ -51,6 +56,7 @@
static class Static {
final Resources mResources;
final IAudioService mAudioService;
+ final DisplayManager mDisplayService;
final Handler mHandler;
final CopyOnWriteArrayList<CallbackInfo> mCallbacks =
new CopyOnWriteArrayList<CallbackInfo>();
@@ -60,18 +66,20 @@
final RouteCategory mSystemCategory;
- final AudioRoutesInfo mCurRoutesInfo = new AudioRoutesInfo();
+ final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo();
- RouteInfo mDefaultAudio;
+ RouteInfo mDefaultAudioVideo;
RouteInfo mBluetoothA2dpRoute;
RouteInfo mSelectedRoute;
- final IAudioRoutesObserver.Stub mRoutesObserver = new IAudioRoutesObserver.Stub() {
+ WifiDisplayStatus mLastKnownWifiDisplayStatus;
+
+ final IAudioRoutesObserver.Stub mAudioRoutesObserver = new IAudioRoutesObserver.Stub() {
public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) {
mHandler.post(new Runnable() {
@Override public void run() {
- updateRoutes(newRoutes);
+ updateAudioRoutes(newRoutes);
}
});
}
@@ -84,34 +92,42 @@
IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
mAudioService = IAudioService.Stub.asInterface(b);
+ mDisplayService = (DisplayManager) appContext.getSystemService(Context.DISPLAY_SERVICE);
+
mSystemCategory = new RouteCategory(
com.android.internal.R.string.default_audio_route_category_name,
- ROUTE_TYPE_LIVE_AUDIO, false);
+ ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO, false);
+ mSystemCategory.mIsSystem = true;
}
// Called after sStatic is initialized
void startMonitoringRoutes(Context appContext) {
- mDefaultAudio = new RouteInfo(mSystemCategory);
- mDefaultAudio.mNameResId = com.android.internal.R.string.default_audio_route_name;
- mDefaultAudio.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO;
- addRoute(mDefaultAudio);
+ mDefaultAudioVideo = new RouteInfo(mSystemCategory);
+ mDefaultAudioVideo.mNameResId = com.android.internal.R.string.default_audio_route_name;
+ mDefaultAudioVideo.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO;
+ addRoute(mDefaultAudioVideo);
appContext.registerReceiver(new VolumeChangeReceiver(),
new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION));
- AudioRoutesInfo newRoutes = null;
+ AudioRoutesInfo newAudioRoutes = null;
try {
- newRoutes = mAudioService.startWatchingRoutes(mRoutesObserver);
+ newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
} catch (RemoteException e) {
}
- if (newRoutes != null) {
- updateRoutes(newRoutes);
+ if (newAudioRoutes != null) {
+ updateAudioRoutes(newAudioRoutes);
}
+
+ updateWifiDisplayStatus(mDisplayService.getWifiDisplayStatus());
+
+ appContext.registerReceiver(new WifiDisplayStatusChangedReceiver(),
+ new IntentFilter(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED));
}
- void updateRoutes(AudioRoutesInfo newRoutes) {
- if (newRoutes.mMainType != mCurRoutesInfo.mMainType) {
- mCurRoutesInfo.mMainType = newRoutes.mMainType;
+ void updateAudioRoutes(AudioRoutesInfo newRoutes) {
+ if (newRoutes.mMainType != mCurAudioRoutesInfo.mMainType) {
+ mCurAudioRoutesInfo.mMainType = newRoutes.mMainType;
int name;
if ((newRoutes.mMainType&AudioRoutesInfo.MAIN_HEADPHONES) != 0
|| (newRoutes.mMainType&AudioRoutesInfo.MAIN_HEADSET) != 0) {
@@ -119,12 +135,12 @@
} else if ((newRoutes.mMainType&AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
name = com.android.internal.R.string.default_audio_route_name_dock_speakers;
} else if ((newRoutes.mMainType&AudioRoutesInfo.MAIN_HDMI) != 0) {
- name = com.android.internal.R.string.default_audio_route_name_hdmi;
+ name = com.android.internal.R.string.default_media_route_name_hdmi;
} else {
name = com.android.internal.R.string.default_audio_route_name;
}
- sStatic.mDefaultAudio.mNameResId = name;
- dispatchRouteChanged(sStatic.mDefaultAudio);
+ sStatic.mDefaultAudioVideo.mNameResId = name;
+ dispatchRouteChanged(sStatic.mDefaultAudioVideo);
}
boolean a2dpEnabled;
@@ -135,17 +151,17 @@
a2dpEnabled = false;
}
- if (!TextUtils.equals(newRoutes.mBluetoothName, mCurRoutesInfo.mBluetoothName)) {
- mCurRoutesInfo.mBluetoothName = newRoutes.mBluetoothName;
- if (mCurRoutesInfo.mBluetoothName != null) {
+ if (!TextUtils.equals(newRoutes.mBluetoothName, mCurAudioRoutesInfo.mBluetoothName)) {
+ mCurAudioRoutesInfo.mBluetoothName = newRoutes.mBluetoothName;
+ if (mCurAudioRoutesInfo.mBluetoothName != null) {
if (sStatic.mBluetoothA2dpRoute == null) {
final RouteInfo info = new RouteInfo(sStatic.mSystemCategory);
- info.mName = mCurRoutesInfo.mBluetoothName;
+ info.mName = mCurAudioRoutesInfo.mBluetoothName;
info.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO;
sStatic.mBluetoothA2dpRoute = info;
addRoute(sStatic.mBluetoothA2dpRoute);
} else {
- sStatic.mBluetoothA2dpRoute.mName = mCurRoutesInfo.mBluetoothName;
+ sStatic.mBluetoothA2dpRoute.mName = mCurAudioRoutesInfo.mBluetoothName;
dispatchRouteChanged(sStatic.mBluetoothA2dpRoute);
}
} else if (sStatic.mBluetoothA2dpRoute != null) {
@@ -155,11 +171,11 @@
}
if (mBluetoothA2dpRoute != null) {
- if (mCurRoutesInfo.mMainType != AudioRoutesInfo.MAIN_SPEAKER &&
+ if (mCurAudioRoutesInfo.mMainType != AudioRoutesInfo.MAIN_SPEAKER &&
mSelectedRoute == mBluetoothA2dpRoute) {
- selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudio);
- } else if (mCurRoutesInfo.mMainType == AudioRoutesInfo.MAIN_SPEAKER &&
- mSelectedRoute == mDefaultAudio && a2dpEnabled) {
+ selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudioVideo);
+ } else if (mCurAudioRoutesInfo.mMainType == AudioRoutesInfo.MAIN_SPEAKER &&
+ mSelectedRoute == mDefaultAudioVideo && a2dpEnabled) {
selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mBluetoothA2dpRoute);
}
}
@@ -181,6 +197,20 @@
public static final int ROUTE_TYPE_LIVE_AUDIO = 0x1;
/**
+ * Route type flag for live video.
+ *
+ * <p>A device that supports live video routing will allow a mirrored version
+ * of the device's primary display or a customized
+ * {@link android.app.Presentation Presentation} to be routed to supported destinations.</p>
+ *
+ * <p>Once initiated, display mirroring is transparent to the application.
+ * While remote routing is active the application may use a
+ * {@link android.app.Presentation Presentation} to replace the mirrored view
+ * on the external display with different content.</p>
+ */
+ public static final int ROUTE_TYPE_LIVE_VIDEO = 0x2;
+
+ /**
* Route type flag for application-specific usage.
*
* <p>Unlike other media route types, user routes are managed by the application.
@@ -219,7 +249,7 @@
* @hide for use by framework routing UI
*/
public RouteInfo getSystemAudioRoute() {
- return sStatic.mDefaultAudio;
+ return sStatic.mDefaultAudioVideo;
}
/**
@@ -296,7 +326,8 @@
}
static void selectRouteStatic(int types, RouteInfo route) {
- if (sStatic.mSelectedRoute == route) return;
+ final RouteInfo oldRoute = sStatic.mSelectedRoute;
+ if (oldRoute == route) return;
if ((route.getSupportedTypes() & types) == 0) {
Log.w(TAG, "selectRoute ignored; cannot select route with supported types " +
typesToString(route.getSupportedTypes()) + " into route types " +
@@ -306,7 +337,7 @@
final RouteInfo btRoute = sStatic.mBluetoothA2dpRoute;
if (btRoute != null && (types & ROUTE_TYPE_LIVE_AUDIO) != 0 &&
- (route == btRoute || route == sStatic.mDefaultAudio)) {
+ (route == btRoute || route == sStatic.mDefaultAudioVideo)) {
try {
sStatic.mAudioService.setBluetoothA2dpOn(route == btRoute);
} catch (RemoteException e) {
@@ -314,10 +345,21 @@
}
}
- if (sStatic.mSelectedRoute != null) {
+ final WifiDisplay activeDisplay =
+ sStatic.mDisplayService.getWifiDisplayStatus().getActiveDisplay();
+ final boolean oldRouteHasAddress = oldRoute != null && oldRoute.mDeviceAddress != null;
+ final boolean newRouteHasAddress = route != null && route.mDeviceAddress != null;
+ if (activeDisplay != null || oldRouteHasAddress || newRouteHasAddress) {
+ if (newRouteHasAddress && !matchesDeviceAddress(activeDisplay, route)) {
+ sStatic.mDisplayService.connectWifiDisplay(route.mDeviceAddress);
+ } else if (activeDisplay != null && !newRouteHasAddress) {
+ sStatic.mDisplayService.disconnectWifiDisplay();
+ }
+ }
+
+ if (oldRoute != null) {
// TODO filter types properly
- dispatchRouteUnselected(types & sStatic.mSelectedRoute.getSupportedTypes(),
- sStatic.mSelectedRoute);
+ dispatchRouteUnselected(types & oldRoute.getSupportedTypes(), oldRoute);
}
sStatic.mSelectedRoute = route;
if (route != null) {
@@ -327,6 +369,22 @@
}
/**
+ * Compare the device address of a display and a route.
+ * Nulls/no device address will match another null/no address.
+ */
+ static boolean matchesDeviceAddress(WifiDisplay display, RouteInfo info) {
+ final boolean routeHasAddress = info != null && info.mDeviceAddress != null;
+ if (display == null && !routeHasAddress) {
+ return true;
+ }
+
+ if (display != null && routeHasAddress) {
+ return display.getDeviceAddress().equals(info.mDeviceAddress);
+ }
+ return false;
+ }
+
+ /**
* Add an app-specified route for media to the MediaRouter.
* App-specified route definitions are created using {@link #createUserRoute(RouteCategory)}
*
@@ -419,7 +477,7 @@
if (info == sStatic.mSelectedRoute) {
// Removing the currently selected route? Select the default before we remove it.
// TODO: Be smarter about the route types here; this selects for all valid.
- selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_USER, sStatic.mDefaultAudio);
+ selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_USER, sStatic.mDefaultAudioVideo);
}
if (!found) {
sStatic.mCategories.remove(removingCat);
@@ -444,7 +502,8 @@
if (info == sStatic.mSelectedRoute) {
// Removing the currently selected route? Select the default before we remove it.
// TODO: Be smarter about the route types here; this selects for all valid.
- selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_USER, sStatic.mDefaultAudio);
+ selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO | ROUTE_TYPE_USER,
+ sStatic.mDefaultAudioVideo);
}
if (!found) {
sStatic.mCategories.remove(removingCat);
@@ -611,20 +670,151 @@
if (selectedRoute == null) return;
if (selectedRoute == sStatic.mBluetoothA2dpRoute ||
- selectedRoute == sStatic.mDefaultAudio) {
+ selectedRoute == sStatic.mDefaultAudioVideo) {
dispatchRouteVolumeChanged(selectedRoute);
} else if (sStatic.mBluetoothA2dpRoute != null) {
try {
dispatchRouteVolumeChanged(sStatic.mAudioService.isBluetoothA2dpOn() ?
- sStatic.mBluetoothA2dpRoute : sStatic.mDefaultAudio);
+ sStatic.mBluetoothA2dpRoute : sStatic.mDefaultAudioVideo);
} catch (RemoteException e) {
Log.e(TAG, "Error checking Bluetooth A2DP state to report volume change", e);
}
} else {
- dispatchRouteVolumeChanged(sStatic.mDefaultAudio);
+ dispatchRouteVolumeChanged(sStatic.mDefaultAudioVideo);
}
}
+ static void updateWifiDisplayStatus(WifiDisplayStatus newStatus) {
+ final WifiDisplayStatus oldStatus = sStatic.mLastKnownWifiDisplayStatus;
+
+ // TODO Naive implementation. Make this smarter later.
+ boolean needScan = false;
+ WifiDisplay[] oldDisplays = oldStatus != null ?
+ oldStatus.getRememberedDisplays() : new WifiDisplay[0];
+ WifiDisplay[] newDisplays = newStatus.getRememberedDisplays();
+ WifiDisplay[] availableDisplays = newStatus.getAvailableDisplays();
+
+ for (int i = 0; i < newDisplays.length; i++) {
+ final WifiDisplay d = newDisplays[i];
+ final WifiDisplay oldRemembered = findMatchingDisplay(d, oldDisplays);
+ if (oldRemembered == null) {
+ addRoute(makeWifiDisplayRoute(d));
+ needScan = true;
+ } else {
+ final boolean available = findMatchingDisplay(d, availableDisplays) != null;
+ final RouteInfo route = findWifiDisplayRoute(d);
+ updateWifiDisplayRoute(route, d, available, newStatus);
+ }
+ }
+ for (int i = 0; i < oldDisplays.length; i++) {
+ final WifiDisplay d = oldDisplays[i];
+ final WifiDisplay newDisplay = findMatchingDisplay(d, newDisplays);
+ if (newDisplay == null) {
+ removeRoute(findWifiDisplayRoute(d));
+ }
+ }
+
+ if (needScan) {
+ sStatic.mDisplayService.scanWifiDisplays();
+ }
+
+ sStatic.mLastKnownWifiDisplayStatus = newStatus;
+ }
+
+ static RouteInfo makeWifiDisplayRoute(WifiDisplay display) {
+ final RouteInfo newRoute = new RouteInfo(sStatic.mSystemCategory);
+ newRoute.mDeviceAddress = display.getDeviceAddress();
+ newRoute.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO;
+ newRoute.mVolumeHandling = RouteInfo.PLAYBACK_VOLUME_FIXED;
+ newRoute.mPlaybackType = RouteInfo.PLAYBACK_TYPE_REMOTE;
+ newRoute.mStatus = sStatic.mResources.getText(
+ com.android.internal.R.string.media_route_status_connecting);
+ newRoute.mEnabled = false;
+
+ newRoute.mName = makeWifiDisplayName(display);
+ return newRoute;
+ }
+
+ static String makeWifiDisplayName(WifiDisplay display) {
+ String name = display.getDeviceAlias();
+ if (TextUtils.isEmpty(name)) {
+ name = display.getDeviceName();
+ }
+ return name;
+ }
+
+ private static void updateWifiDisplayRoute(RouteInfo route, WifiDisplay display,
+ boolean available, WifiDisplayStatus wifiDisplayStatus) {
+ final boolean isScanning =
+ wifiDisplayStatus.getScanState() == WifiDisplayStatus.SCAN_STATE_SCANNING;
+
+ boolean changed = false;
+ int newStatus = RouteInfo.STATUS_NONE;
+
+ if (available) {
+ newStatus = isScanning ? RouteInfo.STATUS_SCANNING : RouteInfo.STATUS_AVAILABLE;
+ } else {
+ newStatus = RouteInfo.STATUS_NOT_AVAILABLE;
+ }
+
+ if (display.equals(wifiDisplayStatus.getActiveDisplay())) {
+ final int activeState = wifiDisplayStatus.getActiveDisplayState();
+ switch (activeState) {
+ case WifiDisplayStatus.DISPLAY_STATE_CONNECTED:
+ newStatus = RouteInfo.STATUS_NONE;
+ break;
+ case WifiDisplayStatus.DISPLAY_STATE_CONNECTING:
+ newStatus = RouteInfo.STATUS_CONNECTING;
+ break;
+ case WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED:
+ Log.e(TAG, "Active display is not connected!");
+ break;
+ }
+ }
+
+ final String newName = makeWifiDisplayName(display);
+ if (route.getName().equals(newName)) {
+ route.mName = newName;
+ changed = true;
+ }
+
+ changed |= route.mEnabled != available;
+ route.mEnabled = available;
+
+ changed |= route.setStatusCode(newStatus);
+
+ if (changed) {
+ dispatchRouteChanged(route);
+ }
+
+ if (!available && route == sStatic.mSelectedRoute) {
+ // Oops, no longer available. Reselect the default.
+ final RouteInfo defaultRoute = sStatic.mDefaultAudioVideo;
+ selectRouteStatic(defaultRoute.getSupportedTypes(), defaultRoute);
+ }
+ }
+
+ private static WifiDisplay findMatchingDisplay(WifiDisplay address, WifiDisplay[] displays) {
+ for (int i = 0; i < displays.length; i++) {
+ final WifiDisplay d = displays[i];
+ if (d.equals(address)) {
+ return d;
+ }
+ }
+ return null;
+ }
+
+ private static RouteInfo findWifiDisplayRoute(WifiDisplay d) {
+ final int count = sStatic.mRoutes.size();
+ for (int i = 0; i < count; i++) {
+ final RouteInfo info = sStatic.mRoutes.get(i);
+ if (d.getDeviceAddress().equals(info.mDeviceAddress)) {
+ return info;
+ }
+ }
+ return null;
+ }
+
/**
* Information about a media route.
*/
@@ -644,6 +834,18 @@
int mPlaybackStream = AudioManager.STREAM_MUSIC;
VolumeCallbackInfo mVcb;
+ String mDeviceAddress;
+ boolean mEnabled = true;
+
+ // A predetermined connection status that can override mStatus
+ private int mStatusCode;
+
+ static final int STATUS_NONE = 0;
+ static final int STATUS_SCANNING = 1;
+ static final int STATUS_CONNECTING = 2;
+ static final int STATUS_AVAILABLE = 3;
+ static final int STATUS_NOT_AVAILABLE = 4;
+
private Object mTag;
/**
@@ -711,6 +913,34 @@
}
/**
+ * Set this route's status by predetermined status code. If the caller
+ * should dispatch a route changed event this call will return true;
+ */
+ boolean setStatusCode(int statusCode) {
+ if (statusCode != mStatusCode) {
+ mStatusCode = statusCode;
+ int resId = 0;
+ switch (statusCode) {
+ case STATUS_SCANNING:
+ resId = com.android.internal.R.string.media_route_status_scanning;
+ break;
+ case STATUS_CONNECTING:
+ resId = com.android.internal.R.string.media_route_status_connecting;
+ break;
+ case STATUS_AVAILABLE:
+ resId = com.android.internal.R.string.media_route_status_available;
+ break;
+ case STATUS_NOT_AVAILABLE:
+ resId = com.android.internal.R.string.media_route_status_not_available;
+ break;
+ }
+ mStatus = resId != 0 ? sStatic.mResources.getText(resId) : null;
+ return true;
+ }
+ return false;
+ }
+
+ /**
* @return A media type flag set describing which types this route supports.
*/
public int getSupportedTypes() {
@@ -866,6 +1096,13 @@
return mVolumeHandling;
}
+ /**
+ * @return true if this route is enabled and may be selected
+ */
+ public boolean isEnabled() {
+ return mEnabled;
+ }
+
void setStatusInt(CharSequence status) {
if (!status.equals(mStatus)) {
mStatus = status;
@@ -881,7 +1118,6 @@
sStatic.mHandler.post(new Runnable() {
@Override
public void run() {
- //Log.d(TAG, "dispatchRemoteVolumeUpdate dir=" + direction + " val=" + value);
if (mVcb != null) {
if (direction != 0) {
mVcb.vcb.onVolumeUpdateRequest(mVcb.route, direction);
@@ -1400,6 +1636,7 @@
int mNameResId;
int mTypes;
final boolean mGroupable;
+ boolean mIsSystem;
RouteCategory(CharSequence name, int types, boolean groupable) {
mName = name;
@@ -1486,6 +1723,14 @@
return mGroupable;
}
+ /**
+ * @return true if this is the category reserved for system routes.
+ * @hide
+ */
+ public boolean isSystem() {
+ return mIsSystem;
+ }
+
public String toString() {
return "RouteCategory{ name=" + mName + " types=" + typesToString(mTypes) +
" groupable=" + mGroupable + " }";
@@ -1671,7 +1916,6 @@
}
static class VolumeChangeReceiver extends BroadcastReceiver {
-
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(AudioManager.VOLUME_CHANGED_ACTION)) {
@@ -1689,6 +1933,15 @@
}
}
}
+ }
+ static class WifiDisplayStatusChangedReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED)) {
+ updateWifiDisplayStatus((WifiDisplayStatus) intent.getParcelableExtra(
+ DisplayManager.EXTRA_WIFI_DISPLAY_STATUS));
+ }
+ }
}
}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index a7294ec..3b40fba 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -1,4 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="com.android.systemui"
coreApp="true">
@@ -91,7 +92,7 @@
android:permission="android.permission.BIND_WALLPAPER"
android:exported="true" />
- <receiver android:name=".BootReceiver" >
+ <receiver android:name=".BootReceiver" androidprv:primaryUserOnly="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
@@ -197,9 +198,8 @@
android:enabled="false"
>
<intent-filter>
- <action android:name="android.intent.action.MAIN" />
+ <action android:name="android.service.dreams.DreamService" />
<category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.DREAM" />
</intent-filter>
</service>
@@ -214,6 +214,11 @@
<action android:name="android.intent.action.CREATE_SHORTCUT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.DESK_DOCK" />
+ </intent-filter>
</activity>
</application>
</manifest>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index a6875718..df6ed19 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -44,4 +44,7 @@
<!-- On tablet-sized devices, we allocate the rightmost third(ish) of the draggable status bar
to quick settings. -->
<item type="dimen" name="settings_panel_dragzone_fraction">35%</item>
+
+ <!-- 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>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 5b15844..62289fb 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -189,4 +189,7 @@
<!-- The padding between each tile within the QuickSettings layout -->
<dimen name="quick_settings_cell_gap">4dp</dimen>
+ <!-- Minimum fraction of the screen that should be taken up by the notification panel.
+ Not used at this screen size. -->
+ <item type="dimen" name="notification_panel_min_height_frac">0%</item>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/BeanBagDream.java b/packages/SystemUI/src/com/android/systemui/BeanBagDream.java
index 6b5c9c0..3bb808f 100644
--- a/packages/SystemUI/src/com/android/systemui/BeanBagDream.java
+++ b/packages/SystemUI/src/com/android/systemui/BeanBagDream.java
@@ -1,10 +1,10 @@
package com.android.systemui;
-import android.service.dreams.Dream;
+import android.service.dreams.DreamService;
import com.android.systemui.BeanBag.Board;
-public class BeanBagDream extends Dream {
+public class BeanBagDream extends DreamService {
private Board mBoard;
diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
index b0879fc..f71f554 100644
--- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
@@ -72,7 +72,7 @@
private void startAssistActivity() {
// Close Recent Apps if needed
- mBar.animateCollapseNotifications(CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL);
+ mBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL);
// Launch Assist
Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
.getAssistIntent(mContext, UserHandle.USER_CURRENT);
@@ -220,7 +220,7 @@
public void hide(boolean animate) {
if (mBar != null) {
// This will indirectly cause show(false, ...) to get called
- mBar.animateCollapseNotifications(CommandQueue.FLAG_EXCLUDE_NONE);
+ mBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
} else {
setVisibility(View.INVISIBLE);
}
diff --git a/packages/SystemUI/src/com/android/systemui/Somnambulator.java b/packages/SystemUI/src/com/android/systemui/Somnambulator.java
index bd87238..011bf9c 100644
--- a/packages/SystemUI/src/com/android/systemui/Somnambulator.java
+++ b/packages/SystemUI/src/com/android/systemui/Somnambulator.java
@@ -20,15 +20,33 @@
import android.content.Intent;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.service.dreams.Dream;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
import android.util.Slog;
public class Somnambulator extends Activity {
+ public static final String TAG = "Somnambulator";
+
+ public static final int DEFAULT_SCREENSAVER_ENABLED = 1;
+ public static final int DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK = 1;
public Somnambulator() {
}
-
+
+ private boolean isScreenSaverEnabled() {
+ return Settings.Secure.getIntForUser(getContentResolver(),
+ Settings.Secure.SCREENSAVER_ENABLED, DEFAULT_SCREENSAVER_ENABLED,
+ UserHandle.USER_CURRENT) != 0;
+ }
+
+ private boolean isScreenSaverActivatedOnDock() {
+ return Settings.Secure.getIntForUser(getContentResolver(),
+ Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
+ DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK, UserHandle.USER_CURRENT) != 0;
+ }
+
@Override
public void onStart() {
super.onStart();
@@ -45,14 +63,20 @@
resultIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, getString(R.string.start_dreams));
setResult(RESULT_OK, resultIntent);
} else {
- IDreamManager somnambulist = IDreamManager.Stub.asInterface(
- ServiceManager.checkService(Dream.DREAM_SERVICE));
- if (somnambulist != null) {
- try {
- Slog.v("Somnambulator", "Dreaming by user request.");
- somnambulist.dream();
- } catch (RemoteException e) {
- // fine, stay asleep then
+ boolean docked = launchIntent.hasCategory(Intent.CATEGORY_DESK_DOCK);
+
+ if (docked && !(isScreenSaverEnabled() && isScreenSaverActivatedOnDock())) {
+ Slog.i(TAG, "Dreams currently disabled for docks.");
+ } else {
+ IDreamManager somnambulist = IDreamManager.Stub.asInterface(
+ ServiceManager.checkService(DreamService.DREAM_SERVICE));
+ if (somnambulist != null) {
+ try {
+ Slog.v(TAG, "Dreaming on " + (docked ? "dock insertion" : "user request"));
+ somnambulist.dream();
+ } catch (RemoteException e) {
+ // fine, stay asleep then
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index de016c0..d7b1b35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -185,7 +185,7 @@
if (isActivity && handled) {
// close the shade if it was open
- animateCollapseNotifications(CommandQueue.FLAG_EXCLUDE_NONE);
+ animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
visibilityChanged(false);
}
return handled;
@@ -357,7 +357,7 @@
public boolean onMenuItemClick(MenuItem item) {
if (item.getItemId() == R.id.notification_inspect_item) {
startApplicationDetailsActivity(packageNameF);
- animateCollapseNotifications(CommandQueue.FLAG_EXCLUDE_NONE);
+ animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
} else {
return false;
}
@@ -789,7 +789,7 @@
}
// close the shade if it was open
- animateCollapseNotifications(CommandQueue.FLAG_EXCLUDE_NONE);
+ animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
visibilityChanged(false);
// If this click was on the intruder alert, hide that instead
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 39e49b8..752bb0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -46,17 +46,16 @@
private static final int MSG_REMOVE_NOTIFICATION = 4 << MSG_SHIFT;
private static final int MSG_DISABLE = 5 << MSG_SHIFT;
private static final int MSG_EXPAND_NOTIFICATIONS = 6 << MSG_SHIFT;
- private static final int MSG_COLLAPSE_NOTIFICATIONS = 7 << MSG_SHIFT;
- private static final int MSG_EXPAND_QUICK_SETTINGS = 8 << MSG_SHIFT;
- private static final int MSG_COLLAPSE_QUICK_SETTINGS = 9 << MSG_SHIFT;
- private static final int MSG_SET_SYSTEMUI_VISIBILITY = 10 << MSG_SHIFT;
- private static final int MSG_TOP_APP_WINDOW_CHANGED = 11 << MSG_SHIFT;
- private static final int MSG_SHOW_IME_BUTTON = 12 << MSG_SHIFT;
- private static final int MSG_SET_HARD_KEYBOARD_STATUS = 13 << MSG_SHIFT;
- private static final int MSG_TOGGLE_RECENT_APPS = 14 << MSG_SHIFT;
- private static final int MSG_PRELOAD_RECENT_APPS = 15 << MSG_SHIFT;
- private static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 16 << MSG_SHIFT;
- private static final int MSG_SET_NAVIGATION_ICON_HINTS = 17 << MSG_SHIFT;
+ private static final int MSG_COLLAPSE_PANELS = 7 << MSG_SHIFT;
+ private static final int MSG_EXPAND_SETTINGS = 8 << MSG_SHIFT;
+ private static final int MSG_SET_SYSTEMUI_VISIBILITY = 9 << MSG_SHIFT;
+ private static final int MSG_TOP_APP_WINDOW_CHANGED = 10 << MSG_SHIFT;
+ private static final int MSG_SHOW_IME_BUTTON = 11 << MSG_SHIFT;
+ private static final int MSG_SET_HARD_KEYBOARD_STATUS = 12 << MSG_SHIFT;
+ private static final int MSG_TOGGLE_RECENT_APPS = 13 << MSG_SHIFT;
+ private static final int MSG_PRELOAD_RECENT_APPS = 14 << MSG_SHIFT;
+ private static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 15 << MSG_SHIFT;
+ private static final int MSG_SET_NAVIGATION_ICON_HINTS = 16 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -86,10 +85,9 @@
public void updateNotification(IBinder key, StatusBarNotification notification);
public void removeNotification(IBinder key);
public void disable(int state);
- public void animateExpandNotifications();
- public void animateCollapseNotifications(int flags);
- public void animateExpandQuickSettings();
- public void animateCollapseQuickSettings();
+ public void animateExpandNotificationsPanel();
+ public void animateCollapsePanels(int flags);
+ public void animateExpandSettingsPanel();
public void setSystemUiVisibility(int vis, int mask);
public void topAppWindowChanged(boolean visible);
public void setImeWindowStatus(IBinder token, int vis, int backDisposition);
@@ -154,31 +152,24 @@
}
}
- public void animateExpandNotifications() {
+ public void animateExpandNotificationsPanel() {
synchronized (mList) {
mHandler.removeMessages(MSG_EXPAND_NOTIFICATIONS);
mHandler.sendEmptyMessage(MSG_EXPAND_NOTIFICATIONS);
}
}
- public void animateCollapseNotifications() {
+ public void animateCollapsePanels() {
synchronized (mList) {
- mHandler.removeMessages(MSG_COLLAPSE_NOTIFICATIONS);
- mHandler.sendEmptyMessage(MSG_COLLAPSE_NOTIFICATIONS);
+ mHandler.removeMessages(MSG_COLLAPSE_PANELS);
+ mHandler.sendEmptyMessage(MSG_COLLAPSE_PANELS);
}
}
- public void animateExpandQuickSettings() {
+ public void animateExpandSettingsPanel() {
synchronized (mList) {
- mHandler.removeMessages(MSG_EXPAND_QUICK_SETTINGS);
- mHandler.sendEmptyMessage(MSG_EXPAND_QUICK_SETTINGS);
- }
- }
-
- public void animateCollapseQuickSettings() {
- synchronized (mList) {
- mHandler.removeMessages(MSG_COLLAPSE_QUICK_SETTINGS);
- mHandler.sendEmptyMessage(MSG_COLLAPSE_QUICK_SETTINGS);
+ mHandler.removeMessages(MSG_EXPAND_SETTINGS);
+ mHandler.sendEmptyMessage(MSG_EXPAND_SETTINGS);
}
}
@@ -289,16 +280,13 @@
mCallbacks.disable(msg.arg1);
break;
case MSG_EXPAND_NOTIFICATIONS:
- mCallbacks.animateExpandNotifications();
+ mCallbacks.animateExpandNotificationsPanel();
break;
- case MSG_COLLAPSE_NOTIFICATIONS:
- mCallbacks.animateCollapseNotifications(0);
+ case MSG_COLLAPSE_PANELS:
+ mCallbacks.animateCollapsePanels(0);
break;
- case MSG_EXPAND_QUICK_SETTINGS:
- mCallbacks.animateExpandQuickSettings();
- break;
- case MSG_COLLAPSE_QUICK_SETTINGS:
- mCallbacks.animateCollapseQuickSettings();
+ case MSG_EXPAND_SETTINGS:
+ mCallbacks.animateExpandSettingsPanel();
break;
case MSG_SET_SYSTEMUI_VISIBILITY:
mCallbacks.setSystemUiVisibility(msg.arg1, msg.arg2);
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 d72632f..3fea0a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -33,6 +33,7 @@
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
+import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -45,7 +46,7 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
-import android.service.dreams.Dream;
+import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -104,7 +105,8 @@
= "com.android.internal.policy.statusbar.START";
private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
- private static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
+ private static final int MSG_CLOSE_PANELS = 1001;
+ private static final int MSG_OPEN_SETTINGS_PANEL = 1002;
// 1020-1030 reserved for BaseStatusBar
// will likely move to a resource or other tunable param at some point
@@ -142,6 +144,7 @@
int mIconSize = -1;
int mIconHPadding = -1;
Display mDisplay;
+ Point mCurrentDisplaySize = new Point();
IDreamManager mDreamManager;
@@ -168,10 +171,9 @@
PanelView mNotificationPanel; // the sliding/resizing panel within the notification window
ScrollView mScrollView;
View mExpandedContents;
- final Rect mNotificationPanelBackgroundPadding = new Rect();
int mNotificationPanelGravity;
int mNotificationPanelMarginBottomPx, mNotificationPanelMarginPx;
- int mNotificationPanelMinHeight;
+ float mNotificationPanelMinHeightFrac;
boolean mNotificationPanelIsFullScreenWidth;
TextView mNotificationPanelDebugText;
@@ -263,7 +265,7 @@
.getDefaultDisplay();
mDreamManager = IDreamManager.Stub.asInterface(
- ServiceManager.checkService(Dream.DREAM_SERVICE));
+ ServiceManager.checkService(DreamService.DREAM_SERVICE));
super.start(); // calls createAndAddWindows()
@@ -296,7 +298,7 @@
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (mExpandedVisible && !mAnimating) {
- animateCollapseNotifications();
+ animateCollapsePanels();
}
}
return mStatusBarWindow.onTouchEvent(event);
@@ -778,7 +780,7 @@
}
if (CLOSE_PANEL_WHEN_EMPTIED && mNotificationData.size() == 0 && !mAnimating) {
- animateCollapseNotifications();
+ animateCollapsePanels();
}
}
@@ -1051,7 +1053,7 @@
}
if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
- animateCollapseNotifications();
+ animateCollapsePanels();
}
}
@@ -1071,7 +1073,7 @@
if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
if (mTicking) {
- mTicker.halt();
+ haltTicker();
}
mNotificationIcons.animate()
@@ -1093,7 +1095,7 @@
}
} else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
if (mTicking && (state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
- mTicker.halt();
+ haltTicker();
}
}
}
@@ -1111,10 +1113,13 @@
super.handleMessage(m);
switch (m.what) {
case MSG_OPEN_NOTIFICATION_PANEL:
- animateExpandNotifications();
+ animateExpandNotificationsPanel();
break;
- case MSG_CLOSE_NOTIFICATION_PANEL:
- animateCollapseNotifications();
+ case MSG_OPEN_SETTINGS_PANEL:
+ animateExpandSettingsPanel();
+ break;
+ case MSG_CLOSE_PANELS:
+ animateCollapsePanels();
break;
case MSG_SHOW_INTRUDER:
setIntruderAlertVisibility(true);
@@ -1167,11 +1172,11 @@
visibilityChanged(true);
}
- public void animateCollapseNotifications() {
- animateCollapseNotifications(CommandQueue.FLAG_EXCLUDE_NONE);
+ public void animateCollapsePanels() {
+ animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
}
- public void animateCollapseNotifications(int flags) {
+ public void animateCollapsePanels(int flags) {
if (SPEW) {
Slog.d(TAG, "animateCollapse():"
+ " mExpandedVisible=" + mExpandedVisible
@@ -1196,7 +1201,7 @@
}
@Override
- public void animateExpandNotifications() {
+ public void animateExpandNotificationsPanel() {
if (SPEW) Slog.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
return ;
@@ -1208,7 +1213,7 @@
}
@Override
- public void animateExpandQuickSettings() {
+ public void animateExpandSettingsPanel() {
if (SPEW) Slog.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
return;
@@ -1352,9 +1357,9 @@
if (0 != (diff & View.SYSTEM_UI_FLAG_LOW_PROFILE)) {
final boolean lightsOut = (0 != (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE));
if (lightsOut) {
- animateCollapseNotifications();
+ animateCollapsePanels();
if (mTicking) {
- mTicker.halt();
+ haltTicker();
}
}
@@ -1484,8 +1489,7 @@
mStatusBarContents.setVisibility(View.VISIBLE);
mTickerView.setVisibility(View.GONE);
mStatusBarContents.startAnimation(loadAnim(com.android.internal.R.anim.fade_in, null));
- mTickerView.startAnimation(loadAnim(com.android.internal.R.anim.fade_out,
- mTickingDoneListener));
+ // we do not animate the ticker away at this point, just get rid of it (b/6992707)
}
}
@@ -1640,12 +1644,17 @@
@Override
public void updateExpandedViewPos(int thingy) {
- // TODO
if (DEBUG) Slog.v(TAG, "updateExpandedViewPos");
+
+ // on larger devices, the notification panel is propped open a bit
+ mNotificationPanel.setMinimumHeight(
+ (int)(mNotificationPanelMinHeightFrac * mCurrentDisplaySize.y));
+
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mNotificationPanel.getLayoutParams();
lp.gravity = mNotificationPanelGravity;
lp.leftMargin = mNotificationPanelMarginPx;
mNotificationPanel.setLayoutParams(lp);
+
lp = (FrameLayout.LayoutParams) mSettingsPanel.getLayoutParams();
lp.gravity = mSettingsPanelGravity;
lp.rightMargin = mNotificationPanelMarginPx;
@@ -1678,7 +1687,7 @@
}
}
if (snapshot.isEmpty()) {
- animateCollapseNotifications(CommandQueue.FLAG_EXCLUDE_NONE);
+ animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
return;
}
new Thread(new Runnable() {
@@ -1729,7 +1738,7 @@
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
- animateCollapseNotifications(CommandQueue.FLAG_EXCLUDE_NONE);
+ animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
}
}, totalDelay + 225);
}
@@ -1751,7 +1760,7 @@
v.getContext().startActivityAsUser(new Intent(Settings.ACTION_SETTINGS)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
new UserHandle(UserHandle.USER_CURRENT));
- animateCollapseNotifications();
+ animateCollapsePanels();
}
};
@@ -1767,7 +1776,7 @@
flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL;
}
}
- animateCollapseNotifications(flags);
+ animateCollapsePanels(flags);
}
else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
// no waiting!
@@ -1777,6 +1786,8 @@
if (DEBUG) {
Slog.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
}
+ mDisplay.getSize(mCurrentDisplaySize);
+
updateResources();
repositionNavigationBar();
updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
@@ -1792,7 +1803,7 @@
@Override
public void userSwitched(int newUserId) {
if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId);
- animateCollapseNotifications();
+ animateCollapsePanels();
updateNotificationIcons();
}
@@ -1885,27 +1896,16 @@
if (mSettingsPanelGravity <= 0) {
mSettingsPanelGravity = Gravity.RIGHT | Gravity.TOP;
}
- getNinePatchPadding(res.getDrawable(R.drawable.notification_panel_bg), mNotificationPanelBackgroundPadding);
- final int notificationPanelDecorationHeight =
- res.getDimensionPixelSize(R.dimen.notification_panel_padding_top)
- + res.getDimensionPixelSize(R.dimen.notification_panel_header_height)
- + mNotificationPanelBackgroundPadding.top
- + mNotificationPanelBackgroundPadding.bottom;
- mNotificationPanelMinHeight =
- notificationPanelDecorationHeight
- + res.getDimensionPixelSize(R.dimen.close_handle_underlap);
mCarrierLabelHeight = res.getDimensionPixelSize(R.dimen.carrier_label_height);
mNotificationHeaderHeight = res.getDimensionPixelSize(R.dimen.notification_panel_header_height);
- if (false) Slog.v(TAG, "updateResources");
- }
-
- private static void getNinePatchPadding(Drawable d, Rect outPadding) {
- if (d instanceof NinePatchDrawable) {
- NinePatchDrawable ninePatch = (NinePatchDrawable) d;
- ninePatch.getPadding(outPadding);
+ mNotificationPanelMinHeightFrac = res.getFraction(R.dimen.notification_panel_min_height_frac, 1, 1);
+ if (mNotificationPanelMinHeightFrac < 0f || mNotificationPanelMinHeightFrac > 1f) {
+ mNotificationPanelMinHeightFrac = 0f;
}
+
+ if (false) Slog.v(TAG, "updateResources");
}
//
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 585793e..f3c2df1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -235,7 +235,7 @@
}
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
- getService().animateCollapseNotifications();
+ getService().animateCollapsePanels();
}
private void addUserTiles(ViewGroup parent, LayoutInflater inflater) {
@@ -246,9 +246,10 @@
@Override
public void onClick(View v) {
mBar.collapseAllPanels(true);
- ContactsContract.QuickContact.showQuickContact(mContext, v,
- ContactsContract.Profile.CONTENT_URI,
+ Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(mContext,
+ v, ContactsContract.Profile.CONTENT_URI,
ContactsContract.QuickContact.MODE_LARGE, null);
+ mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
}
});
mModel.addUserTile(userTile, new QuickSettingsModel.RefreshCallback() {
@@ -707,7 +708,18 @@
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
- SystemProperties.set("ctl.start", "bugreport");
+ // Add a little delay before executing, to give the
+ // dialog a chance to go away before it takes a
+ // screenshot.
+ mHandler.postDelayed(new Runnable() {
+ @Override public void run() {
+ try {
+ ActivityManagerNative.getDefault()
+ .requestBugReport();
+ } catch (RemoteException e) {
+ }
+ }
+ }, 500);
}
}
});
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 85b91d1..0176f42 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -70,7 +70,7 @@
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_BACK:
if (!down) {
- mService.animateCollapseNotifications();
+ mService.animateCollapsePanels();
}
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
index 73d1c7c..b431287 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
@@ -204,14 +204,14 @@
// We exclusively handle the back key by hiding this panel.
case KeyEvent.KEYCODE_BACK: {
if (event.getAction() == KeyEvent.ACTION_UP) {
- mBar.animateCollapseNotifications();
+ mBar.animateCollapsePanels();
}
return true;
}
// We react to the home key but let the system handle it.
case KeyEvent.KEYCODE_HOME: {
if (event.getAction() == KeyEvent.ACTION_UP) {
- mBar.animateCollapseNotifications();
+ mBar.animateCollapsePanels();
}
} break;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
index ab4ef75..194f1f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
@@ -112,7 +112,7 @@
private void onClickNetwork() {
getContext().startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
- getStatusBarManager().collapseNotifications();
+ getStatusBarManager().collapsePanels();
}
// Settings
@@ -121,7 +121,7 @@
getContext().startActivityAsUser(new Intent(Settings.ACTION_SETTINGS)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
new UserHandle(UserHandle.USER_CURRENT));
- getStatusBarManager().collapseNotifications();
+ getStatusBarManager().collapsePanels();
}
}
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 d1dd3c7..97451ae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -740,7 +740,7 @@
SharedPreferences.Editor editor = Prefs.edit(mContext);
editor.putBoolean(Prefs.DO_NOT_DISTURB_PREF, false);
editor.apply();
- animateCollapseNotifications();
+ animateCollapsePanels();
visibilityChanged(false);
}
});
@@ -821,7 +821,7 @@
break;
case MSG_HIDE_CHROME:
if (DEBUG) Slog.d(TAG, "showing shadows (lights out)");
- animateCollapseNotifications();
+ animateCollapsePanels();
visibilityChanged(false);
mBarContents.setVisibility(View.GONE);
mShadow.setVisibility(View.VISIBLE);
@@ -907,7 +907,7 @@
if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
Slog.i(TAG, "DISABLE_EXPAND: yes");
- animateCollapseNotifications();
+ animateCollapsePanels();
visibilityChanged(false);
}
}
@@ -988,16 +988,16 @@
mFeedbackIconArea.setVisibility(View.VISIBLE);
}
- public void animateExpandNotifications() {
+ public void animateExpandNotificationsPanel() {
mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
}
- public void animateCollapseNotifications() {
- animateCollapseNotifications(CommandQueue.FLAG_EXCLUDE_NONE);
+ public void animateCollapsePanels() {
+ animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
}
- public void animateCollapseNotifications(int flags) {
+ public void animateCollapsePanels(int flags) {
if ((flags & CommandQueue.FLAG_EXCLUDE_NOTIFICATION_PANEL) == 0) {
mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PANEL);
mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PANEL);
@@ -1022,12 +1022,7 @@
}
@Override
- public void animateExpandQuickSettings() {
- // TODO: Implement when TabletStatusBar begins to be used.
- }
-
- @Override
- public void animateCollapseQuickSettings() {
+ public void animateExpandSettingsPanel() {
// TODO: Implement when TabletStatusBar begins to be used.
}
@@ -1299,7 +1294,7 @@
mVT.computeCurrentVelocity(1000); // pixels per second
// require a little more oomph once we're already in peekaboo mode
if (mVT.getYVelocity() < -mNotificationFlingVelocity) {
- animateExpandNotifications();
+ animateExpandNotificationsPanel();
visibilityChanged(true);
hilite(false);
mVT.recycle();
@@ -1317,7 +1312,7 @@
&& Math.abs(event.getY() - mInitialTouchY) < (mTouchSlop / 3)
// dragging off the bottom doesn't count
&& (int)event.getY() < v.getBottom()) {
- animateExpandNotifications();
+ animateExpandNotificationsPanel();
visibilityChanged(true);
v.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
v.playSoundEffect(SoundEffectConstants.CLICK);
@@ -1493,7 +1488,7 @@
} catch (RemoteException ex) {
// system process is dead if we're here.
}
- animateCollapseNotifications();
+ animateCollapsePanels();
visibilityChanged(false);
}
@@ -1509,7 +1504,7 @@
flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL;
}
}
- animateCollapseNotifications(flags);
+ animateCollapsePanels(flags);
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index fd2ee38..519d3c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -61,11 +61,11 @@
}
@Override
- public void animateExpandNotifications() {
+ public void animateExpandNotificationsPanel() {
}
@Override
- public void animateCollapseNotifications(int flags) {
+ public void animateCollapsePanels(int flags) {
}
@Override
@@ -143,10 +143,6 @@
}
@Override
- public void animateExpandQuickSettings() {
- }
-
- @Override
- public void animateCollapseQuickSettings() {
+ public void animateExpandSettingsPanel() {
}
}
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 0f9ad59..e1c7e32 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -241,7 +241,8 @@
if (Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.BUGREPORT_IN_POWER_MENU, 0) != 0) {
mItems.add(
- new SinglePressAction(0, R.string.global_action_bug_report) {
+ new SinglePressAction(com.android.internal.R.drawable.stat_sys_adb,
+ R.string.global_action_bug_report) {
public void onPress() {
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
@@ -257,7 +258,11 @@
// screenshot.
mHandler.postDelayed(new Runnable() {
@Override public void run() {
- SystemProperties.set("ctl.start", "bugreport");
+ try {
+ ActivityManagerNative.getDefault()
+ .requestBugReport();
+ } catch (RemoteException e) {
+ }
}
}, 500);
}
@@ -286,6 +291,39 @@
mItems.add(mSilentModeAction);
}
+ // one more thing: optionally add a list of users to switch to
+ if (SystemProperties.getBoolean("fw.power_user_switcher", false)) {
+ addUsersToMenu(mItems);
+ }
+
+ mAdapter = new MyAdapter();
+
+ AlertParams params = new AlertParams(mContext);
+ params.mAdapter = mAdapter;
+ params.mOnClickListener = this;
+ params.mForceInverseBackground = true;
+
+ GlobalActionsDialog dialog = new GlobalActionsDialog(mContext, params);
+ dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
+
+ dialog.getListView().setItemsCanFocus(true);
+ dialog.getListView().setLongClickable(true);
+ dialog.getListView().setOnItemLongClickListener(
+ new AdapterView.OnItemLongClickListener() {
+ @Override
+ public boolean onItemLongClick(AdapterView<?> parent, View view, int position,
+ long id) {
+ return mAdapter.getItem(position).onLongPress();
+ }
+ });
+ dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
+
+ dialog.setOnDismissListener(this);
+
+ return dialog;
+ }
+
+ private void addUsersToMenu(ArrayList<Action> items) {
List<UserInfo> users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE))
.getUsers();
if (users.size() > 1) {
@@ -320,35 +358,9 @@
return false;
}
};
- mItems.add(switchToUser);
+ items.add(switchToUser);
}
}
-
- mAdapter = new MyAdapter();
-
- AlertParams params = new AlertParams(mContext);
- params.mAdapter = mAdapter;
- params.mOnClickListener = this;
- params.mForceInverseBackground = true;
-
- GlobalActionsDialog dialog = new GlobalActionsDialog(mContext, params);
- dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
-
- dialog.getListView().setItemsCanFocus(true);
- dialog.getListView().setLongClickable(true);
- dialog.getListView().setOnItemLongClickListener(
- new AdapterView.OnItemLongClickListener() {
- @Override
- public boolean onItemLongClick(AdapterView<?> parent, View view, int position,
- long id) {
- return mAdapter.getItem(position).onLongPress();
- }
- });
- dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
-
- dialog.setOnDismissListener(this);
-
- return dialog;
}
private void prepareDialog() {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index bba2c7f..72cb1dd 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -993,7 +993,11 @@
if (!mActionBar.isOverflowMenuShowing() || !toggleMenuMode) {
if (cb != null && !isDestroyed() && mActionBar.getVisibility() == View.VISIBLE) {
final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);
- if (cb.onPreparePanel(FEATURE_OPTIONS_PANEL, st.createdPanelView, st.menu)) {
+
+ // If we don't have a menu or we're waiting for a full content refresh,
+ // forget it. This is a lingering event that no longer matters.
+ if (st.menu != null && !st.refreshMenuContent &&
+ cb.onPreparePanel(FEATURE_OPTIONS_PANEL, st.createdPanelView, st.menu)) {
cb.onMenuOpened(FEATURE_ACTION_BAR, st.menu);
mActionBar.showOverflowMenu();
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 2f2b7b0..c3bd988 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -169,11 +169,6 @@
static final boolean SHOW_STARTING_ANIMATIONS = true;
static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
- // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
- // No longer recommended for desk docks; still useful in car docks.
- static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true;
- static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
-
static final int LONG_PRESS_POWER_NOTHING = 0;
static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
static final int LONG_PRESS_POWER_SHUT_OFF = 2;
@@ -347,7 +342,6 @@
boolean mSystemReady;
boolean mSystemBooted;
boolean mHdmiPlugged;
- int mUiMode;
int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
int mLidOpenRotation;
int mCarDockRotation;
@@ -892,8 +886,6 @@
mSettingsObserver.observe();
mShortcutManager = new ShortcutManager(context, mHandler);
mShortcutManager.observe();
- mUiMode = context.getResources().getInteger(
- com.android.internal.R.integer.config_defaultUiModeType);
mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
mHomeIntent.addCategory(Intent.CATEGORY_HOME);
mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
@@ -2936,8 +2928,7 @@
try {
IStatusBarService statusbar = getStatusBarService();
if (statusbar != null) {
- statusbar.collapseNotifications();
- statusbar.collapseQuickSettings();
+ statusbar.collapsePanels();
}
} catch (RemoteException ex) {
// re-acquire status bar service next time it is needed.
@@ -3564,13 +3555,6 @@
if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
Intent.EXTRA_DOCK_STATE_UNDOCKED);
- } else {
- try {
- IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
- ServiceManager.getService(Context.UI_MODE_SERVICE));
- mUiMode = uiModeService.getCurrentModeType();
- } catch (RemoteException e) {
- }
}
updateRotation(true);
updateOrientationListenerLp();
@@ -4123,63 +4107,8 @@
}
}
- /**
- * Return an Intent to launch the currently active dock app as home. Returns
- * null if the standard home should be launched, which is the case if any of the following is
- * true:
- * <ul>
- * <li>The device is not in either car mode or desk mode
- * <li>The device is in car mode but ENABLE_CAR_DOCK_HOME_CAPTURE is false
- * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
- * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
- * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
- * </ul>
- * @return
- */
- Intent createHomeDockIntent() {
- Intent intent = null;
-
- // What home does is based on the mode, not the dock state. That
- // is, when in car mode you should be taken to car home regardless
- // of whether we are actually in a car dock.
- if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
- if (ENABLE_CAR_DOCK_HOME_CAPTURE) {
- intent = mCarDockIntent;
- }
- } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
- if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
- intent = mDeskDockIntent;
- }
- }
-
- if (intent == null) {
- return null;
- }
-
- ActivityInfo ai = intent.resolveActivityInfo(
- mContext.getPackageManager(), PackageManager.GET_META_DATA);
- if (ai == null) {
- return null;
- }
-
- if (ai.metaData != null && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
- intent = new Intent(intent);
- intent.setClassName(ai.packageName, ai.name);
- return intent;
- }
-
- return null;
- }
-
void startDockOrHome() {
- Intent dock = createHomeDockIntent();
- if (dock != null) {
- try {
- mContext.startActivity(dock);
- return;
- } catch (ActivityNotFoundException e) {
- }
- }
+ // We don't have dock home anymore. Home is home. If you lived here, you'd be home by now.
mContext.startActivityAsUser(mHomeIntent, UserHandle.CURRENT);
}
@@ -4206,18 +4135,6 @@
} else {
ActivityManagerNative.getDefault().stopAppSwitches();
sendCloseSystemWindows();
- Intent dock = createHomeDockIntent();
- if (dock != null) {
- int result = ActivityManagerNative.getDefault()
- .startActivityAsUser(null, dock,
- dock.resolveTypeIfNeeded(mContext.getContentResolver()),
- null, null, 0,
- ActivityManager.START_FLAG_ONLY_IF_NEEDED,
- null, null, null, UserHandle.USER_CURRENT);
- if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
- return false;
- }
- }
}
int result = ActivityManagerNative.getDefault()
.startActivityAsUser(null, mHomeIntent,
@@ -4404,8 +4321,7 @@
pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
pw.println(mLastFocusNeedsMenu);
}
- pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
- pw.print(" mDockMode="); pw.print(mDockMode);
+ pw.print(prefix); pw.print("mDockMode="); pw.print(mDockMode);
pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/EmergencyButton.java b/policy/src/com/android/internal/policy/impl/keyguard/EmergencyButton.java
index 1828ea5..203ba3c 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/EmergencyButton.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/EmergencyButton.java
@@ -98,11 +98,19 @@
}
private void updateEmergencyCallButton(State simState, int phoneState) {
- boolean enabled = mLockPatternUtils.isEmergencyCallCapable()
- || (phoneState == TelephonyManager.CALL_STATE_OFFHOOK); // voice call in progress
- if (enabled && KeyguardUpdateMonitor.isSimLocked(simState)) {
- // Some countries can't handle emergency calls while SIM is locked.
- enabled = mLockPatternUtils.isEmergencyCallEnabledWhileSimLocked();
+ boolean enabled = false;
+ if (phoneState == TelephonyManager.CALL_STATE_OFFHOOK) {
+ enabled = true; // always show "return to call" if phone is off-hook
+ } else if (mLockPatternUtils.isEmergencyCallCapable()) {
+ boolean simLocked = KeyguardUpdateMonitor.getInstance(mContext).isSimLocked();
+ if (simLocked) {
+ // Some countries can't handle emergency calls while SIM is locked.
+ enabled = mLockPatternUtils.isEmergencyCallEnabledWhileSimLocked();
+ } else {
+ // True if we need to show a secure screen (pin/pattern/SIM pin/SIM puk);
+ // hides emergency button on "Slide" screen if device is not secure.
+ enabled = mLockPatternUtils.isSecure();
+ }
}
mLockPatternUtils.updateEmergencyCallButtonState(this, phoneState, enabled,
KeyguardViewManager.USE_UPPER_CASE, false);
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 2e7228c..1d1c7fc 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -123,7 +123,9 @@
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
- mViewMediatorCallback.keyguardDoneDrawing();
+ if (mViewMediatorCallback != null) {
+ mViewMediatorCallback.keyguardDoneDrawing();
+ }
}
private int getWidgetPosition(int id) {
@@ -230,7 +232,9 @@
private KeyguardSecurityCallback mCallback = new KeyguardSecurityCallback() {
public void userActivity(long timeout) {
- mViewMediatorCallback.pokeWakelock(timeout);
+ if (mViewMediatorCallback != null) {
+ mViewMediatorCallback.pokeWakelock(timeout);
+ }
}
public void dismiss(boolean authenticated) {
@@ -450,7 +454,9 @@
mLaunchRunnable.run();
mLaunchRunnable = null;
}
- mViewMediatorCallback.keyguardDone(true);
+ if (mViewMediatorCallback != null) {
+ mViewMediatorCallback.keyguardDone(true);
+ }
}
}
@@ -541,7 +547,10 @@
oldView.onPause();
newView.onResume();
- mViewMediatorCallback.setNeedsInput(newView.needsInput());
+ final boolean needsInput = newView.needsInput();
+ if (mViewMediatorCallback != null) {
+ mViewMediatorCallback.setNeedsInput(needsInput);
+ }
// Find and show this child.
final int childCount = mSecurityViewContainer.getChildCount();
@@ -624,9 +633,10 @@
if (keyCode == KeyEvent.KEYCODE_MENU && isSecure()) {
if (DEBUG) Log.d(TAG, "switching screens to unlock screen because wake key was MENU");
showSecurityScreen(SecurityMode.None);
- mViewMediatorCallback.pokeWakelock();
} else {
if (DEBUG) Log.d(TAG, "poking wake lock immediately");
+ }
+ if (mViewMediatorCallback != null) {
mViewMediatorCallback.pokeWakelock();
}
}
@@ -635,11 +645,15 @@
public void verifyUnlock() {
SecurityMode securityMode = mSecurityModel.getSecurityMode();
if (securityMode == KeyguardSecurityModel.SecurityMode.None) {
- mViewMediatorCallback.keyguardDone(true);
+ if (mViewMediatorCallback != null) {
+ mViewMediatorCallback.keyguardDone(true);
+ }
} else if (securityMode != KeyguardSecurityModel.SecurityMode.Pattern
&& securityMode != KeyguardSecurityModel.SecurityMode.Password) {
// can only verify unlock when in pattern/password mode
- mViewMediatorCallback.keyguardDone(false);
+ if (mViewMediatorCallback != null) {
+ mViewMediatorCallback.keyguardDone(false);
+ }
} else {
// otherwise, go to the unlock screen, see if they can verify it
mIsVerifyUnlockOnly = true;
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserAvatar.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserAvatar.java
index 759068d..8c1dfe1 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserAvatar.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserAvatar.java
@@ -45,6 +45,9 @@
private boolean mInit = true;
private KeyguardMultiUserSelectorView mUserSelector;
+ boolean mPressedStateLocked = false;
+ boolean mTempPressedStateHolder = false;
+
public static KeyguardMultiUserAvatar fromXml(int resId, Context context,
KeyguardMultiUserSelectorView userSelector, UserInfo info) {
KeyguardMultiUserAvatar icon = (KeyguardMultiUserAvatar)
@@ -135,25 +138,33 @@
}
}
- boolean mLockDrawableState = false;
-
- public void lockDrawableState() {
- mLockDrawableState = true;
+ public void lockPressedState() {
+ mPressedStateLocked = true;
}
- public void resetDrawableState() {
- mLockDrawableState = false;
+ public void resetPressedState() {
+ mPressedStateLocked = false;
post(new Runnable() {
@Override
public void run() {
- refreshDrawableState();
+ KeyguardMultiUserAvatar.this.setPressed(mTempPressedStateHolder);
}
});
}
- protected void drawableStateChanged() {
- if (!mLockDrawableState) {
- super.drawableStateChanged();
+ @Override
+ public void setPressed(boolean pressed) {
+ if (!mPressedStateLocked) {
+ super.setPressed(pressed);
+ if (pressed) {
+ mUserImage.setColorFilter(Color.argb(0, INACTIVE_COLOR,
+ INACTIVE_COLOR, INACTIVE_COLOR));
+ } else if (!mActive) {
+ mUserImage.setColorFilter(Color.argb(INACTIVE_ALPHA, INACTIVE_COLOR,
+ INACTIVE_COLOR, INACTIVE_COLOR));
+ }
+ } else {
+ mTempPressedStateHolder = pressed;
}
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserSelectorView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserSelectorView.java
index e4096b9..3b45c22 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserSelectorView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserSelectorView.java
@@ -111,7 +111,7 @@
return;
} else {
// Reset the previously active user to appear inactive
- avatar.lockDrawableState();
+ avatar.lockPressedState();
mCallback.hideSecurityView(FADE_OUT_ANIMATION_DURATION);
mActiveUserAvatar.setActive(false, true, SWITCH_ANIMATION_DURATION, new Runnable() {
@Override
@@ -120,7 +120,7 @@
ActivityManagerNative.getDefault().switchUser(avatar.getUserInfo().id);
WindowManagerGlobal.getWindowManagerService().lockNow();
// Set the new active user, and make it appear active
- avatar.resetDrawableState();
+ avatar.resetPressedState();
mCallback.showSecurityView();
mActiveUserAvatar = avatar;
mActiveUserAvatar.setActive(true, false, 0, null);
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java
index d4bed25..2015826 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java
@@ -19,13 +19,11 @@
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
-import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.text.Editable;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
@@ -42,16 +40,11 @@
import com.android.internal.R;
public class KeyguardSimPukView extends LinearLayout implements View.OnClickListener,
- View.OnFocusChangeListener, KeyguardSecurityView, OnEditorActionListener {
+ KeyguardSecurityView, OnEditorActionListener {
private static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
- private TextView mPukText;
- private TextView mPinText;
- private TextView mFocusedEntry;
-
- private View mDelPukButton;
- private View mDelPinButton;
+ private View mDeleteButton;
private ProgressDialog mSimUnlockProgressDialog = null;
private KeyguardSecurityCallback mCallback;
@@ -66,6 +59,60 @@
private volatile boolean mCheckInProgress;
+ private TextView mSimPinEntry;
+
+ private String mPukText;
+
+ private String mPinText;
+ private StateMachine mStateMachine = new StateMachine();
+
+ private class StateMachine {
+ final int ENTER_PUK = 0;
+ final int ENTER_PIN = 1;
+ final int CONFIRM_PIN = 2;
+ final int DONE = 3;
+ private int state = ENTER_PUK;
+
+ public void next() {
+ int msg = 0;
+ if (state == ENTER_PUK) {
+ if (checkPuk()) {
+ state = ENTER_PIN;
+ msg = R.string.kg_puk_enter_pin_hint;
+ } else {
+ msg = R.string.kg_invalid_sim_puk_hint;
+ }
+ } else if (state == ENTER_PIN) {
+ if (checkPin()) {
+ state = CONFIRM_PIN;
+ msg = R.string.kg_enter_confirm_pin_hint;
+ } else {
+ msg = R.string.kg_invalid_sim_pin_hint;
+ }
+ } else if (state == CONFIRM_PIN) {
+ if (confirmPin()) {
+ state = DONE;
+ msg = R.string.kg_login_checking_password;
+ updateSim();
+ } else {
+ msg = R.string.kg_invalid_confirm_pin_hint;
+ }
+ }
+ mSimPinEntry.setText(null);
+ if (msg != 0) {
+ mNavigationManager.setMessage(msg);
+ }
+ }
+
+ void reset() {
+ mPinText="";
+ mPukText="";
+ state = ENTER_PUK;
+ mNavigationManager.setMessage(R.string.kg_puk_enter_puk_hint);
+ mSimPinEntry.requestFocus();
+ }
+ }
+
public KeyguardSimPukView(Context context) {
this(context, null);
}
@@ -86,15 +133,10 @@
mNavigationManager = new KeyguardNavigationManager(this);
- mPukText = (TextView) findViewById(R.id.sim_puk_entry);
- mPukText.setOnEditorActionListener(this);
- mPinText = (TextView) findViewById(R.id.sim_pin_entry);
- mPinText.setOnEditorActionListener(this);
- mDelPukButton = findViewById(R.id.puk_delete_button);
- mDelPukButton.setOnClickListener(this);
- mDelPinButton = findViewById(R.id.pin_delete_button);
- mDelPinButton.setOnClickListener(this);
-
+ mSimPinEntry = (TextView) findViewById(R.id.sim_pin_entry);
+ mSimPinEntry.setOnEditorActionListener(this);
+ mDeleteButton = findViewById(R.id.delete_button);
+ mDeleteButton.setOnClickListener(this);
mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
mKeyboardHelper = new PasswordEntryKeyboardHelper(mContext, mKeyboardView, this, false,
new int[] {
@@ -106,22 +148,12 @@
});
mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
mKeyboardHelper.setEnableHaptics(mLockPatternUtils.isTactileFeedbackEnabled());
-
- mNavigationManager.setMessage(R.string.kg_sim_puk_recovery_hint);
-
- mPinText.setFocusableInTouchMode(true);
- mPinText.setOnFocusChangeListener(this);
- mPukText.setFocusableInTouchMode(true);
- mPukText.setOnFocusChangeListener(this);
-
- setFocusableInTouchMode(true);
-
reset();
}
@Override
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
- return mPukText.requestFocus(direction, previouslyFocusedRect);
+ return mSimPinEntry.requestFocus(direction, previouslyFocusedRect);
}
public boolean needsInput() {
@@ -182,18 +214,9 @@
}
public void onClick(View v) {
- if (v == mDelPukButton) {
- if (mFocusedEntry != mPukText)
- mPukText.requestFocus();
- final Editable digits = mPukText.getEditableText();
- final int len = digits.length();
- if (len > 0) {
- digits.delete(len-1, len);
- }
- } else if (v == mDelPinButton) {
- if (mFocusedEntry != mPinText)
- mPinText.requestFocus();
- final Editable digits = mPinText.getEditableText();
+ if (v == mDeleteButton) {
+ mSimPinEntry.requestFocus();
+ final Editable digits = mSimPinEntry.getEditableText();
final int len = digits.length();
if (len > 0) {
digits.delete(len-1, len);
@@ -202,12 +225,6 @@
mCallback.userActivity(DIGIT_PRESS_WAKE_MILLIS);
}
- @Override
- public void onFocusChange(View view, boolean hasFocus) {
- if (hasFocus)
- mFocusedEntry = (TextView) view;
- }
-
private Dialog getSimUnlockProgressDialog() {
if (mSimUnlockProgressDialog == null) {
mSimUnlockProgressDialog = new ProgressDialog(mContext);
@@ -223,32 +240,37 @@
return mSimUnlockProgressDialog;
}
- private void checkPuk() {
+ private boolean checkPuk() {
// make sure the puk is at least 8 digits long.
- if (mPukText.getText().length() < 8) {
- // otherwise, display a message to the user, and don't submit.
- mNavigationManager.setMessage(R.string.kg_invalid_sim_puk_hint);
- mPukText.setText("");
- return;
+ if (mSimPinEntry.getText().length() >= 8) {
+ mPukText = mSimPinEntry.getText().toString();
+ return true;
}
+ return false;
+ }
+ private boolean checkPin() {
// make sure the PIN is between 4 and 8 digits
- if (mPinText.getText().length() < 4
- || mPinText.getText().length() > 8) {
- // otherwise, display a message to the user, and don't submit.
- mNavigationManager.setMessage(R.string.kg_invalid_sim_pin_hint);
- mPinText.setText("");
- return;
+ int length = mSimPinEntry.getText().length();
+ if (length >= 4 && length <= 8) {
+ mPinText = mSimPinEntry.getText().toString();
+ return true;
}
+ return false;
+ }
+ public boolean confirmPin() {
+ return mPinText.equals(mSimPinEntry.getText().toString());
+ }
+
+ private void updateSim() {
getSimUnlockProgressDialog().show();
if (!mCheckInProgress) {
mCheckInProgress = true;
- new CheckSimPuk(mPukText.getText().toString(),
- mPinText.getText().toString()) {
+ new CheckSimPuk(mPukText, mPinText) {
void onSimLockChangedResponse(final boolean success) {
- mPinText.post(new Runnable() {
+ post(new Runnable() {
public void run() {
if (mSimUnlockProgressDialog != null) {
mSimUnlockProgressDialog.hide();
@@ -256,9 +278,8 @@
if (success) {
mCallback.dismiss(true);
} else {
+ mStateMachine.reset();
mNavigationManager.setMessage(R.string.kg_invalid_puk);
- mPukText.setText("");
- mPinText.setText("");
}
mCheckInProgress = false;
}
@@ -273,24 +294,10 @@
// Check if this was the result of hitting the enter key
mCallback.userActivity(DIGIT_PRESS_WAKE_MILLIS);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
- if (actionId == EditorInfo.IME_NULL
- || actionId == EditorInfo.IME_ACTION_DONE
+ if (actionId == EditorInfo.IME_NULL || actionId == EditorInfo.IME_ACTION_DONE
|| actionId == EditorInfo.IME_ACTION_NEXT) {
- if (view == mPukText && mPukText.getText().length() < 8) {
- mNavigationManager.setMessage(R.string.kg_invalid_sim_puk_hint);
- mPukText.setText("");
- mPukText.requestFocus();
- return true;
- } else if (view == mPinText) {
- if (mPinText.getText().length() < 4 || mPinText.getText().length() > 8) {
- mNavigationManager.setMessage(R.string.kg_invalid_sim_pin_hint);
- mPinText.setText("");
- mPinText.requestFocus();
- } else {
- checkPuk();
- }
- return true;
- }
+ mStateMachine.next();
+ return true;
}
}
return false;
@@ -303,10 +310,7 @@
@Override
public void reset() {
- mNavigationManager.setMessage(R.string.kg_sim_puk_recovery_hint);
- mPinText.setText("");
- mPukText.setText("");
- mPukText.requestFocus();
+ mStateMachine.reset();
}
@Override
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java
index 701017d..866194c 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java
@@ -184,8 +184,8 @@
Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
String text = Settings.Secure.getStringForUser(res, Settings.Secure.LOCK_SCREEN_OWNER_INFO,
UserHandle.USER_CURRENT);
- text = text != null ? text.trim() : null; // Remove trailing newlines
if (ownerInfoEnabled && !TextUtils.isEmpty(text)) {
+ text = text.trim(); // Remove trailing newlines
maybeSetUpperCaseText(mOwnerInfoView, text);
mOwnerInfoView.setVisibility(View.VISIBLE);
} else {
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 ebdb116..1abcc10 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
@@ -164,8 +164,9 @@
}
private void inflateKeyguardView() {
- if (mKeyguardView != null) {
- mKeyguardHost.removeView(mKeyguardView);
+ View v = mKeyguardHost.findViewById(R.id.keyguard_host_view);
+ if (v != null) {
+ mKeyguardHost.removeView(v);
}
// TODO: Remove once b/7094175 is fixed
Slog.d(TAG, "inflateKeyguardView: b/7094175 mContext.config="
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index b567992..87b0eb3 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -117,45 +117,34 @@
// ================================================================================
// From IStatusBarService
// ================================================================================
- public void expandNotifications() {
+ public void expandNotificationsPanel() {
enforceExpandStatusBar();
if (mBar != null) {
try {
- mBar.animateExpandNotifications();
+ mBar.animateExpandNotificationsPanel();
} catch (RemoteException ex) {
}
}
}
- public void collapseNotifications() {
+ public void collapsePanels() {
enforceExpandStatusBar();
if (mBar != null) {
try {
- mBar.animateCollapseNotifications();
+ mBar.animateCollapsePanels();
} catch (RemoteException ex) {
}
}
}
- public void expandQuickSettings() {
+ public void expandSettingsPanel() {
enforceExpandStatusBar();
if (mBar != null) {
try {
- mBar.animateExpandQuickSettings();
- } catch (RemoteException ex) {
- }
- }
- }
-
- public void collapseQuickSettings() {
- enforceExpandStatusBar();
-
- if (mBar != null) {
- try {
- mBar.animateCollapseQuickSettings();
+ mBar.animateExpandSettingsPanel();
} catch (RemoteException ex) {
}
}
@@ -620,8 +609,7 @@
String action = intent.getAction();
if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)
|| Intent.ACTION_SCREEN_OFF.equals(action)) {
- collapseNotifications();
- collapseQuickSettings();
+ collapsePanels();
}
/*
else if (Telephony.Intents.SPN_STRINGS_UPDATED_ACTION.equals(action)) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 738e19b..b684c90 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -38,7 +38,7 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.server.search.SearchManagerService;
-import android.service.dreams.Dream;
+import android.service.dreams.DreamService;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
@@ -741,7 +741,7 @@
Slog.i(TAG, "Dreams Service");
// Dreams (interactive idle-time views, a/k/a screen savers)
dreamy = new DreamManagerService(context, wmHandler);
- ServiceManager.addService(Dream.DREAM_SERVICE, dreamy);
+ ServiceManager.addService(DreamService.DREAM_SERVICE, dreamy);
} catch (Throwable e) {
reportWtf("starting DreamManagerService", e);
}
diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java
index 3b8caba..d1af2b0 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/java/com/android/server/UiModeManagerService.java
@@ -39,7 +39,7 @@
import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
-import android.service.dreams.Dream;
+import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
import android.util.Slog;
@@ -501,7 +501,7 @@
Slog.i(TAG, "Activating dream while docked.");
try {
IDreamManager dreamManagerService = IDreamManager.Stub.asInterface(
- ServiceManager.getService(Dream.DREAM_SERVICE));
+ ServiceManager.getService(DreamService.DREAM_SERVICE));
dreamManagerService.dream();
} catch (RemoteException ex) {
Slog.e(TAG, "Could not start dream when docked.", ex);
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index cae67e9..8193a4f 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -827,7 +827,7 @@
private void tryAddServiceLocked(Service service, int userId) {
try {
UserState userState = getUserStateLocked(userId);
- if (userState.mServices.contains(service) || !service.isConfigured()) {
+ if (userState.mServices.contains(service)) {
return;
}
service.linkToOwnDeath();
@@ -876,7 +876,7 @@
private boolean canDispathEventLocked(Service service, AccessibilityEvent event,
int handledFeedbackTypes) {
- if (!service.isConfigured()) {
+ if (!service.canReceiveEvents()) {
return false;
}
@@ -1192,7 +1192,8 @@
private void tryEnableTouchExplorationLocked(final Service service) {
UserState userState = getUserStateLocked(service.mUserId);
- if (!userState.mIsTouchExplorationEnabled && service.mRequestTouchExplorationMode) {
+ if (!userState.mIsTouchExplorationEnabled && service.mRequestTouchExplorationMode
+ && service.canReceiveEvents()) {
final boolean canToggleTouchExploration =
userState.mTouchExplorationGrantedServices.contains(service.mComponentName);
if (!service.mIsAutomation && !canToggleTouchExploration) {
@@ -1464,7 +1465,7 @@
// If this service is up and running we may have to enable touch
// exploration, otherwise this will happen when the service connects.
synchronized (mLock) {
- if (isConfigured()) {
+ if (canReceiveEvents()) {
if (mRequestTouchExplorationMode) {
tryEnableTouchExplorationLocked(this);
} else {
@@ -1505,13 +1506,7 @@
return false;
}
- /**
- * Returns if the service is configured i.e. at least event types of interest
- * and feedback type must be set.
- *
- * @return True if the service is configured, false otherwise.
- */
- public boolean isConfigured() {
+ public boolean canReceiveEvents() {
return (mEventTypes != 0 && mFeedbackType != 0 && mService != null);
}
@@ -2028,7 +2023,7 @@
StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService(
android.app.Service.STATUS_BAR_SERVICE);
- statusBarManager.expandNotifications();
+ statusBarManager.expandNotificationsPanel();
Binder.restoreCallingIdentity(token);
}
@@ -2038,7 +2033,7 @@
StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService(
android.app.Service.STATUS_BAR_SERVICE);
- statusBarManager.expandQuickSettings();
+ statusBarManager.expandSettingsPanel();
Binder.restoreCallingIdentity(token);
}
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index 921bed7..6e57d1f 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -102,6 +102,10 @@
// The timeout after which we are no longer trying to detect a gesture.
private static final int EXIT_GESTURE_DETECTION_TIMEOUT = 2000;
+ // The timeout to send interaction end events in case we did not
+ // receive the expected hover exit event due to a misbehaving app.
+ private static final int SEND_INTERACTION_END_EVENTS_TIMEOUT = 200;
+
// Temporary array for storing pointer IDs.
private final int[] mTempPointerIds = new int[MAX_POINTER_COUNT];
@@ -135,6 +139,9 @@
// Command for delayed sending of a hover exit event.
private final SendHoverDelayed mSendHoverExitDelayed;
+ // Command for delayed sending of interaction ending events.
+ private final SendInteractionEndEventsDelayed mSendInteractionEndEventsDelayed;
+
// Command for delayed sending of a long press.
private final PerformLongPressDelayed mPerformLongPressDelayed;
@@ -233,6 +240,7 @@
mGestureLibrary.load();
mSendHoverEnterDelayed = new SendHoverDelayed(MotionEvent.ACTION_HOVER_ENTER, true);
mSendHoverExitDelayed = new SendHoverDelayed(MotionEvent.ACTION_HOVER_EXIT, false);
+ mSendInteractionEndEventsDelayed = new SendInteractionEndEventsDelayed();
mDoubleTapDetector = new DoubleTapDetector();
final float density = context.getResources().getDisplayMetrics().density;
mScaledMinPointerDistanceToUseMiddleLocation =
@@ -278,6 +286,7 @@
mSendHoverExitDelayed.remove();
mPerformLongPressDelayed.remove();
mExitGestureDetectionModeDelayed.remove();
+ mSendInteractionEndEventsDelayed.remove();
// Reset the pointer trackers.
mReceivedPointerTracker.clear();
mInjectedPointerTracker.clear();
@@ -334,6 +343,7 @@
// last hover exit event.
if (mTouchExplorationGestureEnded
&& eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
+ mSendInteractionEndEventsDelayed.remove();
mTouchExplorationGestureEnded = false;
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END);
}
@@ -342,6 +352,7 @@
// last hover exit and the touch exploration gesture end events.
if (mTouchInteractionEnded
&& eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
+ mSendInteractionEndEventsDelayed.remove();
mTouchInteractionEnded = false;
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
}
@@ -416,6 +427,10 @@
mSendHoverExitDelayed.remove();
}
+ if (mSendInteractionEndEventsDelayed.isPending()) {
+ mSendInteractionEndEventsDelayed.forceSendAndRemove();
+ }
+
mPerformLongPressDelayed.remove();
// If we have the first tap schedule a long press and break
@@ -685,13 +700,6 @@
}
}
} break;
- case MotionEvent.ACTION_POINTER_UP: {
- final int pointerId = event.getPointerId(event.getActionIndex());
- if (mReceivedPointerTracker.isActiveOrWasLastActiveUpPointer(pointerId)) {
- sendUpForInjectedDownPointers(event, policyFlags);
- mCurrentState = STATE_TOUCH_EXPLORING;
- }
- } break;
case MotionEvent.ACTION_UP: {
// Announce the end of a new touch interaction.
sendAccessibilityEvent(
@@ -873,6 +881,9 @@
final int pointerIdBits = event.getPointerIdBits();
mTouchExplorationGestureEnded = true;
mTouchInteractionEnded = true;
+ if (!mSendInteractionEndEventsDelayed.isPending()) {
+ mSendInteractionEndEventsDelayed.post();
+ }
sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits, policyFlags);
}
}
@@ -1300,6 +1311,11 @@
@Override
public void run() {
+ // Announce the end of gesture recognition.
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_END);
+ // Clearing puts is in touch exploration state with a finger already
+ // down, so announce the transition to exploration state.
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
clear();
}
}
@@ -1479,10 +1495,16 @@
} else {
mTouchExplorationGestureEnded = true;
mTouchInteractionEnded = true;
+ if (!mSendInteractionEndEventsDelayed.isPending()) {
+ mSendInteractionEndEventsDelayed.post();
+ }
}
} else {
if (!mGestureStarted) {
mTouchInteractionEnded = true;
+ if (!mSendInteractionEndEventsDelayed.isPending()) {
+ mSendInteractionEndEventsDelayed.post();
+ }
}
}
sendMotionEvent(mPrototype, mHoverAction, mPointerIdBits, mPolicyFlags);
@@ -1490,6 +1512,40 @@
}
}
+ private class SendInteractionEndEventsDelayed implements Runnable {
+
+ public void remove() {
+ mHandler.removeCallbacks(this);
+ }
+
+ public void post() {
+ mHandler.postDelayed(this, SEND_INTERACTION_END_EVENTS_TIMEOUT);
+ }
+
+ public boolean isPending() {
+ return mHandler.hasCallbacks(this);
+ }
+
+ public void forceSendAndRemove() {
+ if (isPending()) {
+ run();
+ remove();
+ }
+ }
+
+ @Override
+ public void run() {
+ if (mTouchExplorationGestureEnded) {
+ mTouchExplorationGestureEnded = false;
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END);
+ }
+ if (mTouchInteractionEnded) {
+ mTouchInteractionEnded = false;
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
+ }
+ }
+ }
+
@Override
public String toString() {
return LOG_TAG;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index bfefe67..3428326 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -912,21 +912,38 @@
switch (msg.what) {
case SHOW_ERROR_MSG: {
HashMap data = (HashMap) msg.obj;
+ boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
synchronized (ActivityManagerService.this) {
ProcessRecord proc = (ProcessRecord)data.get("app");
+ AppErrorResult res = (AppErrorResult) data.get("result");
if (proc != null && proc.crashDialog != null) {
Slog.e(TAG, "App already has crash dialog: " + proc);
+ if (res != null) {
+ res.set(0);
+ }
return;
}
- AppErrorResult res = (AppErrorResult) data.get("result");
+ if (!showBackground && UserHandle.getAppId(proc.uid)
+ >= Process.FIRST_APPLICATION_UID && proc.userId != mCurrentUserId
+ && proc.pid != MY_PID) {
+ Slog.w(TAG, "Skipping crash dialog of " + proc + ": background");
+ if (res != null) {
+ res.set(0);
+ }
+ return;
+ }
if (mShowDialogs && !mSleeping && !mShuttingDown) {
- Dialog d = new AppErrorDialog(mContext, res, proc);
+ Dialog d = new AppErrorDialog(mContext,
+ ActivityManagerService.this, res, proc);
d.show();
proc.crashDialog = d;
} else {
// The device is asleep, so just pretend that the user
// saw a crash dialog and hit "force quit".
- res.set(0);
+ if (res != null) {
+ res.set(0);
+ }
}
}
@@ -977,7 +994,8 @@
}
AppErrorResult res = (AppErrorResult) data.get("result");
if (mShowDialogs && !mSleeping && !mShuttingDown) {
- Dialog d = new StrictModeViolationDialog(mContext, res, proc);
+ Dialog d = new StrictModeViolationDialog(mContext,
+ ActivityManagerService.this, res, proc);
d.show();
proc.crashDialog = d;
} else {
@@ -3683,7 +3701,8 @@
void closeSystemDialogsLocked(String reason) {
Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
if (reason != null) {
intent.putExtra("reason", reason);
}
@@ -3755,7 +3774,8 @@
Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
Uri.fromParts("package", packageName, null));
if (!mProcessesReady) {
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
}
intent.putExtra(Intent.EXTRA_UID, uid);
intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(uid));
@@ -3768,7 +3788,8 @@
private void forceStopUserLocked(int userId) {
forceStopPackageLocked(null, -1, false, false, true, false, userId);
Intent intent = new Intent(Intent.ACTION_USER_STOPPED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
@@ -7363,7 +7384,14 @@
return mController != null;
}
}
-
+
+ public void requestBugReport() {
+ // No permission check because this can't do anything harmful --
+ // it will just eventually cause the user to be presented with
+ // a UI to select where the bug report goes.
+ SystemProperties.set("ctl.start", "bugreport");
+ }
+
public void registerProcessObserver(IProcessObserver observer) {
enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
"registerProcessObserver()");
@@ -7698,9 +7726,9 @@
}
}
intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
-
+
ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
-
+
final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
for (int i=0; i<ris.size(); i++) {
ActivityInfo ai = ris.get(i).activityInfo;
@@ -7874,7 +7902,8 @@
long ident = Binder.clearCallingIdentity();
try {
Intent intent = new Intent(Intent.ACTION_USER_STARTED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
@@ -8081,8 +8110,15 @@
}
void startAppProblemLocked(ProcessRecord app) {
- app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
- mContext, app.info.packageName, app.info.flags);
+ if (app.userId == mCurrentUserId) {
+ app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
+ mContext, app.info.packageName, app.info.flags);
+ } else {
+ // If this app is not running under the current user, then we
+ // can't give it a report button because that would require
+ // launching the report UI under a different user.
+ app.errorReportReceiver = null;
+ }
skipCurrentReceiverLocked(app);
}
@@ -8590,7 +8626,7 @@
if (appErrorIntent != null) {
try {
- mContext.startActivity(appErrorIntent);
+ mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId));
} catch (ActivityNotFoundException e) {
Slog.w(TAG, "bug report receiver dissappeared", e);
}
@@ -11427,6 +11463,17 @@
for (int user : users) {
List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
.queryIntentReceivers(intent, resolvedType, STOCK_PM_FLAGS, user);
+ if (user != 0 && newReceivers != null) {
+ // If this is not the primary user, we need to check for
+ // any receivers that should be filtered out.
+ for (int i=0; i<newReceivers.size(); i++) {
+ ResolveInfo ri = newReceivers.get(i);
+ if ((ri.activityInfo.flags&ActivityInfo.FLAG_PRIMARY_USER_ONLY) != 0) {
+ newReceivers.remove(i);
+ i--;
+ }
+ }
+ }
if (newReceivers != null && newReceivers.size() == 0) {
newReceivers = null;
}
@@ -12271,12 +12318,14 @@
}
Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
- | Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ | Intent.FLAG_RECEIVER_REPLACE_PENDING
+ | Intent.FLAG_RECEIVER_FOREGROUND);
broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
- broadcastIntentLocked(null, null,
- new Intent(Intent.ACTION_LOCALE_CHANGED),
+ intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ broadcastIntentLocked(null, null, intent,
null, null, 0, null, null,
null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
}
@@ -14057,6 +14106,7 @@
return false;
}
+ mWindowManager.lockNow();
mWindowManager.startFreezingScreen(R.anim.screen_user_exit,
R.anim.screen_user_enter);
@@ -14084,7 +14134,8 @@
mHandler.sendMessageDelayed(mHandler.obtainMessage(USER_SWITCH_TIMEOUT_MSG,
oldUserId, userId, uss), USER_SWITCH_TIMEOUT);
Intent intent = new Intent(Intent.ACTION_USER_STARTED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
@@ -14093,17 +14144,17 @@
if ((userInfo.flags&UserInfo.FLAG_INITIALIZED) == 0) {
if (userId != 0) {
intent = new Intent(Intent.ACTION_USER_INITIALIZE);
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
broadcastIntentLocked(null, null, intent, null,
new IIntentReceiver.Stub() {
public void performReceive(Intent intent, int resultCode,
String data, Bundle extras, boolean ordered,
boolean sticky, int sendingUser) {
- synchronized (ActivityManagerService.this) {
- getUserManagerLocked().makeInitialized(userInfo.id);
- }
+ userInitialized(uss);
}
}, 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID,
userId);
+ uss.initializing = true;
} else {
getUserManagerLocked().makeInitialized(userInfo.id);
}
@@ -14130,7 +14181,8 @@
Intent intent;
if (oldUserId >= 0) {
intent = new Intent(Intent.ACTION_USER_BACKGROUND);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_USER_HANDLE, oldUserId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
@@ -14138,13 +14190,15 @@
}
if (newUserId >= 0) {
intent = new Intent(Intent.ACTION_USER_FOREGROUND);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_USER_HANDLE, newUserId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
false, false, MY_PID, Process.SYSTEM_UID, newUserId);
intent = new Intent(Intent.ACTION_USER_SWITCHED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_USER_HANDLE, newUserId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null,
@@ -14175,6 +14229,7 @@
}
};
synchronized (this) {
+ uss.switching = true;
mCurUserSwitchCallback = callback;
}
for (int i=0; i<N; i++) {
@@ -14206,6 +14261,14 @@
oldUserId, newUserId, uss));
}
+ void userInitialized(UserStartedState uss) {
+ synchronized (ActivityManagerService.this) {
+ getUserManagerLocked().makeInitialized(uss.mHandle.getIdentifier());
+ uss.initializing = false;
+ completeSwitchAndInitalizeLocked(uss);
+ }
+ }
+
void continueUserSwitch(UserStartedState uss, int oldUserId, int newUserId) {
final int N = mUserSwitchObservers.beginBroadcast();
for (int i=0; i<N; i++) {
@@ -14216,6 +14279,13 @@
}
mUserSwitchObservers.finishBroadcast();
synchronized (this) {
+ uss.switching = false;
+ completeSwitchAndInitalizeLocked(uss);
+ }
+ }
+
+ void completeSwitchAndInitalizeLocked(UserStartedState uss) {
+ if (!uss.switching && !uss.initializing) {
mWindowManager.stopFreezingScreen();
}
}
diff --git a/services/java/com/android/server/am/AppErrorDialog.java b/services/java/com/android/server/am/AppErrorDialog.java
index 57e11cf..0ebbe3b 100644
--- a/services/java/com/android/server/am/AppErrorDialog.java
+++ b/services/java/com/android/server/am/AppErrorDialog.java
@@ -29,6 +29,7 @@
class AppErrorDialog extends BaseErrorDialog {
private final static String TAG = "AppErrorDialog";
+ private final ActivityManagerService mService;
private final AppErrorResult mResult;
private final ProcessRecord mProc;
@@ -39,11 +40,13 @@
// 5-minute timeout, then we automatically dismiss the crash dialog
static final long DISMISS_TIMEOUT = 1000 * 60 * 5;
- public AppErrorDialog(Context context, AppErrorResult result, ProcessRecord app) {
+ public AppErrorDialog(Context context, ActivityManagerService service,
+ AppErrorResult result, ProcessRecord app) {
super(context);
Resources res = context.getResources();
+ mService = service;
mProc = app;
mResult = result;
CharSequence name;
@@ -86,7 +89,7 @@
private final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
- synchronized (mProc) {
+ synchronized (mService) {
if (mProc != null && mProc.crashDialog == AppErrorDialog.this) {
mProc.crashDialog = null;
}
diff --git a/services/java/com/android/server/am/StrictModeViolationDialog.java b/services/java/com/android/server/am/StrictModeViolationDialog.java
index fe76d18..35d50a1 100644
--- a/services/java/com/android/server/am/StrictModeViolationDialog.java
+++ b/services/java/com/android/server/am/StrictModeViolationDialog.java
@@ -28,6 +28,7 @@
class StrictModeViolationDialog extends BaseErrorDialog {
private final static String TAG = "StrictModeViolationDialog";
+ private final ActivityManagerService mService;
private final AppErrorResult mResult;
private final ProcessRecord mProc;
@@ -39,11 +40,13 @@
// dialog
static final long DISMISS_TIMEOUT = 1000 * 60 * 1;
- public StrictModeViolationDialog(Context context, AppErrorResult result, ProcessRecord app) {
+ public StrictModeViolationDialog(Context context, ActivityManagerService service,
+ AppErrorResult result, ProcessRecord app) {
super(context);
Resources res = context.getResources();
+ mService = service;
mProc = app;
mResult = result;
CharSequence name;
@@ -83,7 +86,7 @@
private final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
- synchronized (mProc) {
+ synchronized (mService) {
if (mProc != null && mProc.crashDialog == StrictModeViolationDialog.this) {
mProc.crashDialog = null;
}
diff --git a/services/java/com/android/server/am/UserStartedState.java b/services/java/com/android/server/am/UserStartedState.java
index 3f3ed85..50c8553 100644
--- a/services/java/com/android/server/am/UserStartedState.java
+++ b/services/java/com/android/server/am/UserStartedState.java
@@ -32,12 +32,17 @@
= new ArrayList<IStopUserCallback>();
public int mState = STATE_BOOTING;
+ public boolean switching;
+ public boolean initializing;
public UserStartedState(UserHandle handle, boolean initial) {
mHandle = handle;
}
void dump(String prefix, PrintWriter pw) {
- pw.print(prefix); pw.print("mState="); pw.println(mState);
+ pw.print(prefix); pw.print("mState="); pw.print(mState);
+ if (switching) pw.print(" SWITCHING");
+ if (initializing) pw.print(" INITIALIZING");
+ pw.println();
}
}
diff --git a/services/java/com/android/server/dreams/DreamController.java b/services/java/com/android/server/dreams/DreamController.java
index 81c80187..6db495a 100644
--- a/services/java/com/android/server/dreams/DreamController.java
+++ b/services/java/com/android/server/dreams/DreamController.java
@@ -25,7 +25,7 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.IBinder.DeathRecipient;
-import android.service.dreams.Dream;
+import android.service.dreams.DreamService;
import android.service.dreams.IDreamService;
import android.util.Slog;
import android.view.IWindowManager;
@@ -48,11 +48,13 @@
private final Listener mListener;
private final IWindowManager mIWindowManager;
- private final Intent mDreamingStartedIntent = new Intent(Dream.ACTION_DREAMING_STARTED)
+ private final Intent mDreamingStartedIntent = new Intent(Intent.ACTION_DREAMING_STARTED)
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- private final Intent mDreamingStoppedIntent = new Intent(Dream.ACTION_DREAMING_STOPPED)
+ private final Intent mDreamingStoppedIntent = new Intent(Intent.ACTION_DREAMING_STOPPED)
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ private final Intent mCloseNotificationShadeIntent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+
private DreamRecord mCurrentDream;
public DreamController(Context context, Handler handler, Listener listener) {
@@ -81,6 +83,9 @@
public void startDream(Binder token, ComponentName name, boolean isTest, int userId) {
stopDream();
+ // Close the notification shade
+ mContext.sendBroadcast(mCloseNotificationShadeIntent);
+
Slog.i(TAG, "Starting dream: name=" + name + ", isTest=" + isTest + ", userId=" + userId);
mCurrentDream = new DreamRecord(token, name, isTest, userId);
@@ -93,8 +98,7 @@
return;
}
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.addCategory(Dream.CATEGORY_DREAM);
+ Intent intent = new Intent(DreamService.SERVICE_INTERFACE);
intent.setComponent(name);
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
try {
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 6accb39..1eafd9c 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -5614,7 +5614,7 @@
int flags, String installerPackageName, Uri verificationURI,
ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
VerificationParams verificationParams = new VerificationParams(verificationURI, null, null,
- manifestDigest);
+ VerificationParams.NO_UID, manifestDigest);
installPackageWithVerificationAndEncryption(packageURI, observer, flags,
installerPackageName, verificationParams, encryptionParams);
}
@@ -6438,6 +6438,10 @@
verification.putExtra(Intent.EXTRA_REFERRER,
verificationParams.getReferrer());
}
+ if (verificationParams.getOriginatingUid() >= 0) {
+ verification.putExtra(Intent.EXTRA_ORIGINATING_UID,
+ verificationParams.getOriginatingUid());
+ }
if (verificationParams.getInstallerUid() >= 0) {
verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
verificationParams.getInstallerUid());
diff --git a/services/java/com/android/server/pm/PackageSettingBase.java b/services/java/com/android/server/pm/PackageSettingBase.java
index d8f7345..6a363a8 100644
--- a/services/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/java/com/android/server/pm/PackageSettingBase.java
@@ -20,6 +20,7 @@
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageUserState;
import android.content.pm.UserInfo;
import android.util.SparseArray;
@@ -64,7 +65,8 @@
boolean permissionsFixed;
boolean haveGids;
- private static final PackageUserState DEFAULT_USER_STATE = new PackageUserState();
+ private static final PackageUserState DEFAULT_USER_STATE = new PackageUserState(false);
+ private static final PackageUserState DEFAULT_SYSTEM_USER_STATE = new PackageUserState(true);
// Whether this package is currently stopped, thus can not be
// started until explicitly launched by the user.
@@ -174,7 +176,7 @@
private PackageUserState modifyUserState(int userId) {
PackageUserState state = userState.get(userId);
if (state == null) {
- state = new PackageUserState();
+ state = new PackageUserState((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0);
userState.put(userId, state);
}
return state;
@@ -182,7 +184,11 @@
public PackageUserState readUserState(int userId) {
PackageUserState state = userState.get(userId);
- return state != null ? state : DEFAULT_USER_STATE;
+ if (state != null) {
+ return state;
+ }
+ return ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0)
+ ? DEFAULT_SYSTEM_USER_STATE : DEFAULT_USER_STATE;
}
void setEnabled(int state, int userId) {
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 2fb853a..bdf5044 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -2609,10 +2609,11 @@
pw.print(" installerPackageName="); pw.println(ps.installerPackageName);
}
pw.print(" signatures="); pw.println(ps.signatures);
- pw.print(" permissionsFixed="); pw.println(ps.permissionsFixed);
- pw.print(" haveGids="); pw.println(ps.haveGids);
+ pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
+ pw.print(" haveGids="); pw.print(ps.haveGids);
+ pw.print(" installStatus="); pw.println(ps.installStatus);
pw.print(" pkgFlags="); printFlags(pw, ps.pkgFlags, FLAG_DUMP_SPEC);
- pw.print(" installStatus="); pw.println(ps.installStatus);
+ pw.println();
for (UserInfo user : users) {
pw.print(" User "); pw.print(user.id); pw.print(": ");
pw.print(" installed=");
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
index 2edc700..a0326c5 100644
--- a/services/java/com/android/server/pm/UserManagerService.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -16,9 +16,6 @@
package com.android.server.pm;
-import static android.os.ParcelFileDescriptor.MODE_CREATE;
-import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
-
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
@@ -35,7 +32,6 @@
import android.os.Environment;
import android.os.FileUtils;
import android.os.IUserManager;
-import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -74,6 +70,7 @@
private static final String ATTR_LAST_LOGGED_IN_TIME = "lastLoggedIn";
private static final String ATTR_SERIAL_NO = "serialNumber";
private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
+ private static final String ATTR_PARTIAL = "partial";
private static final String TAG_USERS = "users";
private static final String TAG_USER = "user";
@@ -132,24 +129,40 @@
private UserManagerService(Context context, PackageManagerService pm,
Object installLock, Object packagesLock,
File dataDir, File baseUserPath) {
- synchronized (UserManagerService.class) {
- mContext = context;
- mPm = pm;
- mInstallLock = installLock;
- mPackagesLock = packagesLock;
- mUsersDir = new File(dataDir, USER_INFO_DIR);
- mUsersDir.mkdirs();
- // Make zeroth user directory, for services to migrate their files to that location
- File userZeroDir = new File(mUsersDir, "0");
- userZeroDir.mkdirs();
- mBaseUserPath = baseUserPath;
- FileUtils.setPermissions(mUsersDir.toString(),
- FileUtils.S_IRWXU|FileUtils.S_IRWXG
- |FileUtils.S_IROTH|FileUtils.S_IXOTH,
- -1, -1);
- mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
- readUserList();
- sInstance = this;
+ mContext = context;
+ mPm = pm;
+ mInstallLock = installLock;
+ mPackagesLock = packagesLock;
+ synchronized (mInstallLock) {
+ synchronized (mPackagesLock) {
+ mUsersDir = new File(dataDir, USER_INFO_DIR);
+ mUsersDir.mkdirs();
+ // Make zeroth user directory, for services to migrate their files to that location
+ File userZeroDir = new File(mUsersDir, "0");
+ userZeroDir.mkdirs();
+ mBaseUserPath = baseUserPath;
+ FileUtils.setPermissions(mUsersDir.toString(),
+ FileUtils.S_IRWXU|FileUtils.S_IRWXG
+ |FileUtils.S_IROTH|FileUtils.S_IXOTH,
+ -1, -1);
+ mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
+ readUserListLocked();
+ // Prune out any partially created users.
+ ArrayList<UserInfo> partials = new ArrayList<UserInfo>();
+ for (int i = 0; i < mUsers.size(); i++) {
+ UserInfo ui = mUsers.valueAt(i);
+ if (ui.partial && i != 0) {
+ partials.add(ui);
+ }
+ }
+ for (int i = 0; i < partials.size(); i++) {
+ UserInfo ui = partials.get(i);
+ Slog.w(LOG_TAG, "Removing partially created user #" + i
+ + " (name=" + ui.name + ")");
+ removeUserStateLocked(ui.id);
+ }
+ sInstance = this;
+ }
}
}
@@ -159,8 +172,12 @@
synchronized (mPackagesLock) {
ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
for (int i = 0; i < mUsers.size(); i++) {
- if (!excludeDying || !mRemovingUserIds.contains(mUsers.keyAt(i))) {
- users.add(mUsers.valueAt(i));
+ UserInfo ui = mUsers.valueAt(i);
+ if (ui.partial) {
+ continue;
+ }
+ if (!excludeDying || !mRemovingUserIds.contains(ui.id)) {
+ users.add(ui);
}
}
return users;
@@ -179,7 +196,12 @@
* Should be locked on mUsers before calling this.
*/
private UserInfo getUserInfoLocked(int userId) {
- return mUsers.get(userId);
+ UserInfo ui = mUsers.get(userId);
+ if (ui != null && ui.partial) {
+ Slog.w(LOG_TAG, "getUserInfo: unknown user #" + userId);
+ return null;
+ }
+ return ui;
}
public boolean exists(int userId) {
@@ -191,14 +213,22 @@
@Override
public void setUserName(int userId, String name) {
checkManageUsersPermission("rename users");
+ boolean changed = false;
synchronized (mPackagesLock) {
UserInfo info = mUsers.get(userId);
+ if (info == null || info.partial) {
+ Slog.w(LOG_TAG, "setUserName: unknown user #" + userId);
+ return;
+ }
if (name != null && !name.equals(info.name)) {
info.name = name;
writeUserLocked(info);
+ changed = true;
}
}
- sendUserInfoChangedBroadcast(userId);
+ if (changed) {
+ sendUserInfoChangedBroadcast(userId);
+ }
}
@Override
@@ -206,7 +236,10 @@
checkManageUsersPermission("update users");
synchronized (mPackagesLock) {
UserInfo info = mUsers.get(userId);
- if (info == null) return;
+ if (info == null || info.partial) {
+ Slog.w(LOG_TAG, "setUserIcon: unknown user #" + userId);
+ return;
+ }
writeBitmapLocked(info, bitmap);
writeUserLocked(info);
}
@@ -225,7 +258,13 @@
checkManageUsersPermission("read users");
synchronized (mPackagesLock) {
UserInfo info = mUsers.get(userId);
- if (info == null || info.iconPath == null) return null;
+ if (info == null || info.partial) {
+ Slog.w(LOG_TAG, "getUserIcon: unknown user #" + userId);
+ return null;
+ }
+ if (info.iconPath == null) {
+ return null;
+ }
return BitmapFactory.decodeFile(info.iconPath);
}
}
@@ -239,7 +278,7 @@
// Erase any guest user that currently exists
for (int i = 0; i < mUsers.size(); i++) {
UserInfo user = mUsers.valueAt(i);
- if (user.isGuest()) {
+ if (!user.partial && user.isGuest()) {
if (!enable) {
removeUser(user.id);
}
@@ -271,7 +310,10 @@
checkManageUsersPermission("makeInitialized");
synchronized (mPackagesLock) {
UserInfo info = mUsers.get(userId);
- if (info != null && (info.flags&UserInfo.FLAG_INITIALIZED) == 0) {
+ if (info == null || info.partial) {
+ Slog.w(LOG_TAG, "makeInitialized: unknown user #" + userId);
+ }
+ if ((info.flags&UserInfo.FLAG_INITIALIZED) == 0) {
info.flags |= UserInfo.FLAG_INITIALIZED;
writeUserLocked(info);
}
@@ -453,6 +495,9 @@
if (userInfo.iconPath != null) {
serializer.attribute(null, ATTR_ICON_PATH, userInfo.iconPath);
}
+ if (userInfo.partial) {
+ serializer.attribute(null, ATTR_PARTIAL, "true");
+ }
serializer.startTag(null, TAG_NAME);
serializer.text(userInfo.name);
@@ -516,6 +561,7 @@
String iconPath = null;
long creationTime = 0L;
long lastLoggedInTime = 0L;
+ boolean partial = false;
FileInputStream fis = null;
try {
@@ -546,6 +592,10 @@
iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH);
creationTime = readLongAttribute(parser, ATTR_CREATION_TIME, 0);
lastLoggedInTime = readLongAttribute(parser, ATTR_LAST_LOGGED_IN_TIME, 0);
+ String valueString = parser.getAttributeValue(null, ATTR_PARTIAL);
+ if ("true".equals(valueString)) {
+ partial = true;
+ }
while ((type = parser.next()) != XmlPullParser.START_TAG
&& type != XmlPullParser.END_DOCUMENT) {
@@ -562,6 +612,7 @@
userInfo.serialNumber = serialNumber;
userInfo.creationTime = creationTime;
userInfo.lastLoggedInTime = lastLoggedInTime;
+ userInfo.partial = partial;
return userInfo;
} catch (IOException ioe) {
@@ -613,11 +664,14 @@
userInfo.serialNumber = mNextSerialNumber++;
long now = System.currentTimeMillis();
userInfo.creationTime = (now > EPOCH_PLUS_30_YEARS) ? now : 0;
+ userInfo.partial = true;
mUsers.put(userId, userInfo);
writeUserListLocked();
writeUserLocked(userInfo);
- updateUserIdsLocked();
mPm.createNewUserLILPw(userId, userPath);
+ userInfo.partial = false;
+ writeUserLocked(userInfo);
+ updateUserIdsLocked();
}
}
if (userInfo != null) {
@@ -670,19 +724,7 @@
void finishRemoveUser(int userHandle) {
synchronized (mInstallLock) {
synchronized (mPackagesLock) {
- // Cleanup package manager settings
- mPm.cleanUpUserLILPw(userHandle);
-
- // Remove this user from the list
- mUsers.remove(userHandle);
- mRemovingUserIds.remove(userHandle);
- // Remove user file
- AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + ".xml"));
- userFile.delete();
- // Update the user list
- writeUserListLocked();
- updateUserIdsLocked();
- removeDirectoryRecursive(Environment.getUserSystemDirectory(userHandle));
+ removeUserStateLocked(userHandle);
}
}
@@ -698,6 +740,22 @@
}
}
+ private void removeUserStateLocked(int userHandle) {
+ // Cleanup package manager settings
+ mPm.cleanUpUserLILPw(userHandle);
+
+ // Remove this user from the list
+ mUsers.remove(userHandle);
+ mRemovingUserIds.remove(userHandle);
+ // Remove user file
+ AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + ".xml"));
+ userFile.delete();
+ // Update the user list
+ writeUserListLocked();
+ updateUserIdsLocked();
+ removeDirectoryRecursive(Environment.getUserSystemDirectory(userHandle));
+ }
+
private void removeDirectoryRecursive(File parent) {
if (parent.isDirectory()) {
String[] files = parent.list();
@@ -732,9 +790,17 @@
* Caches the list of user ids in an array, adjusting the array size when necessary.
*/
private void updateUserIdsLocked() {
- int[] newUsers = new int[mUsers.size()];
+ int num = 0;
for (int i = 0; i < mUsers.size(); i++) {
- newUsers[i] = mUsers.keyAt(i);
+ if (!mUsers.valueAt(i).partial) {
+ num++;
+ }
+ }
+ int[] newUsers = new int[num];
+ for (int i = 0; i < mUsers.size(); i++) {
+ if (!mUsers.valueAt(i).partial) {
+ newUsers[i] = mUsers.keyAt(i);
+ }
}
mUserIds = newUsers;
}
@@ -747,7 +813,11 @@
synchronized (mPackagesLock) {
UserInfo user = mUsers.get(userId);
long now = System.currentTimeMillis();
- if (user != null && now > EPOCH_PLUS_30_YEARS) {
+ if (user == null || user.partial) {
+ Slog.w(LOG_TAG, "userForeground: unknown user #" + userId);
+ return;
+ }
+ if (now > EPOCH_PLUS_30_YEARS) {
user.lastLoggedInTime = now;
writeUserLocked(user);
}
@@ -793,7 +863,9 @@
UserInfo user = mUsers.valueAt(i);
if (user == null) continue;
pw.print(" "); pw.print(user);
- pw.println(mRemovingUserIds.contains(mUsers.keyAt(i)) ? " <removing> " : "");
+ if (mRemovingUserIds.contains(mUsers.keyAt(i))) pw.print(" <removing> ");
+ if (user.partial) pw.print(" <partial>");
+ pw.println();
pw.print(" Created: ");
if (user.creationTime == 0) {
pw.println("<unknown>");
diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java
index ad138e8..c2d47e5 100644
--- a/services/java/com/android/server/power/PowerManagerService.java
+++ b/services/java/com/android/server/power/PowerManagerService.java
@@ -51,7 +51,6 @@
import android.os.UserHandle;
import android.os.WorkSource;
import android.provider.Settings;
-import android.service.dreams.Dream;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
@@ -363,8 +362,8 @@
mContext.registerReceiver(new BootCompletedReceiver(), filter, null, mHandler);
filter = new IntentFilter();
- filter.addAction(Dream.ACTION_DREAMING_STARTED);
- filter.addAction(Dream.ACTION_DREAMING_STOPPED);
+ filter.addAction(Intent.ACTION_DREAMING_STARTED);
+ filter.addAction(Intent.ACTION_DREAMING_STOPPED);
mContext.registerReceiver(new DreamReceiver(), filter, null, mHandler);
filter = new IntentFilter();
@@ -1644,12 +1643,6 @@
&& mMaximumScreenOffTimeoutFromDeviceAdmin < Integer.MAX_VALUE;
}
- @Override // Binder call
- public void preventScreenOn(boolean prevent) {
- // TODO Auto-generated method stub
- // Only used by phone app, delete this
- }
-
/**
* Used by the phone application to make the attention LED flash when ringing.
*/
diff --git a/services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java b/services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
index e07230d..4480151 100644
--- a/services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
+++ b/services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
@@ -126,7 +126,7 @@
CertificateFactory cf = CertificateFactory.getInstance("X.509");
return (X509Certificate) cf.generateCertificate(istream);
} catch (CertificateException e) {
- throw new IllegalStateException("Got malformed certificate from settings, ignoring", e);
+ throw new IllegalStateException("Got malformed certificate from settings, ignoring");
}
}
@@ -167,7 +167,7 @@
String strVersion = IoUtils.readFileAsString(updateVersion.getCanonicalPath()).trim();
return Integer.parseInt(strVersion);
} catch (IOException e) {
- Slog.i(TAG, "Couldn't find current metadata, assuming first update", e);
+ Slog.i(TAG, "Couldn't find current metadata, assuming first update");
return 0;
}
}
@@ -181,7 +181,7 @@
try {
return IoUtils.readFileAsString(updateContent.getCanonicalPath()).trim();
} catch (IOException e) {
- Slog.i(TAG, "Failed to read current content, assuming first update!", e);
+ Slog.i(TAG, "Failed to read current content, assuming first update!");
return null;
}
}
diff --git a/services/java/com/android/server/updates/SmsShortCodesInstallReceiver.java b/services/java/com/android/server/updates/SmsShortCodesInstallReceiver.java
new file mode 100644
index 0000000..0f14f57
--- /dev/null
+++ b/services/java/com/android/server/updates/SmsShortCodesInstallReceiver.java
@@ -0,0 +1,24 @@
+/*
+ * 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.updates;
+
+public class SmsShortCodesInstallReceiver extends ConfigUpdateInstallReceiver {
+
+ public SmsShortCodesInstallReceiver() {
+ super("/data/misc/sms/", "codes", "metadata/", "version");
+ }
+}
diff --git a/services/jni/com_android_server_power_PowerManagerService.cpp b/services/jni/com_android_server_power_PowerManagerService.cpp
index 38af38d..dcc2b58 100644
--- a/services/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/jni/com_android_server_power_PowerManagerService.cpp
@@ -183,14 +183,16 @@
gPowerModule->setInteractive(gPowerModule, true);
}
+ const sp<IBinder>& display = s->getBuiltInDisplay(0); // TODO: support multiple displays
{
ALOGD_IF_SLOW(100, "Excessive delay in unblank() while turning screen on");
- s->unblank();
+ s->unblank(display);
}
} else {
+ const sp<IBinder>& display = s->getBuiltInDisplay(0); // TODO: support multiple displays
{
ALOGD_IF_SLOW(100, "Excessive delay in blank() while turning screen off");
- s->blank();
+ s->blank(display);
}
if (gPowerModule) {
diff --git a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
index 3b6e107..50f98b8 100644
--- a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
@@ -284,25 +284,39 @@
}, 3000);
}
},
- new Test("Expand") {
+ new Test("Expand notifications") {
public void run() {
- mStatusBarManager.expandNotifications();
+ mStatusBarManager.expandNotificationsPanel();
}
},
- new Test("Expand in 3 sec.") {
+ new Test(" ... in 3 sec.") {
public void run() {
mHandler.postDelayed(new Runnable() {
public void run() {
- mStatusBarManager.expandNotifications();
+ mStatusBarManager.expandNotificationsPanel();
}
}, 3000);
}
},
- new Test("Collapse in 3 sec.") {
+ new Test("Expand settings") {
+ public void run() {
+ mStatusBarManager.expandSettingsPanel();
+ }
+ },
+ new Test(" ... in 3 sec.") {
public void run() {
mHandler.postDelayed(new Runnable() {
public void run() {
- mStatusBarManager.collapseNotifications();
+ mStatusBarManager.expandSettingsPanel();
+ }
+ }, 3000);
+ }
+ },
+ new Test("Collapse panels in 3 sec.") {
+ public void run() {
+ mHandler.postDelayed(new Runnable() {
+ public void run() {
+ mStatusBarManager.collapsePanels();
}
}, 3000);
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index 0cf0f21..e882440 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -65,11 +65,6 @@
}
@Override
- public void preventScreenOn(boolean arg0) throws RemoteException {
- // pass for now.
- }
-
- @Override
public void reboot(String arg0) throws RemoteException {
// pass for now.
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 2e6aa88..ef57e63 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -1231,10 +1231,17 @@
mGroup.getNetworkName()));
}
- mWifiNative.setP2pGroupIdle(mGroup.getInterface(), GROUP_IDLE_TIME_S);
if (mGroup.isGroupOwner()) {
+ /* Setting an idle time out on GO causes issues with certain scenarios
+ * on clients where it can be off-channel for longer and with the power
+ * save modes used.
+ *
+ * TODO: Verify multi-channel scenarios and supplicant behavior are
+ * better before adding a time out in future
+ */
startDhcpServer(mGroup.getInterface());
} else {
+ mWifiNative.setP2pGroupIdle(mGroup.getInterface(), GROUP_IDLE_TIME_S);
mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(mContext,
P2pStateMachine.this, mGroup.getInterface());
mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);