Merge "Use a larger scaling span for larger screen devices." into jb-mr1-dev
diff --git a/api/current.txt b/api/current.txt
index f0148b4..4abcaee 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -62,21 +62,17 @@
field public static final java.lang.String INJECT_EVENTS = "android.permission.INJECT_EVENTS";
field public static final java.lang.String INSTALL_LOCATION_PROVIDER = "android.permission.INSTALL_LOCATION_PROVIDER";
field public static final java.lang.String INSTALL_PACKAGES = "android.permission.INSTALL_PACKAGES";
- field public static final java.lang.String INTERACT_ACROSS_USERS = "android.permission.INTERACT_ACROSS_USERS";
field public static final java.lang.String INTERNAL_SYSTEM_WINDOW = "android.permission.INTERNAL_SYSTEM_WINDOW";
field public static final java.lang.String INTERNET = "android.permission.INTERNET";
field public static final java.lang.String KILL_BACKGROUND_PROCESSES = "android.permission.KILL_BACKGROUND_PROCESSES";
field public static final java.lang.String MANAGE_ACCOUNTS = "android.permission.MANAGE_ACCOUNTS";
field public static final java.lang.String MANAGE_APP_TOKENS = "android.permission.MANAGE_APP_TOKENS";
- field public static final java.lang.String MANAGE_USERS = "android.permission.MANAGE_USERS";
field public static final java.lang.String MASTER_CLEAR = "android.permission.MASTER_CLEAR";
field public static final java.lang.String MODIFY_AUDIO_SETTINGS = "android.permission.MODIFY_AUDIO_SETTINGS";
field public static final java.lang.String MODIFY_PHONE_STATE = "android.permission.MODIFY_PHONE_STATE";
field public static final java.lang.String MOUNT_FORMAT_FILESYSTEMS = "android.permission.MOUNT_FORMAT_FILESYSTEMS";
field public static final java.lang.String MOUNT_UNMOUNT_FILESYSTEMS = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS";
- field public static final java.lang.String NET_TUNNELING = "android.permission.NET_TUNNELING";
field public static final java.lang.String NFC = "android.permission.NFC";
- field public static final java.lang.String PACKAGE_VERIFICATION_AGENT = "android.permission.PACKAGE_VERIFICATION_AGENT";
field public static final deprecated java.lang.String PERSISTENT_ACTIVITY = "android.permission.PERSISTENT_ACTIVITY";
field public static final java.lang.String PROCESS_OUTGOING_CALLS = "android.permission.PROCESS_OUTGOING_CALLS";
field public static final java.lang.String READ_CALENDAR = "android.permission.READ_CALENDAR";
@@ -3901,11 +3897,12 @@
method public static android.app.PendingIntent getActivity(android.content.Context, int, android.content.Intent, int);
method public static android.app.PendingIntent getActivity(android.content.Context, int, android.content.Intent, int, android.os.Bundle);
method public static android.app.PendingIntent getBroadcast(android.content.Context, int, android.content.Intent, int);
+ method public java.lang.String getCreatorPackage();
+ method public int getCreatorUid();
+ method public android.os.UserHandle getCreatorUserHandle();
method public android.content.IntentSender getIntentSender();
method public static android.app.PendingIntent getService(android.content.Context, int, android.content.Intent, int);
- method public java.lang.String getTargetPackage();
- method public int getTargetUid();
- method public android.os.UserHandle getTargetUserHandle();
+ method public deprecated java.lang.String getTargetPackage();
method public static android.app.PendingIntent readPendingIntentOrNullFromParcel(android.os.Parcel);
method public void send() throws android.app.PendingIntent.CanceledException;
method public void send(int) throws android.app.PendingIntent.CanceledException;
@@ -6060,9 +6057,10 @@
public class IntentSender implements android.os.Parcelable {
method public int describeContents();
- method public java.lang.String getTargetPackage();
- method public int getTargetUid();
- method public android.os.UserHandle getTargetUserHandle();
+ method public java.lang.String getCreatorPackage();
+ method public int getCreatorUid();
+ method public android.os.UserHandle getCreatorUserHandle();
+ method public deprecated java.lang.String getTargetPackage();
method public static android.content.IntentSender readIntentSenderOrNullFromParcel(android.os.Parcel);
method public void sendIntent(android.content.Context, int, android.content.Intent, android.content.IntentSender.OnFinished, android.os.Handler) throws android.content.IntentSender.SendIntentException;
method public void sendIntent(android.content.Context, int, android.content.Intent, android.content.IntentSender.OnFinished, android.os.Handler, java.lang.String) throws android.content.IntentSender.SendIntentException;
@@ -6705,17 +6703,6 @@
field public java.lang.String packageName;
}
- public class PackageUserState {
- ctor public PackageUserState();
- ctor public PackageUserState(android.content.pm.PackageUserState);
- field public java.util.HashSet disabledComponents;
- field public int enabled;
- field public java.util.HashSet enabledComponents;
- field public boolean installed;
- field public boolean notLaunched;
- field public boolean stopped;
- }
-
public class PathPermission extends android.os.PatternMatcher {
ctor public PathPermission(java.lang.String, int, java.lang.String, java.lang.String);
ctor public PathPermission(android.os.Parcel);
@@ -16594,7 +16581,6 @@
public class UserManager {
method public java.lang.String getUserName();
- method public boolean supportsMultipleUsers();
}
public abstract class Vibrator {
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index a3c1838..e7cea57 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -32,8 +32,8 @@
/**
* A description of an Intent and target action to perform with it. Instances
- * of this class are created with {@link #getActivity},
- * {@link #getBroadcast}, {@link #getService}; the returned object can be
+ * of this class are created with {@link #getActivity}, {@link #getActivities},
+ * {@link #getBroadcast}, and {@link #getService}; the returned object can be
* handed to other applications so that they can perform the action you
* described on your behalf at a later time.
*
@@ -54,6 +54,34 @@
* categories, and components, and same flags), it will receive a PendingIntent
* representing the same token if that is still valid, and can thus call
* {@link #cancel} to remove it.
+ *
+ * <p>Because of this behavior, it is important to know when two Intents
+ * are considered to be the same for purposes of retrieving a PendingIntent.
+ * A common mistake people make is to create multiple PendingIntent objects
+ * with Intents that only vary in their "extra" contents, expecting to get
+ * a different PendingIntent each time. This does <em>not</em> happen. The
+ * parts of the Intent that are used for matching are the same ones defined
+ * by {@link Intent#filterEquals(Intent) Intent.filterEquals}. If you use two
+ * Intent objects that are equivalent as per
+ * {@link Intent#filterEquals(Intent) Intent.filterEquals}, then you will get
+ * the same PendingIntent for both of them.
+ *
+ * <p>There are two typical ways to deal with this.
+ *
+ * <p>If you truly need multiple distinct PendingIntent objects active at
+ * the same time (such as to use as two notifications that are both shown
+ * at the same time), then you will need to ensure there is something that
+ * is different about them to associate them with different PendingIntents.
+ * This may be any of the Intent attributes considered by
+ * {@link Intent#filterEquals(Intent) Intent.filterEquals}, or different
+ * request code integers supplied to {@link #getActivity}, {@link #getActivities},
+ * {@link #getBroadcast}, or {@link #getService}.
+ *
+ * <p>If you only need one PendingIntent active at a time for any of the
+ * Intents you will use, then you can alternatively use the flags
+ * {@link #FLAG_CANCEL_CURRENT} or {@link #FLAG_UPDATE_CURRENT} to either
+ * cancel or modify whatever current PendingIntent is associated with the
+ * Intent you are supplying.
*/
public final class PendingIntent implements Parcelable {
private final IIntentSender mTarget;
@@ -622,6 +650,20 @@
}
/**
+ * @deprecated Renamed to {@link #getCreatorPackage()}.
+ */
+ @Deprecated
+ public String getTargetPackage() {
+ try {
+ return ActivityManagerNative.getDefault()
+ .getPackageForIntentSender(mTarget);
+ } catch (RemoteException e) {
+ // Should never happen.
+ return null;
+ }
+ }
+
+ /**
* Return the package name of the application that created this
* PendingIntent, that is the identity under which you will actually be
* sending the Intent. The returned string is supplied by the system, so
@@ -630,7 +672,7 @@
* @return The package name of the PendingIntent, or null if there is
* none associated with it.
*/
- public String getTargetPackage() {
+ public String getCreatorPackage() {
try {
return ActivityManagerNative.getDefault()
.getPackageForIntentSender(mTarget);
@@ -649,7 +691,7 @@
* @return The uid of the PendingIntent, or -1 if there is
* none associated with it.
*/
- public int getTargetUid() {
+ public int getCreatorUid() {
try {
return ActivityManagerNative.getDefault()
.getUidForIntentSender(mTarget);
@@ -670,7 +712,7 @@
* @return The user handle of the PendingIntent, or null if there is
* none associated with it.
*/
- public UserHandle getTargetUserHandle() {
+ public UserHandle getCreatorUserHandle() {
try {
int uid = ActivityManagerNative.getDefault()
.getUidForIntentSender(mTarget);
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 51a81c5..84a447f 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -117,7 +117,7 @@
private OnClickHandler mOnClickHandler;
public AppWidgetHost(Context context, int hostId) {
- this(context, hostId, null, Looper.getMainLooper());
+ this(context, hostId, null, context.getMainLooper());
}
/**
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index ece8841..cd1e882 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1219,9 +1219,16 @@
public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
ContentObserver observer)
{
+ registerContentObserver(uri, notifyForDescendents, observer, UserHandle.myUserId());
+ }
+
+ /** @hide - designated user version */
+ public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
+ ContentObserver observer, int userHandle)
+ {
try {
getContentService().registerContentObserver(uri, notifyForDescendents,
- observer.getContentObserver());
+ observer.getContentObserver(), userHandle);
} catch (RemoteException e) {
}
}
@@ -1276,10 +1283,21 @@
* @see #requestSync(android.accounts.Account, String, android.os.Bundle)
*/
public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
+ notifyChange(uri, observer, syncToNetwork, UserHandle.myUserId());
+ }
+
+ /**
+ * Notify registered observers within the designated user(s) that a row was updated.
+ *
+ * @hide
+ */
+ public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork,
+ int userHandle) {
try {
getContentService().notifyChange(
uri, observer == null ? null : observer.getContentObserver(),
- observer != null && observer.deliverSelfNotifications(), syncToNetwork);
+ observer != null && observer.deliverSelfNotifications(), syncToNetwork,
+ userHandle);
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/content/ContentService.java b/core/java/android/content/ContentService.java
index 472fe94..0f6488a 100644
--- a/core/java/android/content/ContentService.java
+++ b/core/java/android/content/ContentService.java
@@ -17,6 +17,7 @@
package android.content;
import android.accounts.Account;
+import android.app.ActivityManager;
import android.database.IContentObserver;
import android.database.sqlite.SQLiteException;
import android.net.Uri;
@@ -33,6 +34,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -138,17 +140,47 @@
getSyncManager();
}
- public void registerContentObserver(Uri uri, boolean notifyForDescendents,
- IContentObserver observer) {
+ /**
+ * Register a content observer tied to a specific user's view of the provider.
+ * @param userHandle the user whose view of the provider is to be observed. May be
+ * the calling user without requiring any permission, otherwise the caller needs to
+ * hold the INTERACT_ACROSS_USERS_FULL permission. Pseudousers USER_ALL and
+ * USER_CURRENT are properly handled; all other pseudousers are forbidden.
+ */
+ @Override
+ public void registerContentObserver(Uri uri, boolean notifyForDescendants,
+ IContentObserver observer, int userHandle) {
if (observer == null || uri == null) {
throw new IllegalArgumentException("You must pass a valid uri and observer");
}
- synchronized (mRootNode) {
- mRootNode.addObserverLocked(uri, observer, notifyForDescendents, mRootNode,
- Binder.getCallingUid(), Binder.getCallingPid());
- if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri +
- " with notifyForDescendents " + notifyForDescendents);
+
+ final int callingUser = UserHandle.getCallingUserId();
+ if (callingUser != userHandle) {
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ "no permission to observe other users' provider view");
}
+
+ if (userHandle < 0) {
+ if (userHandle == UserHandle.USER_CURRENT) {
+ userHandle = ActivityManager.getCurrentUser();
+ } else if (userHandle != UserHandle.USER_ALL) {
+ throw new InvalidParameterException("Bad user handle for registerContentObserver: "
+ + userHandle);
+ }
+ }
+
+ synchronized (mRootNode) {
+ mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode,
+ Binder.getCallingUid(), Binder.getCallingPid(), userHandle);
+ if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri +
+ " with notifyForDescendants " + notifyForDescendants);
+ }
+ }
+
+ public void registerContentObserver(Uri uri, boolean notifyForDescendants,
+ IContentObserver observer) {
+ registerContentObserver(uri, notifyForDescendants, observer,
+ UserHandle.getCallingUserId());
}
public void unregisterContentObserver(IContentObserver observer) {
@@ -161,14 +193,39 @@
}
}
+ /**
+ * Notify observers of a particular user's view of the provider.
+ * @param userHandle the user whose view of the provider is to be notified. May be
+ * the calling user without requiring any permission, otherwise the caller needs to
+ * hold the INTERACT_ACROSS_USERS_FULL permission. Pseudousers USER_ALL and
+ * USER_CURRENT are properly interpreted; no other pseudousers are allowed.
+ */
+ @Override
public void notifyChange(Uri uri, IContentObserver observer,
- boolean observerWantsSelfNotifications, boolean syncToNetwork) {
+ boolean observerWantsSelfNotifications, boolean syncToNetwork,
+ int userHandle) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Notifying update of " + uri + " from observer " + observer
- + ", syncToNetwork " + syncToNetwork);
+ Log.v(TAG, "Notifying update of " + uri + " for user " + userHandle
+ + " from observer " + observer + ", syncToNetwork " + syncToNetwork);
}
- int userId = UserHandle.getCallingUserId();
+ // Notify for any user other than the caller's own requires permission.
+ final int callingUserHandle = UserHandle.getCallingUserId();
+ if (userHandle != callingUserHandle) {
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ "no permission to notify other users");
+ }
+
+ // We passed the permission check; resolve pseudouser targets as appropriate
+ if (userHandle < 0) {
+ if (userHandle == UserHandle.USER_CURRENT) {
+ userHandle = ActivityManager.getCurrentUser();
+ } else if (userHandle != UserHandle.USER_ALL) {
+ throw new InvalidParameterException("Bad user handle for notifyChange: "
+ + userHandle);
+ }
+ }
+
// This makes it so that future permission checks will be in the context of this
// process rather than the caller's process. We will restore this before returning.
long identityToken = clearCallingIdentity();
@@ -176,7 +233,7 @@
ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
synchronized (mRootNode) {
mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications,
- calls);
+ userHandle, calls);
}
final int numCalls = calls.size();
for (int i=0; i<numCalls; i++) {
@@ -207,7 +264,7 @@
if (syncToNetwork) {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
- syncManager.scheduleLocalSync(null /* all accounts */, userId,
+ syncManager.scheduleLocalSync(null /* all accounts */, callingUserHandle,
uri.getAuthority());
}
}
@@ -216,6 +273,12 @@
}
}
+ public void notifyChange(Uri uri, IContentObserver observer,
+ boolean observerWantsSelfNotifications, boolean syncToNetwork) {
+ notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork,
+ UserHandle.getCallingUserId());
+ }
+
/**
* Hide this class since it is not part of api,
* but current unittest framework requires it to be public
@@ -543,16 +606,18 @@
public final IContentObserver observer;
public final int uid;
public final int pid;
- public final boolean notifyForDescendents;
+ public final boolean notifyForDescendants;
+ private final int userHandle;
private final Object observersLock;
public ObserverEntry(IContentObserver o, boolean n, Object observersLock,
- int _uid, int _pid) {
+ int _uid, int _pid, int _userHandle) {
this.observersLock = observersLock;
observer = o;
uid = _uid;
pid = _pid;
- notifyForDescendents = n;
+ userHandle = _userHandle;
+ notifyForDescendants = n;
try {
observer.asBinder().linkToDeath(this, 0);
} catch (RemoteException e) {
@@ -571,7 +636,8 @@
pidCounts.put(pid, pidCounts.get(pid)+1);
pw.print(prefix); pw.print(name); pw.print(": pid=");
pw.print(pid); pw.print(" uid=");
- pw.print(uid); pw.print(" target=");
+ pw.print(uid); pw.print(" user=");
+ pw.print(userHandle); pw.print(" target=");
pw.println(Integer.toHexString(System.identityHashCode(
observer != null ? observer.asBinder() : null)));
}
@@ -639,17 +705,21 @@
return uri.getPathSegments().size() + 1;
}
+ // Invariant: userHandle is either a hard user number or is USER_ALL
public void addObserverLocked(Uri uri, IContentObserver observer,
- boolean notifyForDescendents, Object observersLock, int uid, int pid) {
- addObserverLocked(uri, 0, observer, notifyForDescendents, observersLock, uid, pid);
+ boolean notifyForDescendants, Object observersLock,
+ int uid, int pid, int userHandle) {
+ addObserverLocked(uri, 0, observer, notifyForDescendants, observersLock,
+ uid, pid, userHandle);
}
private void addObserverLocked(Uri uri, int index, IContentObserver observer,
- boolean notifyForDescendents, Object observersLock, int uid, int pid) {
+ boolean notifyForDescendants, Object observersLock,
+ int uid, int pid, int userHandle) {
// If this is the leaf node add the observer
if (index == countUriSegments(uri)) {
- mObservers.add(new ObserverEntry(observer, notifyForDescendents, observersLock,
- uid, pid));
+ mObservers.add(new ObserverEntry(observer, notifyForDescendants, observersLock,
+ uid, pid, userHandle));
return;
}
@@ -662,8 +732,8 @@
for (int i = 0; i < N; i++) {
ObserverNode node = mChildren.get(i);
if (node.mName.equals(segment)) {
- node.addObserverLocked(uri, index + 1, observer, notifyForDescendents,
- observersLock, uid, pid);
+ node.addObserverLocked(uri, index + 1, observer, notifyForDescendants,
+ observersLock, uid, pid, userHandle);
return;
}
}
@@ -671,8 +741,8 @@
// No child found, create one
ObserverNode node = new ObserverNode(segment);
mChildren.add(node);
- node.addObserverLocked(uri, index + 1, observer, notifyForDescendents,
- observersLock, uid, pid);
+ node.addObserverLocked(uri, index + 1, observer, notifyForDescendants,
+ observersLock, uid, pid, userHandle);
}
public boolean removeObserverLocked(IContentObserver observer) {
@@ -705,37 +775,49 @@
}
private void collectMyObserversLocked(boolean leaf, IContentObserver observer,
- boolean observerWantsSelfNotifications, ArrayList<ObserverCall> calls) {
+ boolean observerWantsSelfNotifications, int targetUserHandle,
+ ArrayList<ObserverCall> calls) {
int N = mObservers.size();
IBinder observerBinder = observer == null ? null : observer.asBinder();
for (int i = 0; i < N; i++) {
ObserverEntry entry = mObservers.get(i);
- // Don't notify the observer if it sent the notification and isn't interesed
+ // Don't notify the observer if it sent the notification and isn't interested
// in self notifications
boolean selfChange = (entry.observer.asBinder() == observerBinder);
if (selfChange && !observerWantsSelfNotifications) {
continue;
}
- // Make sure the observer is interested in the notification
- if (leaf || (!leaf && entry.notifyForDescendents)) {
- calls.add(new ObserverCall(this, entry.observer, selfChange));
+ // Does this observer match the target user?
+ if (targetUserHandle == UserHandle.USER_ALL
+ || entry.userHandle == UserHandle.USER_ALL
+ || targetUserHandle == entry.userHandle) {
+ // Make sure the observer is interested in the notification
+ if (leaf || (!leaf && entry.notifyForDescendants)) {
+ calls.add(new ObserverCall(this, entry.observer, selfChange));
+ }
}
}
}
+ /**
+ * targetUserHandle is either a hard user handle or is USER_ALL
+ */
public void collectObserversLocked(Uri uri, int index, IContentObserver observer,
- boolean observerWantsSelfNotifications, ArrayList<ObserverCall> calls) {
+ boolean observerWantsSelfNotifications, int targetUserHandle,
+ ArrayList<ObserverCall> calls) {
String segment = null;
int segmentCount = countUriSegments(uri);
if (index >= segmentCount) {
// This is the leaf node, notify all observers
- collectMyObserversLocked(true, observer, observerWantsSelfNotifications, calls);
+ collectMyObserversLocked(true, observer, observerWantsSelfNotifications,
+ targetUserHandle, calls);
} else if (index < segmentCount){
segment = getUriSegment(uri, index);
- // Notify any observers at this level who are interested in descendents
- collectMyObserversLocked(false, observer, observerWantsSelfNotifications, calls);
+ // Notify any observers at this level who are interested in descendants
+ collectMyObserversLocked(false, observer, observerWantsSelfNotifications,
+ targetUserHandle, calls);
}
int N = mChildren.size();
@@ -744,7 +826,7 @@
if (segment == null || node.mName.equals(segment)) {
// We found the child,
node.collectObserversLocked(uri, index + 1,
- observer, observerWantsSelfNotifications, calls);
+ observer, observerWantsSelfNotifications, targetUserHandle, calls);
if (segment != null) {
break;
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 7438ba8..161670f 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -856,8 +856,10 @@
public abstract void startActivity(Intent intent);
/**
- * Same as {@link #startActivity(Intent)}, but for a specific user. It requires holding
- * the {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission.
+ * Version of {@link #startActivity(Intent)} that allows you to specify the
+ * user the activity will be started for. This is not available to applications
+ * that are not pre-installed on the system image. Using it requires holding
+ * the INTERACT_ACROSS_USERS_FULL permission.
* @param intent The description of the activity to start.
* @param user The UserHandle of the user to start this activity for.
* @throws ActivityNotFoundException
@@ -895,8 +897,10 @@
public abstract void startActivity(Intent intent, Bundle options);
/**
- * Same as {@link #startActivity(Intent, Bundle)}, but for a specific user. It requires holding
- * the {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission.
+ * Version of {@link #startActivity(Intent, Bundle)} that allows you to specify the
+ * user the activity will be started for. This is not available to applications
+ * that are not pre-installed on the system image. Using it requires holding
+ * the INTERACT_ACROSS_USERS_FULL permission.
* @param intent The description of the activity to start.
* @param options Additional options for how the Activity should be started.
* May be null if there are no options. See {@link android.app.ActivityOptions}
@@ -1118,10 +1122,10 @@
Bundle initialExtras);
/**
- * Same as {@link #sendBroadcast(Intent)}, but for a specific user. This broadcast
- * can only be sent to receivers that are part of the calling application. It
- * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
- * permission.
+ * Version of {@link #sendBroadcast(Intent)} that allows you to specify the
+ * user the broadcast will be sent to. This is not available to applications
+ * that are not pre-installed on the system image. Using it requires holding
+ * the INTERACT_ACROSS_USERS permission.
* @param intent The intent to broadcast
* @param user UserHandle to send the intent to.
* @see #sendBroadcast(Intent)
@@ -1129,10 +1133,10 @@
public abstract void sendBroadcastAsUser(Intent intent, UserHandle user);
/**
- * Same as {@link #sendBroadcast(Intent, String)}, but for a specific user. This broadcast
- * can only be sent to receivers that are part of the calling application. It
- * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
- * permission.
+ * Version of {@link #sendBroadcast(Intent, String)} that allows you to specify the
+ * user the broadcast will be sent to. This is not available to applications
+ * that are not pre-installed on the system image. Using it requires holding
+ * the INTERACT_ACROSS_USERS permission.
*
* @param intent The Intent to broadcast; all receivers matching this
* Intent will receive the broadcast.
@@ -1147,12 +1151,12 @@
String receiverPermission);
/**
- * Same as
- * {@link #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)},
- * but for a specific user. This broadcast
- * can only be sent to receivers that are part of the calling application. It
- * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
- * permission.
+ * Version of
+ * {@link #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)}
+ * that allows you to specify the
+ * user the broadcast will be sent to. This is not available to applications
+ * that are not pre-installed on the system image. Using it requires holding
+ * the INTERACT_ACROSS_USERS permission.
*
* <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
*
@@ -1261,11 +1265,10 @@
public abstract void removeStickyBroadcast(Intent intent);
/**
- * Same as {@link #sendStickyBroadcast(Intent)},
- * but for a specific user. This broadcast
- * can only be sent to receivers that are part of the calling application. It
- * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
- * permission.
+ * Version of {@link #sendStickyBroadcast(Intent)} that allows you to specify the
+ * user the broadcast will be sent to. This is not available to applications
+ * that are not pre-installed on the system image. Using it requires holding
+ * the INTERACT_ACROSS_USERS permission.
*
* @param intent The Intent to broadcast; all receivers matching this
* Intent will receive the broadcast, and the Intent will be held to
@@ -1277,12 +1280,12 @@
public abstract void sendStickyBroadcastAsUser(Intent intent, UserHandle user);
/**
- * Same as
- * {@link #sendStickyOrderedBroadcast(Intent, BroadcastReceiver, Handler, int, String, Bundle)
- * but for a specific user. This broadcast
- * can only be sent to receivers that are part of the calling application. It
- * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
- * permission.
+ * Version of
+ * {@link #sendStickyOrderedBroadcast(Intent, BroadcastReceiver, Handler, int, String, Bundle)}
+ * that allows you to specify the
+ * user the broadcast will be sent to. This is not available to applications
+ * that are not pre-installed on the system image. Using it requires holding
+ * the INTERACT_ACROSS_USERS permission.
*
* <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
*
@@ -1309,12 +1312,10 @@
Bundle initialExtras);
/**
- * Same as
- * {@link #sendStickyOrderedBroadcast(Intent, BroadcastReceiver, Handler, int, String, Bundle)
- * but for a specific user. This broadcast
- * can only be sent to receivers that are part of the calling application. It
- * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
- * permission.
+ * Version of {@link #removeStickyBroadcast(Intent)} that allows you to specify the
+ * user the broadcast will be sent to. This is not available to applications
+ * that are not pre-installed on the system image. Using it requires holding
+ * the INTERACT_ACROSS_USERS permission.
*
* <p>You must hold the {@link android.Manifest.permission#BROADCAST_STICKY}
* permission in order to use this API. If you do not hold that
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index 86a9392..f956bcf 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -30,12 +30,28 @@
* @hide
*/
interface IContentService {
- void registerContentObserver(in Uri uri, boolean notifyForDescendentsn,
- IContentObserver observer);
void unregisterContentObserver(IContentObserver observer);
+ /**
+ * Register a content observer tied to a specific user's view of the provider.
+ * @param userHandle the user whose view of the provider is to be observed. May be
+ * the calling user without requiring any permission, otherwise the caller needs to
+ * hold the INTERACT_ACROSS_USERS_FULL permission. Pseudousers USER_ALL and
+ * USER_CURRENT are properly handled.
+ */
+ void registerContentObserver(in Uri uri, boolean notifyForDescendants,
+ IContentObserver observer, int userHandle);
+
+ /**
+ * Notify observers of a particular user's view of the provider.
+ * @param userHandle the user whose view of the provider is to be notified. May be
+ * the calling user without requiring any permission, otherwise the caller needs to
+ * hold the INTERACT_ACROSS_USERS_FULL permission. Pseudousers USER_ALL
+ * USER_CURRENT are properly interpreted.
+ */
void notifyChange(in Uri uri, IContentObserver observer,
- boolean observerWantsSelfNotifications, boolean syncToNetwork);
+ boolean observerWantsSelfNotifications, boolean syncToNetwork,
+ int userHandle);
void requestSync(in Account account, String authority, in Bundle extras);
void cancelSync(in Account account, String authority);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index d3b8648..e8507bc 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2376,6 +2376,16 @@
public static final String ACTION_USER_SWITCHED =
"android.intent.action.USER_SWITCHED";
+ /**
+ * Broadcast sent to the system when a user's information changes. Carries an extra
+ * {@link #EXTRA_USER_HANDLE} to indicate which user's information changed.
+ * This is only sent to registered receivers, not manifest receivers. It is sent to the user
+ * whose information has changed.
+ * @hide
+ */
+ public static final String ACTION_USER_INFO_CHANGED =
+ "android.intent.action.USER_INFO_CHANGED";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Standard intent categories (see addCategory()).
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index 6c3cf99..166495b 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -205,6 +205,20 @@
}
/**
+ * @deprecated Renamed to {@link #getCreatorPackage()}.
+ */
+ @Deprecated
+ public String getTargetPackage() {
+ try {
+ return ActivityManagerNative.getDefault()
+ .getPackageForIntentSender(mTarget);
+ } catch (RemoteException e) {
+ // Should never happen.
+ return null;
+ }
+ }
+
+ /**
* Return the package name of the application that created this
* IntentSender, that is the identity under which you will actually be
* sending the Intent. The returned string is supplied by the system, so
@@ -213,7 +227,7 @@
* @return The package name of the PendingIntent, or null if there is
* none associated with it.
*/
- public String getTargetPackage() {
+ public String getCreatorPackage() {
try {
return ActivityManagerNative.getDefault()
.getPackageForIntentSender(mTarget);
@@ -232,7 +246,7 @@
* @return The uid of the PendingIntent, or -1 if there is
* none associated with it.
*/
- public int getTargetUid() {
+ public int getCreatorUid() {
try {
return ActivityManagerNative.getDefault()
.getUidForIntentSender(mTarget);
@@ -253,7 +267,7 @@
* @return The user handle of the PendingIntent, or null if there is
* none associated with it.
*/
- public UserHandle getTargetUserHandle() {
+ public UserHandle getCreatorUserHandle() {
try {
int uid = ActivityManagerNative.getDefault()
.getUidForIntentSender(mTarget);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 4784d7f..fd488ae 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2434,8 +2434,7 @@
* @param verificationCode either {@link PackageManager#VERIFICATION_ALLOW}
* or {@link PackageManager#VERIFICATION_REJECT}.
* @throws SecurityException if the caller does not have the
- * {@link android.Manifest.permission#PACKAGE_VERIFICATION_AGENT}
- * permission.
+ * PACKAGE_VERIFICATION_AGENT permission.
*/
public abstract void verifyPendingInstall(int id, int verificationCode);
@@ -2469,8 +2468,7 @@
* bounds value; namely, 0 or
* {@link PackageManager#MAXIMUM_VERIFICATION_TIMEOUT}.
* @throws SecurityException if the caller does not have the
- * {@link android.Manifest.permission#PACKAGE_VERIFICATION_AGENT}
- * permission.
+ * PACKAGE_VERIFICATION_AGENT permission.
*/
public abstract void extendVerificationTimeout(int id,
int verificationCodeAtTimeout, long millisecondsToDelay);
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 1a71bfb..3579977 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -22,6 +22,7 @@
/**
* Per-user state information about a package.
+ * @hide
*/
public class PackageUserState {
public boolean stopped;
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 653c5f3..0798913 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -19,6 +19,7 @@
import android.os.ParcelFileDescriptor;
import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
/**
* {@hide}
@@ -27,8 +28,8 @@
UserInfo createUser(in String name, int flags);
boolean removeUser(int userHandle);
void setUserName(int userHandle, String name);
- ParcelFileDescriptor setUserIcon(int userHandle);
- ParcelFileDescriptor getUserIcon(int userHandle);
+ void setUserIcon(int userHandle, in Bitmap icon);
+ Bitmap getUserIcon(int userHandle);
List<UserInfo> getUsers();
UserInfo getUserInfo(int userHandle);
void setGuestEnabled(boolean enable);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index cac1e07..392aff7 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -18,6 +18,7 @@
import com.android.internal.R;
import android.content.Context;
import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
import android.util.Log;
import java.util.List;
@@ -40,6 +41,7 @@
/**
* Returns whether the system supports multiple users.
* @return true if multiple users can be created, false if it is a single user device.
+ * @hide
*/
public boolean supportsMultipleUsers() {
return getMaxSupportedUsers() > 1;
@@ -55,8 +57,9 @@
}
/**
- * Returns the user name of the user making this call.
- * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+ * Returns the user name of the user making this call. This call is only
+ * available to applications on the system image; it requires the
+ * MANAGE_USERS permission.
* @return the user name
*/
public String getUserName() {
@@ -151,32 +154,30 @@
}
/**
- * Returns a file descriptor for the user's photo. PNG data can be written into this file.
+ * Sets the user's photo.
* @param userHandle the user for whom to change the photo.
- * @return a {@link ParcelFileDescriptor} to which to write the photo.
+ * @param icon the bitmap to set as the photo.
* @hide
*/
- public ParcelFileDescriptor setUserIcon(int userHandle) {
+ public void setUserIcon(int userHandle, Bitmap icon) {
try {
- return mService.setUserIcon(userHandle);
+ mService.setUserIcon(userHandle, icon);
} catch (RemoteException re) {
Log.w(TAG, "Could not set the user icon ", re);
- return null;
}
}
/**
* Returns a file descriptor for the user's photo. PNG data can be read from this file.
* @param userHandle the user whose photo we want to read.
- * @return a {@link ParcelFileDescriptor} from which to read the file, or null if there's no
- * photo.
+ * @return a {@link Bitmap} of the user's photo, or null if there's no photo.
* @hide
*/
- public ParcelFileDescriptor getUserIcon(int userHandle) {
+ public Bitmap getUserIcon(int userHandle) {
try {
return mService.getUserIcon(userHandle);
} catch (RemoteException re) {
- Log.w(TAG, "Could not set the user icon ", re);
+ Log.w(TAG, "Could not get the user icon ", re);
return null;
}
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a182234..68ce72f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5614,6 +5614,13 @@
"wifi_supplicant_scan_interval_ms";
/**
+ * The interval in milliseconds to scan at supplicant when p2p is connected
+ * @hide
+ */
+ public static final String WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS =
+ "wifi_scan_interval_p2p_connected_ms";
+
+ /**
* Whether the Wi-Fi watchdog is enabled.
*/
public static final String WIFI_WATCHDOG_ON = "wifi_watchdog_on";
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index f906e24..446a51e 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -733,13 +733,17 @@
*/
void checkEglErrors() {
if (isEnabled()) {
- int error = sEgl.eglGetError();
- if (error != EGL_SUCCESS) {
- // something bad has happened revert to
- // normal rendering.
- Log.w(LOG_TAG, "EGL error: " + GLUtils.getEGLErrorString(error));
- fallback(error != EGL11.EGL_CONTEXT_LOST);
- }
+ checkEglErrorsForced();
+ }
+ }
+
+ private void checkEglErrorsForced() {
+ int error = sEgl.eglGetError();
+ if (error != EGL_SUCCESS) {
+ // something bad has happened revert to
+ // normal rendering.
+ Log.w(LOG_TAG, "EGL error: " + GLUtils.getEGLErrorString(error));
+ fallback(error != EGL11.EGL_CONTEXT_LOST);
}
}
@@ -812,7 +816,9 @@
throw new RuntimeException("eglInitialize failed " +
GLUtils.getEGLErrorString(sEgl.eglGetError()));
}
-
+
+ checkEglErrorsForced();
+
sEglConfig = chooseEglConfig();
if (sEglConfig == null) {
// We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index c93da06..d6f63a7 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -832,7 +832,6 @@
sConfirmSafeVolumeDialog.dismiss();
}
sConfirmSafeVolumeDialog = new AlertDialog.Builder(mContext)
- .setTitle(android.R.string.dialog_alert_title)
.setMessage(com.android.internal.R.string.safe_media_volume_warning)
.setPositiveButton(com.android.internal.R.string.yes,
new DialogInterface.OnClickListener() {
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 90e85e6..fc04cd1 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -650,8 +650,7 @@
static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj) {
ScopedUtfChars name(env, nameObj);
- // TODO: pass the name to SF.
- sp<IBinder> token(SurfaceComposerClient::createDisplay());
+ sp<IBinder> token(SurfaceComposerClient::createDisplay(String8(name.c_str())));
return javaObjectForIBinder(env, token);
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0bc09aa..89d78b6 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -981,7 +981,7 @@
android:protectionLevel="dangerous"
android:label="@string/permlab_getTasks"
android:description="@string/permdesc_getTasks" />
- <!-- Allows an application to call APIs that allow it to do interactions
+ <!-- @hide Allows an application to call APIs that allow it to do interactions
across the users on the device, using singleton services and
user-targeted broadcasts. This permission is not available to
third party applications. -->
@@ -1000,7 +1000,7 @@
android:label="@string/permlab_interactAcrossUsersFull"
android:description="@string/permdesc_interactAcrossUsersFull" />
- <!-- Allows an application to call APIs that allow it to query and manage
+ <!-- @hide Allows an application to call APIs that allow it to query and manage
users on the device. This permission is not available to
third party applications. -->
<permission android:name="android.permission.MANAGE_USERS"
@@ -1769,7 +1769,7 @@
android:description="@string/permdesc_devicePower"
android:protectionLevel="signature" />
- <!-- Allows low-level access to tun tap driver -->
+ <!-- @hide Allows low-level access to tun tap driver -->
<permission android:name="android.permission.NET_TUNNELING"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="signature" />
@@ -1981,7 +1981,7 @@
android:protectionLevel="signature" />
<uses-permission android:name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE"/>
- <!-- Package verifier needs to have this permission before the PackageManager will
+ <!-- @hide Package verifier needs to have this permission before the PackageManager will
trust it to verify packages.
-->
<permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT"
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 3c0c0a7..7209e4e 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -299,8 +299,9 @@
with this component (by binding to a service for example) those processes will
always interact with the instance running for user 0. Enabling
single user mode forces "exported" of the component to be false, to
- help avoid introducing multi-user security bugs. You must hold the
- permission {@link android.Manifest.permission#INTERACT_ACROSS_USERS} in order
+ help avoid introducing multi-user security bugs. This feature is only
+ available to applications built in to the system image; you must hold the
+ permission INTERACT_ACROSS_USERS in order
to use this feature. This flag can only be used with services,
receivers, and providers; it can not be used with activities. -->
<attr name="singleUser" format="boolean" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 1a9a0a9..297e72a 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -292,6 +292,9 @@
<!-- Integer indicating wpa_supplicant scan interval in milliseconds -->
<integer translatable="false" name="config_wifi_supplicant_scan_interval">15000</integer>
+ <!-- Integer indicating wpa_supplicant scan interval when p2p is connected in milliseconds -->
+ <integer translatable="false" name="config_wifi_scan_interval_p2p_connected">60000</integer>
+
<!-- Integer indicating the framework scan interval in milliseconds. This is used in the scenario
where the chipset does not support background scanning (config_wifi_background_scan_suport
is false) to set up a periodic wake up scan so that the device can connect to a new access
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 56e5ce1..b904c60 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3890,7 +3890,7 @@
<!-- Message shown in dialog when user is attempting to set the music volume above the
recommended maximum level for headphones -->
<string name="safe_media_volume_warning" product="default">
- "Raise volume above the recommended level?"
+ "Raise volume above safe level?\nListening at high volume for long periods may damage your hearing."
</string>
<string name="kg_temp_back_string"> < </string> <!-- TODO: remove this -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index eb56d08..0360224 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -275,6 +275,7 @@
<java-symbol type="integer" name="config_ntpTimeout" />
<java-symbol type="integer" name="config_wifi_framework_scan_interval" />
<java-symbol type="integer" name="config_wifi_supplicant_scan_interval" />
+ <java-symbol type="integer" name="config_wifi_scan_interval_p2p_connected" />
<java-symbol type="integer" name="db_connection_pool_size" />
<java-symbol type="integer" name="db_journal_size_limit" />
<java-symbol type="integer" name="db_wal_autocheckpoint" />
diff --git a/core/tests/coretests/src/android/content/ObserverNodeTest.java b/core/tests/coretests/src/android/content/ObserverNodeTest.java
index 95b8465..1acff9c 100644
--- a/core/tests/coretests/src/android/content/ObserverNodeTest.java
+++ b/core/tests/coretests/src/android/content/ObserverNodeTest.java
@@ -23,6 +23,7 @@
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
+import android.os.UserHandle;
import android.test.AndroidTestCase;
public class ObserverNodeTest extends AndroidTestCase {
@@ -33,6 +34,8 @@
}
public void testUri() {
+ final int myUserHandle = UserHandle.myUserId();
+
ObserverNode root = new ObserverNode("");
Uri[] uris = new Uri[] {
Uri.parse("content://c/a/"),
@@ -48,21 +51,25 @@
int[] nums = new int[] {4, 7, 1, 4, 2, 2, 3, 3};
// special case
- root.addObserverLocked(uris[0], new TestObserver().getContentObserver(), false, root, 0, 0);
+ root.addObserverLocked(uris[0], new TestObserver().getContentObserver(), false, root,
+ 0, 0, myUserHandle);
for(int i = 1; i < uris.length; i++) {
- root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), true, root, 0, 0);
+ root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), true, root,
+ 0, 0, myUserHandle);
}
ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
for (int i = nums.length - 1; i >=0; --i) {
- root.collectObserversLocked(uris[i], 0, null, false, calls);
+ root.collectObserversLocked(uris[i], 0, null, false, myUserHandle, calls);
assertEquals(nums[i], calls.size());
calls.clear();
}
}
public void testUriNotNotify() {
+ final int myUserHandle = UserHandle.myUserId();
+
ObserverNode root = new ObserverNode("");
Uri[] uris = new Uri[] {
Uri.parse("content://c/"),
@@ -77,13 +84,14 @@
int[] nums = new int[] {7, 1, 3, 3, 1, 1, 1, 1};
for(int i = 0; i < uris.length; i++) {
- root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), false, root, 0, 0);
+ root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), false, root,
+ 0, 0, myUserHandle);
}
ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
for (int i = uris.length - 1; i >=0; --i) {
- root.collectObserversLocked(uris[i], 0, null, false, calls);
+ root.collectObserversLocked(uris[i], 0, null, false, myUserHandle, calls);
assertEquals(nums[i], calls.size());
calls.clear();
}
diff --git a/docs/html/guide/faq/security.jd b/docs/html/guide/faq/security.jd
index 52ee0d9..a6e07c8 100644
--- a/docs/html/guide/faq/security.jd
+++ b/docs/html/guide/faq/security.jd
@@ -57,9 +57,7 @@
<p>We appreciate researchers practicing responsible disclosure by emailing us
with a detailed summary of the issue and keeping the issue confidential while
users are at risk. In return, we will make sure to keep the researcher informed
-of our progress in issuing a fix and will properly credit the reporter(s) when
-we provide the patch. We will always move swiftly to mitigate or fix an
-externally-reported flaw and provide updates to users. </p>
+of our progress in issuing a fix. </p>
<a name="informed" id="informed"></a><h2>How can I stay informed about Android security?</h2>
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
index e7f98de..ed9bb97 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
@@ -98,7 +98,9 @@
mWakeLock.acquire();
}
- public void onStop(Bundle icicle) {
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
mWakeLock.release();
}
diff --git a/media/tests/contents/media_api/music/sine_200+1000Hz_44K_mo.wav b/media/tests/contents/media_api/music/sine_200+1000Hz_44K_mo.wav
old mode 100755
new mode 100644
index 312b6fb..24c2a0d
--- a/media/tests/contents/media_api/music/sine_200+1000Hz_44K_mo.wav
+++ b/media/tests/contents/media_api/music/sine_200+1000Hz_44K_mo.wav
Binary files differ
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 7cc5dec..a0ae9e3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -317,13 +317,14 @@
boolean backedUpDataChanged = false;
String property = null, table = uri.getPathSegments().get(0);
+ final boolean isGlobal = table.equals(TABLE_GLOBAL);
if (table.equals(TABLE_SYSTEM)) {
property = Settings.System.SYS_PROP_SETTING_VERSION + '_' + userHandle;
backedUpDataChanged = true;
} else if (table.equals(TABLE_SECURE)) {
property = Settings.Secure.SYS_PROP_SETTING_VERSION + '_' + userHandle;
backedUpDataChanged = true;
- } else if (table.equals(TABLE_GLOBAL)) {
+ } else if (isGlobal) {
property = Settings.Global.SYS_PROP_SETTING_VERSION; // this one is global
backedUpDataChanged = true;
}
@@ -342,8 +343,9 @@
String notify = uri.getQueryParameter("notify");
if (notify == null || "true".equals(notify)) {
- getContext().getContentResolver().notifyChange(uri, null);
- if (LOCAL_LOGV) Log.v(TAG, "notifying: " + uri);
+ final int notifyTarget = isGlobal ? UserHandle.USER_ALL : userHandle;
+ getContext().getContentResolver().notifyChange(uri, null, true, notifyTarget);
+ if (LOCAL_LOGV) Log.v(TAG, "notifying for " + notifyTarget + ": " + uri);
} else {
if (LOCAL_LOGV) Log.v(TAG, "notification suppressed: " + uri);
}
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 8fe28a3..47ec243 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -667,8 +667,12 @@
private void addWidget(int appId) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
AppWidgetProviderInfo appWidgetInfo = appWidgetManager.getAppWidgetInfo(appId);
- AppWidgetHostView view = getAppWidgetHost().createView(mContext, appId, appWidgetInfo);
- addWidget(view);
+ if (appWidgetInfo != null) {
+ AppWidgetHostView view = getAppWidgetHost().createView(mContext, appId, appWidgetInfo);
+ addWidget(view);
+ } else {
+ Log.w(TAG, "AppWidgetInfo was null; not adding widget id " + appId);
+ }
}
private void maybePopulateWidgets() {
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index f4ad756..f960833 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -353,7 +353,7 @@
while (it.hasNext()) {
Alarm alarm = it.next();
- if (UserHandle.getUserId(alarm.operation.getTargetUid()) == userHandle) {
+ if (UserHandle.getUserId(alarm.operation.getCreatorUid()) == userHandle) {
it.remove();
}
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index db042b5..ce5424b 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -11438,7 +11438,7 @@
// Add the new results to the existing results, tracking
// and de-dupping single user receivers.
for (int i=0; i<newReceivers.size(); i++) {
- ResolveInfo ri = receivers.get(i);
+ ResolveInfo ri = newReceivers.get(i);
if ((ri.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
ComponentName cn = new ComponentName(
ri.activityInfo.packageName, ri.activityInfo.name);
diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java
index 1b6ff7a..b0af081 100644
--- a/services/java/com/android/server/am/BroadcastQueue.java
+++ b/services/java/com/android/server/am/BroadcastQueue.java
@@ -965,12 +965,12 @@
if (!printed) {
if (needSep) {
pw.println();
- needSep = false;
}
+ needSep = true;
printed = true;
pw.println(" Active broadcasts [" + mQueueName + "]:");
}
- pw.println(" Broadcast #" + i + ":");
+ pw.println(" Active Broadcast " + mQueueName + " #" + i + ":");
br.dump(pw, " ");
}
printed = false;
@@ -985,9 +985,10 @@
pw.println();
}
needSep = true;
+ printed = true;
pw.println(" Active ordered broadcasts [" + mQueueName + "]:");
}
- pw.println(" Ordered Broadcast #" + i + ":");
+ pw.println(" Active Ordered Broadcast " + mQueueName + " #" + i + ":");
mOrderedBroadcasts.get(i).dump(pw, " ");
}
if (dumpPackage == null || (mPendingBroadcast != null
@@ -1023,7 +1024,8 @@
printed = true;
}
if (dumpAll) {
- pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
+ pw.print(" Historical Broadcast " + mQueueName + " #");
+ pw.print(i); pw.println(":");
r.dump(pw, " ");
} else {
if (i >= 50) {
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
index 690d7c9..be86628 100644
--- a/services/java/com/android/server/pm/UserManagerService.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -29,6 +29,8 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.os.Binder;
import android.os.Environment;
import android.os.FileUtils;
@@ -188,30 +190,35 @@
writeUserLocked(info);
}
}
+ sendUserInfoChangedBroadcast(userId);
}
@Override
- public ParcelFileDescriptor setUserIcon(int userId) {
+ public void setUserIcon(int userId, Bitmap bitmap) {
checkManageUsersPermission("update users");
synchronized (mPackagesLock) {
UserInfo info = mUsers.get(userId);
- if (info == null) return null;
- ParcelFileDescriptor fd = openIconBitmapLocked(info, true /* write */);
- if (fd != null) {
- writeUserLocked(info);
- }
- return fd;
+ if (info == null) return;
+ writeBitmapLocked(info, bitmap);
+ writeUserLocked(info);
}
+ sendUserInfoChangedBroadcast(userId);
+ }
+
+ private void sendUserInfoChangedBroadcast(int userId) {
+ Intent changedIntent = new Intent(Intent.ACTION_USER_INFO_CHANGED);
+ changedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+ changedIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ mContext.sendBroadcastAsUser(changedIntent, new UserHandle(userId));
}
@Override
- public ParcelFileDescriptor getUserIcon(int userId) {
+ public Bitmap getUserIcon(int userId) {
checkManageUsersPermission("read users");
synchronized (mPackagesLock) {
UserInfo info = mUsers.get(userId);
if (info == null || info.iconPath == null) return null;
- ParcelFileDescriptor fd = openIconBitmapLocked(info, false /* read */);
- return fd;
+ return BitmapFactory.decodeFile(info.iconPath);
}
}
@@ -289,7 +296,7 @@
}
}
- private ParcelFileDescriptor openIconBitmapLocked(UserInfo info, boolean toWrite) {
+ private void writeBitmapLocked(UserInfo info, Bitmap bitmap) {
try {
File dir = new File(mUsersDir, Integer.toString(info.id));
File file = new File(dir, USER_PHOTO_FILENAME);
@@ -300,16 +307,18 @@
FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
-1, -1);
}
- ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
- toWrite ? MODE_CREATE|MODE_READ_WRITE : MODE_READ_WRITE);
- if (toWrite) {
+ FileOutputStream os;
+ if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, os = new FileOutputStream(file))) {
info.iconPath = file.getAbsolutePath();
}
- return fd;
+ try {
+ os.close();
+ } catch (IOException ioe) {
+ // What the ... !
+ }
} catch (FileNotFoundException e) {
Slog.w(LOG_TAG, "Error setting photo for user ", e);
}
- return null;
}
/**
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 9fe1c60..4aa092b 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -75,6 +75,7 @@
import android.util.Log;
import android.util.LruCache;
+import com.android.internal.R;
import com.android.internal.app.IBatteryStats;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
@@ -112,6 +113,7 @@
private ConnectivityManager mCm;
private final boolean mP2pSupported;
+ private final AtomicBoolean mP2pConnected = new AtomicBoolean(false);
private final String mPrimaryDeviceType;
/* Scan results handling */
@@ -595,16 +597,16 @@
mScanIntent = PendingIntent.getBroadcast(mContext, SCAN_REQUEST, scanIntent, 0);
mDefaultFrameworkScanIntervalMs = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_wifi_framework_scan_interval);
+ R.integer.config_wifi_framework_scan_interval);
mDriverStopDelayMs = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_wifi_driver_stop_delay);
+ R.integer.config_wifi_driver_stop_delay);
mBackgroundScanSupported = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_wifi_background_scan_support);
+ R.bool.config_wifi_background_scan_support);
mPrimaryDeviceType = mContext.getResources().getString(
- com.android.internal.R.string.config_wifi_p2p_device_type);
+ R.string.config_wifi_p2p_device_type);
mUserWantsSuspendOpt.set(Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1);
@@ -2011,6 +2013,10 @@
replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_FAILED,
WifiManager.BUSY);
break;
+ case WifiP2pService.P2P_CONNECTION_CHANGED:
+ NetworkInfo info = (NetworkInfo) message.obj;
+ mP2pConnected.set(info.isConnected());
+ break;
default:
loge("Error! unhandled message" + message);
break;
@@ -2408,7 +2414,7 @@
mNetworkInfo.setIsAvailable(true);
int defaultInterval = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_wifi_supplicant_scan_interval);
+ R.integer.config_wifi_supplicant_scan_interval);
mSupplicantScanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(),
Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS,
@@ -3486,7 +3492,7 @@
* The scans are useful to notify the user of the presence of an open network.
* Note that these are not wake up scans.
*/
- if (mWifiConfigStore.getConfiguredNetworks().size() == 0) {
+ if (!mP2pConnected.get() && mWifiConfigStore.getConfiguredNetworks().size() == 0) {
sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);
}
@@ -3497,6 +3503,7 @@
boolean ret = HANDLED;
switch (message.what) {
case CMD_NO_NETWORKS_PERIODIC_SCAN:
+ if (mP2pConnected.get()) break;
if (message.arg1 == mPeriodicScanToken &&
mWifiConfigStore.getConfiguredNetworks().size() == 0) {
sendMessage(CMD_START_SCAN);
@@ -3557,6 +3564,21 @@
/* Handled in parent state */
ret = NOT_HANDLED;
break;
+ case WifiP2pService.P2P_CONNECTION_CHANGED:
+ NetworkInfo info = (NetworkInfo) message.obj;
+ mP2pConnected.set(info.isConnected());
+ if (mP2pConnected.get()) {
+ int defaultInterval = mContext.getResources().getInteger(
+ R.integer.config_wifi_scan_interval_p2p_connected);
+ long scanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(),
+ Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS,
+ defaultInterval);
+ mWifiNative.setScanInterval((int) scanIntervalMs/1000);
+ } else if (mWifiConfigStore.getConfiguredNetworks().size() == 0) {
+ if (DBG) log("Turn on scanning after p2p disconnected");
+ sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
+ ++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);
+ }
default:
ret = NOT_HANDLED;
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index edd1dac..35dd764 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -137,18 +137,6 @@
/* Idle time after a peer is gone when the group is torn down */
private static final int GROUP_IDLE_TIME_S = 5;
- /**
- * Delay between restarts upon failure to setup connection with supplicant
- */
- private static final int P2P_RESTART_INTERVAL_MSECS = 5000;
-
- /**
- * Number of times we attempt to restart p2p
- */
- private static final int P2P_RESTART_TRIES = 5;
-
- private int mP2pRestartCount = 0;
-
private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE;
/* Delayed message to timeout group creation */
@@ -159,6 +147,9 @@
/* User rejected a peer request */
private static final int PEER_CONNECTION_USER_REJECT = BASE + 3;
+ /* Commands to the WifiStateMachine */
+ public static final int P2P_CONNECTION_CHANGED = BASE + 11;
+
private final boolean mP2pSupported;
private WifiP2pDevice mThisDevice = new WifiP2pDevice();
@@ -1597,6 +1588,8 @@
intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, new WifiP2pInfo(mWifiP2pInfo));
intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo));
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+ mWifiChannel.sendMessage(WifiP2pService.P2P_CONNECTION_CHANGED,
+ new NetworkInfo(mNetworkInfo));
}
private void sendP2pPersistentGroupsChangedBroadcast() {